ping
偏向報道
この所、TVで ohtani-san ohtani-san って五月蝿い。世の中の野球選手って彼しかいないのかね? 他の頑張っている選手が可哀想。このパターンは他にもあるな(あったな)。スマイル日向子だったかな。ゴルフのおねーたん。活躍できなくても、盛んに報道してたな。流行か。
移ろいやすいというか、視聴率で露出度を決めているんだろうね。商品ですから。
栄一番宣もひどいな。これぞ、皆様の国民放送を人質にしてのやりたい放題だ。再放送で番組制作費を極力抑える。そして推し番組に金をかけるとな。後はYouTubeでも流しておけ。幾らで買ってるんですかね?
民放は、材料費の安い、お笑い芸人ばかりだしね。後は動物番組ね。ユーチューブから拾ってきた。動画はTVで流すの止めてしまえ。放送時間は、1日3時間ぐらいでいいぞ。そうすれば、見応えのある番組を作れるだろう。
で、ネットは大混雑になって困る。ここで提案です。ネットに流す動画はIPv6だけにしちゃえ。そうすれば、みんな仕方なしに移行するだろう。これで、日本もIPv6後進国を脱却出来るの間違い無し。動画ってYouTubeやらHuluやらZoomやら、色々あるからね。高速道路に追いやってしまう作戦ですよ。
なんか文句ある? Windows11になる時、Intelのお願いをMSは聞き入れて、第7世代より古いCPUは切り捨てた(おいらのは第6世代ですよ)。こういう横暴がまかり通る世の中だから、ISPも一致団結すれば、簡単な事さ。
ああ、オイラーも偏向報道してるな。OpenBSDの発信が主ですから。マイナーですよ、ニッチですよ。
mozc
夏はパソコンを置いている所が蒸し風呂になるので、涼しい所でオペレーション。そして日記書き。それはいいんだけど、Debian機の日本語入力が、mozcだ。これに慣れてしまうと、Windows10のIMEと微妙に違うので、指がオロオロする。
リナでの選択肢はmozcしか選択肢ないので、Windows側もmozcにすることにした。
Windows + Emacs + Mozc + boiled-mozc
こういうのがあったので、設定してみた。
socket
少しソケットの勉強をする
まつもと直伝 プログラミングのオキテ 第16回 ネットワーク・プログラミング(ソケット編)
(gdb) p pkt $2 = { hdr = { ether_dhost = "\377\377\377\377\377\377", ether_shost = "\000\000\000\000\000", ether_type = 0 }, sync = "\377\377\377\377\377\377", dest = "\000\f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\000\\ f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\000\ \f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\000\f)Y\350\272\00\ 0\f)Y\350\272\000\f)", <incomplete sequence \350\272> }
前回やったarpのWoLパケット送出部。bpfのソケット経由なんだけど、どこで本物のソケットに引き継がれるのだろう? 更に、ここでは未定になってる ether_shost
は、何処で埋められるのだろう? 疑問だらけだ。
ping
いわゆる導通試験器ね。昔はよくお世話になった。アナログの針が振れるやつ。会社に入って、デジタル式のものが支給されたけど、なかなか馴染めなかったぞ。針がふらふらしてると電気の息使いがみられてよかった。デジタルだと数値がパラパラしてて、何となく頼りなさげだった。ああ、話が違った。
ob$ ping -c5 10.0.2.2 PING 10.0.2.2 (10.0.2.2): 56 data bytes 64 bytes from 10.0.2.2: icmp_seq=0 ttl=255 time=71.568 ms 64 bytes from 10.0.2.2: icmp_seq=1 ttl=255 time=2.823 ms 64 bytes from 10.0.2.2: icmp_seq=2 ttl=255 time=1.796 ms 64 bytes from 10.0.2.2: icmp_seq=3 ttl=255 time=2.086 ms 64 bytes from 10.0.2.2: icmp_seq=4 ttl=255 time=1.768 ms --- 10.0.2.2 ping statistics --- 5 packets transmitted, 5 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 1.768/16.008/71.568/27.783 ms ob$ ping -c5 10.0.2.2 PING 10.0.2.2 (10.0.2.2): 56 data bytes 64 bytes from 10.0.2.2: icmp_seq=0 ttl=255 time=5.319 ms 64 bytes from 10.0.2.2: icmp_seq=1 ttl=255 time=1.903 ms 64 bytes from 10.0.2.2: icmp_seq=2 ttl=255 time=1.802 ms 64 bytes from 10.0.2.2: icmp_seq=3 ttl=255 time=1.832 ms 64 bytes from 10.0.2.2: icmp_seq=4 ttl=255 time=1.796 ms --- 10.0.2.2 ping statistics --- 5 packets transmitted, 5 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 1.796/2.530/5.319/1.395 ms
56byteのパケットを投げて、それがちゃんと戻って来るか。往復時間を計測してる。最後に統計データが出てくる。んだけど、この場合は余り頼りにならない。
上記の2回目の平均が2.5msって、オイラーは納得しないぞ。初回がとても時間がかかってしまっているので、それに引っ張られて平均値が上昇してるんだ。くれぐれも、統計数値に惑わされないように。
この場合なら、中央値ぐらいを取るのが妥当だろう。まあ、算術計算って、非常に処理が簡単だからね。
statistics
OpenBSD 6.6 のソースだと全体行が2000行を超えるけど、目的を持てば簡単に追えるだろう。debianは、ping,ping6用と別れているから、もう少し小ぶりなコードだろう。冒頭から流し読みしてくと、お決まりっぽいのに出会った。
double tmin = 999999999.0; /* minimum round trip time */ double tmax; /* maximum round trip time */ double tsum; /* sum of all times, for doing average */ double tsumsq; /* sum of all times squared, for std. dev. */
こんなグローバル変数が出てきた。tminだけ初期値を決めていて、他は無指定。こんなんで良いのか? 初期値が有る変数はdataエリアに格納される。宣言だけの変数はbssエリアに場所だけ確保される。プログラムが起動した時、OSはbssエリアをZEROクリアする仕様になってる。だから、これでもOK。
でも、このからくりを知らない人は、煙に巻かれてしまうぞ。多少プログラムサイズが大きくなっても、初期値を書いておいた方が親切かな。 コンパイラーが余計なお世話で、グローバル変数で、初期値にZEROを入れてるのは、bssエリアに追い出してしまったり、するのかな?
適当に使ってる場所を探したら、出力してる部分が出てきた。
if (timinginfo) { /* Only display average to microseconds */ double num = nreceived + nrepeats; double avg = tsum / num; double dev = sqrt(fmax(0, tsumsq / num - avg * avg)); printf("round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms \n", tmin, avg, tmax, dev); }
1回パケットを投げる毎に、その場で、最小、最大、合計時間等を算出してる。まあ、普通のやり方だな。
インクリメンタルな分散計算 お前の目は節穴か。ちゃんと見て桶。ボーと生きてんじゃねぇよ。
timespecsub(&ts, &tp, &ts); triptime = ((double)ts.tv_sec) * 1000.0 + ((double)ts.tv_nsec) / 1000000.0; tsum += triptime; tsumsq += triptime * triptime; if (triptime < tmin) tmin = triptime; if (triptime > tmax) tmax = triptime;
これを、中央値にしたいとなると、今までの結果を保存しておく必要が出てくる。面倒になるんで止めたんだろうね。後は初回の値を捨てるとかって、エグイ方法があるな。 そんな事は許してよいものか?
年収100万円の100人が住む村に、アマゾンをリタイアした会長が移住してきました。念願の宇宙旅行にも行ったし、後は田舎でのんびりだな。有り余る資産を投資しているんで、ぬれ手で粟で年収1000億。さてこの村の平均年収は?
なんてのがあるけど、これは資産を隠しているって事? どんなに金を貯めても墓までは持って行けない。資産が有ると言っても、株だとやたらに売りに出すわけにはいかないみたいだね。絵に書いた餅?
ping for gdb
pingを観光しようと思って作ったやつ
vbox$ ./ping 10.0.2.2 ping: socket: Permission denied
こんなエラーになる。なんでかな? Makefileを見たよ。そしたら一般人も実施出来るようにフラグが立ててあった。手動で立ててみても、権利なし。はて困った。正規の場所でコンパイルすると、
vbox# make cc -O2 -pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual -Werror-implicit-function-declaration -MD -MP -c ping.c cc -static -pie -o ping ping.o -lm vbox# make install install -c -s -o root -g bin -m 4555 ping /sbin/ping install -c -o root -g bin -m 444 ping.8 /usr/share/man/man8/ping.8 /sbin/ping6 -> /sbin/ping
こんなことになってた。installコマンドを使っているのね。注目は ーs でstripしちゃう事。
vbox# export STRIP=/usr/bin/true vbox# make install install -c -s -o root -g bin -m 4555 ping /sbin/ping install -c -o root -g bin -m 444 ping.8 /usr/share/man/man8/ping.8 /sbin/ping6 -> /sbin/ping
STRIPコマンドを外部から設定出来るので、無害なものに置き換え。そしてインストール。これで、普通にpingする分には問題無し。gdbから使うと、何故かソケットに権利無しと言われる。gdbから起動するアプリは、権利が剥奪されてるのかな。とりあえずroot権限で実行。
(gdb) up #2 0x166aaee5 in main (argc=1, argv=0xcf7fc338) at ping.c:923 923 if (poll(&pfd, 1, timeout) <= 0) (gdb) l 918 timeout = INFTIM; 919 920 pfd.fd = s; 921 pfd.events = POLLIN; 922 923 if (poll(&pfd, 1, timeout) <= 0) 924 continue; 925 926 if (v6flag) { 927 m.msg_name = &peer6;
タイマー制御で投げるパケットの時間間隔は正確に制御されてるけど、暇な時間はpollからの連絡待ちになってるのね。
パケットの形
デフォでは、56byteのデータを投げるってなってるけど、中身はどうなってるの? 外観検査してみる。
vbox$ ./pkt-recv -i em0 IP.PROTOCOL==1 >LOG -- 1 -- TIME: 1625353947.610235 Sun Jul 4 08:12:27 2021 SIZE: 98/98 000000: 52 54 00 12 35 02 08 00 27 20 E8 38 08 00 45 00 : RT..5... ' .8..E. 000010: 00 54 B5 85 00 00 FF 01 EE 12 0A 00 02 0F 0A 00 : .T...... ........ 000020: 02 02 08 00 D6 43 1F B6 00 00 04 D0 17 39 91 E0 : .....C.. .....9.. 000030: 7C 9B 34 D6 3F 18 5C 72 46 75 CD 75 9B D7 31 2C : |.4.?.\r Fu.u..1, 000040: B3 AE 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 : ........ .. !"#$% 000050: 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 : &'()*+,- ./012345 000060: 36 37 : 67 == vbox$ cat LOG | ./pkt-analyze LINKTYPE: 1 (Ethernet) -- 1 -- received: 98 bytes 1625353947.610235 Sun Jul 4 08:12:27 2021 Ethernet 08:00:27:20:e8:38 -> 52:54:00:12:35:02 (type: 0x0800) IP head/total size : 20 / 84 bytes ID/fragment : 0xb585 / 0x0000 TTL/protocol : 255 / 1 checksum : 0xee12 (Valid) src/dst addr : 10.0.2.15 / 10.0.2.2 ICMP total size : 64 bytes type/code : 8 / 0 checksum : 0xd643 (Valid) ==
何やら、適当なデータが使われているみたいですなあ。んな事ない。0x18 からインクリメントされる人工のデータみたいだ。詳しくはソース嫁。
データは下記のように、任意に指定出来たりします。そして -sオプションで、サイズも増量出来るようになってます。
vbox$ ping -c 1 -p deadbeaf 10.0.2.2 -- 1 -- TIME: 1625355967.100441 Sun Jul 4 08:46:07 2021 SIZE: 98/98 000000: 52 54 00 12 35 02 08 00 27 20 E8 38 08 00 45 00 : RT..5... ' .8..E. 000010: 00 54 60 17 00 00 FF 01 43 81 0A 00 02 0F 0A 00 : .T`..... C....... 000020: 02 02 08 00 B2 24 BD B2 00 00 A5 0D 8D 55 8A 64 : .....$.. .....U.d 000030: 94 46 40 CF 04 87 4B FF D1 5F EA 62 57 2F D8 7E : .F@...K. ._.bW/.~ 000040: CF 66 DE AD BE AF DE AD BE AF DE AD BE AF DE AD : .f...... ........ 000050: BE AF DE AD BE AF DE AD BE AF DE AD BE AF DE AD : ........ ........ 000060: BE AF : .. ==
大きなデータを指定すれば、そのデータが往復するんで、ネットワークや相手方、そして自分自身にも負担を強いる事になります。
ping flood
それを顕著に強調すると、サイバー戦争の武器にする事も出来ます。
debian(pen)が攻める側になり、OpenBSD(ob)が防戦する側として、演習します。
sakae@pen:~$ sudo ping -f -c 100 aa.bb.cc.128 PING aa.bb.cc.128 (aa.bb.cc.128) 56(84) bytes of data. --- aa.bb.cc.128 ping statistics --- 100 packets transmitted, 100 received, 0% packet loss, time 144ms rtt min/avg/max/mdev = 0.156/1.021/31.173/3.770 ms, pipe 2, ipg/ewma 1.454/0.61 ms
これ、普通は1秒間隔で送出されるパケットなんですが、洪水を発生させました。100個のパケットなので99秒費やすはずですが、わずか144msの間に集中しました。猛烈な雨です、じゃなくてパケットです。
Pingフラッド って奴。洪水作戦。最近は、線状降水帯の影響で、洪水に岩のおまけが付いて来ると言う、大災害が発生してます。注意しましょう。
どやって? 一番簡単なのは、全部捨て去る作戦。
block in proto icmp
を/etc/pf.confに書けばOk。
sakae@pen:~$ ping -c 5 aa.bb.cc.128 PING aa.bb.cc.128 (aa.bb.cc.128) 56(84) bytes of data. --- aa.bb.cc.128 ping statistics --- 5 packets transmitted, 0 received, 100% packet loss, time 84ms
完全防水になり、OpenBSD本体にはパケットが侵入できていません。まあ、これでもいいんだけど、礼儀正しく少しはICMPに応答するようにします。
pass in proto icmp max-pkt-rate 50/10
10秒間で50パケットは、普通に通すけど、それ以外は、拒否します。この設定で実行すると
sakae@pen:~$ sudo ping -f -c 200 aa.bb.cc.128 PING aa.bb.cc.128 (aa.bb.cc.128) 56(84) bytes of data. ................................................................................ ...................................................................... --- aa.bb.cc.128 ping statistics --- 200 packets transmitted, 50 received, 75% packet loss, time 556ms rtt min/avg/max/mdev = 0.178/1.617/28.858/4.826 ms, pipe 2, ipg/ewma 12.836/2.539 ms
バリアで一つ思い出した事がある。狂った国から発射されるミサイルを追撃して、撃ち落としてしまいましょって言う盾作戦。一発なら防御出来るかも知れないけど、複数が同時に発射されたらどうなるの?
一発ぐらい見逃されて、何処かに着弾したりして。pf.confみたいに、きれいにはいかないだろうね。まあ、折角開発したんだから買ってくれって、押し売りされて、やっと断る理由を見つけたって所かな。
info
The summary information can also be displayed while ping is running by sending it a SIGINFO signal (see the status argument of stty(1) for more information).
pingのマニュアルを見ていると、動作中でも要約を知る事が出来るとな。してその方法は、SIGINFO割り込みをキーボードから発生させれば良いとな。キーバインドはsttyコマンドのstatusに設定せいって事らしい。
vbox$ stty -e : min quit reprint start status stop susp time werase 1 ^\ ^R ^Q <undef> ^S ^Z 0 ^W
sttyの状況を確認すると、未割り当てになってる。
vbox$ stty status \^p
こんな風に割り当てた(バックスラッシュ、山形文字がCtl相当、そしてp)。
64 bytes from 10.0.2.2: icmp_seq=2 ttl=255 time=0.842 ms 64 bytes from 10.0.2.2: icmp_seq=3 ttl=255 time=1.062 ms ;; Press Ctl-p load: 0.24 cmd: ping 1443 [runnable] 0.00u 0.00s 0% 178k --- 10.0.2.2 ping statistics --- 4 packets transmitted, 4 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 0.468/0.970/1.510/0.377 ms 64 bytes from 10.0.2.2: icmp_seq=4 ttl=255 time=0.895 ms 64 bytes from 10.0.2.2: icmp_seq=5 ttl=255 time=0.862 ms
これで、動作中にも、状況を把握出来るようになった。
尚、sttyで各種割り込みキーに普通の文字も割当可能だけど、それをやっちゃうと、壊れたキーボードになっちゃうんで、止めとけ。やっていいのは、生意気な新人をいたぶる時だけです(おい、おい)。
RFC 792
ICMP (Page 14) を見ると、ペイロードに有意義なデータを入れる事になっている。勿論OpenBSDも同様。マニュアルには、
If the data space is at least 24 bytes, ping uses the first sixteen bytes of this space to include a timestamp which it uses in the computation of round trip times. The following 8 bytes store a message authentication code. If less than 24 bytes of pad are specified, no round trip times are given.
こんな事が書かれていた。折角なので確かめてみるか。
struct payload { struct tv64 tv64; u_int8_t mac[SIPHASH_DIGEST_LENGTH]; };
OpenBSDの時間の扱いはとっくの昔に64Bit化されます。ダイジェストが8Byteを占めるんで、合わせて24Byteになるとな。
(gdb) bt #0 pinger (s=3) at ping.c:1160 #1 0x18a1de87 in retransmit (s=3) at ping.c:1081 #2 0x18a1ca66 in main (argc=1, argv=0xcf7f0298) at ping.c:853
pingerの中でパケットを組み立てている。
SipHash24_Init(&ctx, &mac_key); SipHash24_Update(&ctx, tv64, sizeof(*tv64)); SipHash24_Update(&ctx, &ident, sizeof(ident)); SipHash24_Update(&ctx, &seq, sizeof(seq)); SipHash24_Final(&payload.mac, &ctx);
ここでは、認証確認のためのハッシュを作成
(gdb) p *tv64 $8 = {tv64_sec = 15873237536484556959, tv64_nsec = 7183945255579513247} (gdb) p ident $9 = 32566 (gdb) p seq $10 = 0
その元データ、inentはプロセス番号だな。
ここを抜けると、
/* compute ICMP checksum here */ => icp->icmp_cksum = in_cksum((u_short *)icp, cc);
こんな所にやって来る。ccは64って事で、icmpのペイロードだ。どんなデータになってるか調べてみる。
(gdb) x/64b icp 0x34e8d04c <outpackhdr+20>: 0x08 0x00 0x00 0x00 0x78 0x06 0x00 0x00 0x34e8d054 <outpackhdr+28>: 0x30 0xa7 0xca 0xba 0x04 0x63 0x30 0x1c 0x34e8d05c <outpackhdr+36>: 0x80 0x71 0x25 0x95 0x57 0xd7 0x2f 0x6b 0x34e8d064 <outpackhdr+44>: 0x1c 0xbe 0x97 0x8e 0x81 0xbb 0x8c 0x99 0x34e8d06c <outpackhdr+52>: 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x34e8d074 <outpackhdr+60>: 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x34e8d07c <outpackhdr+68>: 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x34e8d084 <outpackhdr+76>: 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37
目を凝らして見れば、outpackhdr+52 の所から、人工データのインクリメントなデータが並んでいるのが見て取れる。
余計な事だろうけど、この人工データは、pingが走り初めた割と最初の方で作られていた。
B if (!(options & F_PINGFILLED)) for (i = ECHOTMLEN; i < datalen; ++i) => *datap++ = i;
(gdb) p i $9 = 24 (gdb) p/x i $10 = 0x18 (gdb) p datalen $11 = 56
この0x18って謎の数値は、payload構造体のサイズだった。まあ、それでもいいんだけど、若干遊んでいるな。コード書く人の特権と理解しておこう。