メインコンテンツまでスキップ

「Binary Hacks Rebooted」を読んだメモ

· 約7分

MEMO

shebang

  • interpreter 以外のプログラムを指定することもできるらしい
% cat test.sh
───────┬──────────────────────────────────────────
│ File: test.sh
───────┼──────────────────────────────────────────
1 │ #!/bin/ls -al
2 │ echo "Hello World"
───────┴──────────────────────────────────────────

% ./test.sh
-rwxr-xr-x 1 mmori mmori 33 Mar 25 18:35 ./test.sh
  • 引数は複数渡そうとしても無理っぽい
% cat test.sh
───────┬──────────────────────────────────
│ File: test.sh
───────┼──────────────────────────────────
1 │ #!/bin/ls --all -l
2 │ echo "Hello World"
───────┴──────────────────────────────────

% ./test.sh
/bin/ls: unrecognized option '--all -l'
Try '/bin/ls --help' for more information.
	/* Is there an optional argument? */
i_arg = NULL;
i_sep = next_terminator(i_name, i_end);
if (i_sep && (*i_sep != '\0'))
i_arg = next_non_spacetab(i_sep, i_end);
  • よく #!/bin/env python3 とかがあるけどこれのおかげで動いている

  • 色々飛ばして最後は open_exec で実行

	/*
* OK, now restart the process with the interpreter's dentry.
*/
file = open_exec(i_name);
if (IS_ERR(file))
return PTR_ERR(file);

binfmt_misc

# binfmt
sudo pacman -S qemu-user-static-binfmt binfmt-wasm
# Compilers
sudo pacman -S aarch64-linux-gnu-gcc aarch64-linux-gnu-glibc
% ls /proc/sys/fs/binfmt_misc/
DOSWin qemu-alpha qemu-hexagon qemu-m68k qemu-mips qemu-mipsel qemu-or1k qemu-ppc64le qemu-s390x qemu-sparc qemu-xtensa status
qemu-aarch64 qemu-arm qemu-hppa qemu-microblaze qemu-mips64 qemu-mipsn32 qemu-ppc qemu-riscv32 qemu-sh4 qemu-sparc32plus qemu-xtensaeb wasip1
qemu-aarch64_be qemu-armeb qemu-loongarch64 qemu-microblazeel qemu-mips64el qemu-mipsn32el qemu-ppc64 qemu-riscv64 qemu-sh4eb qemu-sparc64 register wasip2

% cat /proc/sys/fs/binfmt_misc/qemu-aarch64
───────┬───────────────────────────────────────────────
│ File: /proc/sys/fs/binfmt_misc/qemu-aarch64
───────┼───────────────────────────────────────────────
1 │ enabled
2 │ interpreter /usr/bin/qemu-aarch64-static
3 │ flags: PF
4 │ offset 0
5 │ magic 7f454c460201010000000000000000000200b700
6 │ mask ffffffffffffff00fffffffffffffffffeffffff
───────┴───────────────────────────────────────────────

% aarch64-linux-gnu-gcc hello.c -static -o hello-aarch64

% xxd -l 0x20 hello-aarch64
00000000: 7f45 4c46 0201 0103 0000 0000 0000 0000 .ELF............
00000010: 0200 b700 0100 0000 c006 4000 0000 0000 ..........@.....
% cat /proc/sys/fs/binfmt_misc/wasip1
───────┬─────────────────────────────────────────────
│ File: /proc/sys/fs/binfmt_misc/wasip1
───────┼─────────────────────────────────────────────
1 │ enabled
2 │ interpreter /usr/bin/binfmt-wasmtime-wrapper
3 │ flags:
4 │ offset 0
5 │ magic 0061736d01000000
───────┴─────────────────────────────────────────────

% cat /proc/sys/fs/binfmt_misc/wasip2
───────┬─────────────────────────────────────────────
│ File: /proc/sys/fs/binfmt_misc/wasip2
───────┼─────────────────────────────────────────────
1 │ enabled
2 │ interpreter /usr/bin/binfmt-wasmtime-wrapper
3 │ flags:
4 │ offset 0
5 │ magic 0061736d0d000100
───────┴─────────────────────────────────────────────

% rustc --target wasm32-wasip1 main.rs -o hello-wasm

% rustc --target wasm32-wasip2 main.rs -o hello-wasmp2

% xxd -l 0x20 hello-wasm
00000000: 0061 736d 0100 0000 016c 0f60 0000 6001 .asm.....l.`..`.
00000010: 7f00 6002 7f7f 017f 6001 7f01 7f60 037f ..`.....`....`..

% xxd -l 0x20 hello-wasmp2
00000000: 0061 736d 0d00 0100 0724 0142 0401 6f02 .asm.....$.B..o.
00000010: 7373 0170 0001 4000 0001 0400 0f67 6574 ss.p..@......get
  • cargo で aarch64 用のバイナリを作るときには .cargo/config.toml でも設定できる
% cat .cargo/config.toml
───────┬─────────────────────────────────────────────────
│ File: .cargo/config.toml
───────┼─────────────────────────────────────────────────
1 │ [target.aarch64-unknown-linux-gnu]
2 │ linker = "aarch64-linux-gnu-gcc"
3 │ rustflags = ["-C", "target-feature=+crt-static"]
───────┴─────────────────────────────────────────────────

CRIU

  • /proc/sys/kernel/ns_last_pid は CRIU の開発者が追加したらしい
  • criu-ns を使うと PID の namespace を分けて重複を避けることができる

Unikernel

# ディストリビューションごとの package manager を使ってくれる
curl -sSfL https://get.kraftkit.sh | sh
cd workspace

# Create Kraftfile
cat << EOF | tee Kraftfile
spec: v0.6

name: template

unikraft: stable

targets:
- qemu/x86_64
EOF

# Config
kraft menu

# Create Makefile
cat << EOF | tee Makefile
$(eval $(call addlib,apphelloworld))

APPHELLOWORLD_SRCS-y += $(APPHELLOWORLD_BASE)/main.c
EOF

# main.c
cat << EOF | tee main.c
#include <stdio.h>
#include <unistd.h>

int main(void) {
printf("Hello, Kernel World!\n");
for (;;) {}
printf("Can't reach here\n");

return 0;
}
EOF

# Build
kraft build

# Run
kraft run
% kraft build
[+] updating index... done! [6.3s]
[?] project already configured, are you sure you want to rerun the configure step: [Y/n]
[+] configuring template (qemu/x86_64) ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• 100% [1.3s]
[+] building template (qemu/x86_64) ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• 100% [3.7s]

[●] Build completed successfully!

└─ kernel: .unikraft/build/template_qemu-x86_64 (242 kB)

Learn how to package your unikernel with: kraft pkg --help
kraft build 4.37s user 2.42s system 49% cpu 13.588 total

% kraft run
i using arch=x86_64 plat=qemu
o. .o _ _ __ _
Oo Oo ___ (_) | __ __ __ _ ' _) :_
oO oO ' _ `| | |/ / _)' _` | |_| _)
oOo oOO| | | | | (| | | (_) | _) :_
OoOoO ._, ._:_:_,\_._, .__,_:_, \___)
Helene 0.18.0
Hello, Kernel World!

% ps ax | grep qemu
2896210 ? Sl 0:14 qemu-system-x86_64 -cpu host,+x2apic,-pmu -daemonize -device pvpanic -display none -enable-kvm -kernel $WORKDIR/.unikraft/build/template_qemu-x86_64 -machine pc,accel=kvm -m size=64M -monitor unix:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/mon.sock,server,nowait -name 0d3aa028c089 -nographic -no-reboot -S -parallel none -pidfile $HOME/.local/share/kraftkit/runtime/0d3aa028c089/machine.pid -qmp unix:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/ctrl.sock,server,nowait -qmp unix:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/evnt.sock,server,nowait -rtc base=utc -serial file:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/vm.log -smp cpus=1,threads=1,sockets=1 -vga none

sleep 関数を呼ぼうとしたら build でこけた。今回はテストなので一旦無視する

% kraft build
[+] updating index... done! [6.3s]
[?] project already configured, are you sure you want to rerun the configure step: [Y/n]
[+] configuring template (qemu/x86_64) ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• 100% [1.2s]
<!> building template (qemu/x86_64) •• 2% [4.1s]
W make: hostname: No such file or directory
i LN Makefile
W make[1]: hostname: No such file or directory
W which: no time in ($HOME/.cargo/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor
i CP config
i GEN libuklibid: libraries.in.new
W make: hostname: No such file or directory
W make[1]: hostname: No such file or directory
W which: no time in ($HOME/.cargo/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor
W make: hostname: No such file or directory
i LN Makefile
W make[1]: hostname: No such file or directory
W which: no time in ($HOME/.cargo/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor
i CP config
i GEN libuklibid: libraries.in.new
i CP libuklibid: libraries.in
W $WORKDIR/main.c: In function ‘main’:
W $WORKDIR/main.c:6:9: error: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
W 6 | sleep(10);
W | ^~~~~
W make[1]: *** [$WORKDIR/.unikraft/unikraft/support/build/Makefile.build:27: $HOME/workspace/binary_hacks_rebooted/uniker
i CC apphelloworld: main.o
W make: *** [Makefile:1175: sub-make] Error 2

E could not complete build: build failed: exit status 2
kraft build 4.75s user 2.70s system 36% cpu 20.281 total

bpftrace

https://github.com/bpftrace/bpftrace

% sudo bpftrace tools/bashreadline.bt
Attaching 3 probes...
Tracing bash commands... Hit Ctrl-C to end.
TIME PID COMMAND
09:41:34 3091887 ls
09:41:42 3091887 echo hello
09:41:48 3091887 df -h
^C
% sudo bpftrace tools/cpuwalk.bt
Attaching 2 probes...
Sampling CPU at 99hz... Hit Ctrl-C to end.
^C

@cpu:
[0, 1) 17 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[1, 2) 18 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[2, 3) 22 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[3, 4) 19 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[4, 5) 7 |@@@@@@@@@@@@@ |
[5, 6) 5 |@@@@@@@@@ |
[6, 7) 18 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[7, 8) 15 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[8, 9) 1 |@ |
[9, 10) 9 |@@@@@@@@@@@@@@@@@ |
[10, 11) 14 |@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[11, 12) 20 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[12, 13) 12 |@@@@@@@@@@@@@@@@@@@@@@@ |
[13, 14) 17 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[14, 15) 15 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[15, 16) 27 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|

Meltdown/Spectre

https://github.com/kianenigma/meltdown-spectre/blob/master/meltdown-spectre/main-meltdown.c

数値表現

https://gigazine.net/news/20250217-android-calclator-app/

「RISC-V で学ぶコンピュータアーキテクチャ完全入門」を読んだメモ

· 約7分

MEMO

Verilog

RISC-V

パイプライン

分岐予測

  • 本来であれば分岐命令が実行されて次のPCが決まるまで (Execution stage の完了まで) 待たなければならないため、他の pipeline が stall する

    • 分岐先を予測すれば stall を回避して先に instruction fetch できる
  • 分岐予測の種類

    • ① 分岐命令かどうかの予測
    • ② 飛び先アドレスの予測
      • ⇒ Branch Target Buffer (BTB) を用いる
      • 分岐命令のアドレスジャンプ先のアドレスを保持したテーブルがあればいい ← このテーブルが BTB
      • 実行時に PC の下位ビットをインデックスとして BTB のエントリにアクセス
      • エントリの分岐アドレスが PC と一致すればジャンプ先アドレスを取り出す
    • ③ 分岐結果の予測
      • ⇒ Pattern History Table (PHT) を用いる
      • 分岐履歴を保持しておいて,その履歴から分岐の結果を予測
      • BTB と同じように PC の下位ビットをインデックスとして PHT にアクセス
      • PHT には分岐の結果が格納されているため、これをもとに各分岐命令ごとの結果を予測
  • PHT の履歴をどのように記録していくかのアルゴリズムによって性能は変わる

    • PHT が 1 bit で一つ前の結果を記録する
    • bimodal 分岐予測
    • gshare 分岐予測
  • bimodal 分岐予測

    • 2 bit のカウンタを用いて分岐の結果を記録
      • 00: weak not taken
      • 01: weak taken
      • 10: strong not taken
      • 11: strong taken
    • 上位ビットが 1 ならば成立と予測
    • 実際に分岐が成立した場合はカウンタをインクリメントし、成立しなかった場合はデクリメント
  • gshare 分岐予測

    • 過去 n 回の分岐履歴を保存して予測する → Branch History Register (BHR)
    • PC と n bit の BHR を XOR してインデックスを生成
    • そのインデックスを用いて bimoal 分岐予測と同じように予測を行う

キャッシュ

  • メインメモリへのアクセスはどうしても遅いので、容量は小さくていいので高速なメモリを CPU に持たせる
  • DRAM を使おうとすると遅延が大きく、読み書きするたびに後続の処理を stall させる必要が出てしまう
  • ダイレクトマップ方式
    • 分岐予測と同じように PC の下位ビットをインデックスとして命令キャッシュにアクセス
    • PC とキャッシュのタグが一致 (ヒット) したらメインメモリにアクセスせずに命令を取り出す
  • キャッシュラインを使用することで空間的局所性を利用
    • あるアドレスを読み込んだときにその周辺のアドレスも読み込む
  • n way セットアソシアティブキャッシュ
    • index が衝突した場合にダイレクトマップでは1つしかキャッシュラインを使えないが、n way ならば n 個のキャッシュラインを使える
    • n 個のキャッシュテーブルがあるイメージ。n が多すぎると hit 確認でクリティカルパスが長くなり遅延が増える
  • キャッシュは命令だけでなくデータキャッシュもある
    • データキャッシュは読み書きが発生するため、メインメモリとの同期も必要
    • Write Through/Write Back
    • メインメモリへの書き込みは遅いので書き込みが終わるまで stall するのは避けたい
    • Write Buffer に書き込んでおいて、メインメモリへの書き込みはメモリコントローラに任せる
    • Write Buffer が溢れた場合やメモリからの読み込みが発生した場合はメモリコントローラがプロセッサを stall させる

Vivado

  • flatpak で install すると楽
flatpak install com.github.corna.Vivado
  • 事前にアカウントの作成はする必要がある

  • バージョンによって名前が違いそうだが、ML edition は特定のボードを除いて無料で使用できる

  • flatpak はサンドボックス環境で動作していてアクセス権限が絞られている

  • home ディレクトリはアクセス権があったほうがいいので設定を変更する

flatpak override com.github.corna.Vivado --filesystem=home
% flatpak info --show-permissions com.github.corna.Vivado
[Context]
shared=network;ipc;
sockets=x11;
devices=all;
filesystems=xdg-documents;xdg-desktop;home;xdg-download;~/.Xilinx:create;
persistent=.;

[Session Bus Policy]
org.gnome.SessionManager=talk

[Environment]
LD_LIBRARY_PATH=/app/lib
TERMINFO=/app/share/terminfo
LC_ALL=en_US.UTF-8
  • board の driver がない場合に Hardware Manager の auto connect ができないので、下記でドライバをインストールする
cd $HOME/.var/app/com.github.corna.Vivado/data/xilinx-install/Vivado/2024.2/data/xicom/cable_drivers/lin64/install_script/install_drivers
sudo ./install_drivers
% sudo ./install_drivers
[sudo] password for mmori:
INFO: Installing cable drivers.
INFO: Script name = ./install_drivers
INFO: HostName = strix
INFO: RDI_BINROOT= .
INFO: Current working dir = /home/mmori/.var/app/com.github.corna.Vivado/data/xilinx-install/Vivado/2024.2/data/xicom/cable_drivers/lin64/install_script/install_drivers
INFO: Kernel version = 6.6.64-1-lts.
INFO: Arch = x86_64.
Successfully installed Digilent Cable Drivers
--File /etc/udev/rules.d/52-xilinx-ftdi-usb.rules does not exist.
--File version of /etc/udev/rules.d/52-xilinx-ftdi-usb.rules = 0000.
--Updating rules file.
--File /etc/udev/rules.d/52-xilinx-pcusb.rules does not exist.
--File version of /etc/udev/rules.d/52-xilinx-pcusb.rules = 0000.
--Updating rules file.

INFO: Digilent Return code = 0
INFO: Xilinx Return code = 0
INFO: Xilinx FTDI Return code = 0
INFO: Return code = 0
INFO: Driver installation successful.
CRITICAL WARNING: Cable(s) on the system must be unplugged then plugged back in order for the driver scripts to update the cables.

「入門 監視 ― モダンなモニタリングのためのデザインパターン」を読んだメモ

· 約19分

Memo

アンチパターン・デザインパターン

  • 監視設定の自動化
  • json などの構造化ログでメトリクスを収集すれば、その後の自動化が楽になる(場合による)
  • 高い SLA を守るためにはその分高頻度のメトリクス収集が必要
  • ユーザ視点の監視
  • 可能な限り SaaS を使う。コスト・効果ともに優れている場合が多い

アラート

  • 敏感すぎる・鈍感すぎるアラートにならないようにアラートの削除とチューニング
  • 自動復旧できないか?
  • インシデント対応の役割分担
    • 現場指揮官、起こったことの記録者、調整役、インシデント対応者
    • (実際にこれを分けるのは難しそう)
  • PagerDuty Incident Response

統計

  • パーセンタイルの理解が間違ってた…

ビジネスの監視

フロントエンド監視・アプリケーション監視

サーバ監視

メトリクス収集ツールについて

  • 紹介されていた中では collectd, telegraf あたりが良さそう

  • collectd

    • プラグインでカスタムメトリクスを収集できるが、telegraf などのほうが柔軟?
    • パフォーマンスは良さそう
  • telegraf

    • プラグインが豊富で様々なデータソースからメトリクスを収集できる
    • リソース消費が多い?
  • Diamond

    • カスタムメトリクスを収集できる
    • Python 製でパフォーマンスが若干劣る?
    • あまりメンテナンスされていなさそう

CPU

  • top などで確認できる
  • 内部的には /proc/stat からのデータ取得
cat /proc/stat
cpu  33413 59 13366 2018394 1458 2262 687 0 0 0
cpu0 1973 2 801 126259 81 91 66 0 0 0
cpu1 2106 3 711 126291 104 68 37 0 0 0
cpu2 2189 5 806 126152 102 65 29 0 0 0
cpu3 1875 1 791 126367 134 69 35 0 0 0
cpu4 2452 22 930 126026 69 69 29 0 0 0
cpu5 2173 0 773 126261 66 60 26 0 0 0
cpu6 2029 4 669 126380 67 89 59 0 0 0
cpu7 2005 0 780 126315 114 76 57 0 0 0
cpu8 1655 1 1575 124644 93 1199 160 0 0 0
cpu9 2204 0 1125 125957 70 70 28 0 0 0
cpu10 1919 4 705 126452 62 65 28 0 0 0
cpu11 2151 0 847 126234 103 70 26 0 0 0
cpu12 1979 3 674 126485 97 66 26 0 0 0
cpu13 2756 1 684 125664 119 65 25 0 0 0
cpu14 2115 3 697 126376 73 64 24 0 0 0
cpu15 1826 1 790 126523 96 70 25 0 0 0
intr 2023571 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 3805 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45306 60782 0 0 0 0 0 0 0 0 0 45 16562 587 133165 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 5771496
btime 1713664320
processes 16869
procs_running 2
procs_blocked 0
softirq 1061126 57397 66610 143 41034 44699 0 7992 508718 45 334488

Memory

  • free などで確認
    • buff は FS のメタデータのキャッシュ
    • cache はデータ本体のキャッシュ
    • shared は多分共有ライブラリなど
% free -h
total used free shared buff/cache available
Mem: 31Gi 3.6Gi 24Gi 106Mi 3.0Gi 27Gi
Swap: 4.0Gi 0B 4.0Gi
  • 内部的には /proc/meminfo からのデータ取得
cat /proc/meminfo
MemTotal:       32676436 kB
MemFree: 26243212 kB
MemAvailable: 28892088 kB
Buffers: 3212 kB
Cached: 3081776 kB
SwapCached: 0 kB
Active: 4194420 kB
Inactive: 1483412 kB
Active(anon): 2706408 kB
Inactive(anon): 0 kB
Active(file): 1488012 kB
Inactive(file): 1483412 kB
Unevictable: 3136 kB
Mlocked: 48 kB
SwapTotal: 4194300 kB
SwapFree: 4194300 kB
Zswap: 0 kB
Zswapped: 0 kB
Dirty: 272 kB
Writeback: 0 kB
AnonPages: 2585280 kB
Mapped: 960064 kB
Shmem: 113560 kB
KReclaimable: 85464 kB
Slab: 231872 kB
SReclaimable: 85464 kB
SUnreclaim: 146408 kB
KernelStack: 18544 kB
PageTables: 44560 kB
SecPageTables: 0 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 20532516 kB
Committed_AS: 12818284 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 170084 kB
VmallocChunk: 0 kB
Percpu: 12352 kB
HardwareCorrupted: 0 kB
AnonHugePages: 712704 kB
ShmemHugePages: 0 kB
ShmemPmdMapped: 0 kB
FileHugePages: 374784 kB
FilePmdMapped: 18432 kB
CmaTotal: 0 kB
CmaFree: 0 kB
Unaccepted: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB
DirectMap4k: 959096 kB
DirectMap2M: 8284160 kB
DirectMap1G: 25165824 kB
  • OOMKiller のログを監視するのも大切

Network の監視

  • ifconfig や ip コマンドで確認
  • /proc/net/dev からのデータ取得

Disk の監視

  • iostat や df などで確認
iostat
Linux 6.8.6-arch1-1 (strix) 	04/21/2024 	_x86_64_	(16 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
1.71 0.00 0.74 0.05 0.00 97.50

Device tps kB_read/s kB_wrtn/s kB_dscd/s kB_read kB_wrtn kB_dscd
sda 27.38 1172.47 534.96 197.67 2230709 1017793 376084
zram0 0.03 0.62 0.00 0.00 1180 4 0
  • /proc/diskstats からのデータ取得
cat /proc/diskstats
   8       0 sda 18834 2018 4461434 26986 34351 23700 2080266 16927 0 24827 46864 228 0 774072 471 4649 2478
8 1 sda1 129 1053 8442 50 12 0 10 1 0 64 52 0 0 0 0 0 0
8 2 sda2 18599 965 4448448 26912 34338 23700 2080256 16925 0 24787 44309 228 0 774072 471 0 0
254 0 zram0 54 0 2360 0 1 0 8 0 0 10 0 0 0 0 0 0 0
8 16 sdb 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Load average の監視

uptime
 11:27:17 up 35 min,  1 user,  load average: 0.54, 0.57, 0.48
  • /proc/loadavg からのデータ取得
cat /proc/loadavg
0.63 0.58 0.49 2/1168 22514

SSL 証明書の監視

  • 有効期限の監視と通知

Web サーバの監視

  • レスポンスのステータスコードを監視する

DB の監視

MQ の監視

  • queue の長さの監視 => ConsumerLag?
  • consumption ratio
    • consume のスピード

cache

  • hit/miss ratio

DNS

  • qps の監視
  • BIND の場合はメトリクスを収集するためのオプションがある
    • collectd のプラグインと組み合わせて監視できる

NTP

  • kerberos の認証などで問題になりうる
  • ntpstat

Logging

  • 収集
    • syslog
  • 保存
    • SaaS を使用?
  • 分析
    • 目的、用途に応じて使い分ける
      • Splunk
      • grep などのコマンドラインツール
      • ELK スタック (Elasticsearch, Logstash, Kibana)

セキュリティ監視

etc

  • nagios
  • zabbix

「Rust で始める TCP 自作入門」を読んだメモ

· 約5分

TCP・ネットワーク関連

Socket

  • stream socket: TCP
  • datagram socket: UDP
  • raw socket: データリンク層のフレームを直接操作する
  • packet socket: ネットワーク層のパケットを直接操作する

TCP header

alt text

  • TCP header は 20 バイト
  • Data offset は 4 bit で TCP header の長さを示す。最小値は 5 で 20 バイト(Options がない場合)、最大値は 15 で 60 バイト
  • URG (urgent)
    • 緊急のデータであることを示して先に処理させる
  • ACK (acknowledgment)
  • PSH (push)
    • データをバッファリングせずに送信させる
  • RST (reset)
    • 予期しない状況やエラー時に接続をリセットする
  • SYN (synchronize)
  • FIN (finish)
  • Window size は受信側のバッファサイズを通知する
  • Checksum はヘッダとデータの整合性を確認するためのもので計算には送信元 IP と宛先 IP も必要
  • Urgent pointer は URG フラグが立っている場合に使用されるもので、緊急のデータの位置を示す
  • Options は可変長で window scale や timestamp などが含まれる
  • Padding は Options の長さが 32 bit の倍数になるように埋めるためのもの

スライディングウィンドウ

  • ある程度のセグメントを ACK を待たずに送信することで効率的に通信を行う仕組み
    • 制限なしにパケットを送信し続けてしまうと受信側のバッファがオーバーフローしてしまう
    • しかし、ACK を毎回待っていると通信効率が悪くなる
  • データ送信したらその分 Window を消費し、ACK を受け取ったら Window を回復する

TCP の問題点、QUIC

  • HoL (Head of Line) Blocking
    • パケットロスが発生した場合にその後のパケットも待たされてしまう問題
  • シーケンス番号の使い回し
    • パケットロスが発生したときに再送されたパケットは同じシーケンス番号を持つため、確認応答がもとのパケットと紛らわしい
    • 再送タイムアウト時間の推定に悪影響(←あまり良くわかってない)
  • QUICK
    • 一つのコネクションで複数のストリームを扱うため、HoL Blocking を回避できる
    • 扱うデータごとにストリームを分けることで再送によるブロッキングを回避
    • セグメントのID とシーケンス番号を分けることでシーケンス番号の使い回しを回避

Rust 関連

Error Handling

Rust エラー処理

thread

std::thread

Arc

std::sync::Arc

ツール関連

WireShark

  • Install
paru -S wireshark-qt

sudo usermod -aG wireshark $USER
  • loop back デバイスの 5000 番ポートへの TCP 通信をキャプチャする
tshark -i lo -f "tcp port 5000"
  • キャプチャ例: nc で 5000 番ポートに接続
% tshark -i lo -f "tcp port 5000"
Capturing on 'Loopback: lo'
1 0.000000000 ::1 → ::1 TCP 94 45276 → 5000 [SYN] Seq=0 Win=33280 Len=0 MSS=65476 SACK_PERM TSval=1034799462 TSecr=0 WS=128
2 0.000007955 ::1 → ::1 TCP 74 5000 → 45276 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0
3 0.000057822 127.0.0.1 → 127.0.0.1 TCP 74 52950 → 5000 [SYN] Seq=0 Win=33280 Len=0 MSS=65495 SACK_PERM TSval=2869984391 TSecr=0 WS=128
4 0.000068765 127.0.0.1 → 127.0.0.1 TCP 54 5000 → 52950 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0

nc

  • リスニング状態で待機
nc -l 5000
  • 5000 番ポートに接続
nc localhost 5000
% nc -l 5000
hello

% nc localhost 5000
hello
  • ポートスキャン
nc -zv localhost <port>-<port>
% nc -zv localhost 22
Connection to localhost (::1) 22 port [tcp/ssh] succeeded!

ip

  • Network namespace の作成
sudo ip netns add host0
sudo ip netns add host1
  • Virtual Ethernet Device の作成
    • veth type のデバイスを作成し、veth0 と veth1 という名前でペアを作成する
    • 仮想的に 2 つのネットワークインタフェースが接続された状態になる
    • veth のドライバが必要
sudo ip link add name veth0 type veth peer name veth1
  • namespace に作成したネットワークインタフェースを割り当てる
    • veth1 を host1 という namespace に割り当てる
sudo ip link set veth1 netns host1
  • namespace 内でのコマンド実行
sudo ip netns exec host1 <command>
  • ネットワークインタフェースを有効にする
sudo ip netns exec host1 ip link set veth1 up

ethtool

iptables