pf.os
妄想
テレワークがデフォになりつつある現在、ノーパソに外部ディスプレイを取り付けている方をよく見かける。そうだよなあ、excelの広大が表をちまちまと見てたら、仕事にならん。
オイラーは最近目が衰えたせいか、ターミナルのフォントサイズを大きくする傾向にある。そなると困るのがemacsで画面を割った時だ。大きな表示器が欲しい。最近はUSBで繋げるやつもあるそうですからね。
モニターにはEIZOが良いらしい(高いけどね)。んな訳で、 モニター購入の前に!PCとの接続確認を見てる。
USB-Cと言っても、映像を流せるやつと流せない旧式が有るとな。オイラーの今のノーパソだとHDMIでの接続になるな。最大 4096x2304ドット、1677万色(HDMI接続時)が、運がよければ表示出来るとな。
と、ここまで妄想して、まて、焦るなと声が聞こえてきたぞ。40インチの巨大表示器が有るじゃん。何時も女房が、YouTube見てる。TVの横を見たら、豪勢に4ポートもhdmiが用意されてたぞ。
なら、ケーブルだな。オーディオ神話宜しく、金メッキの高級品から普及品まで、それぞれ。平均1000円ぐらいか。後で、100均へ偵察に行ってこい。
ThinkPad側は、Win+P で、モニターを次々に切り替えられるとな。
pf.os
前回ちょいと興味を持った、/etc/pf.osに付いて、調べてみる。まずは、どんな使われ方をするの? pf.conf(5)を調べる。
Examples: pass out proto tcp from any os OpenBSD
これ、イミグレーションで、OpenBSDだけを通過させるって言う、偏屈仕様の宣言だ。昔あったね、米国の国籍を持ってる人しか入国を認めんと言う対策が。問題点を下記のように指摘してた。
Operating system fingerprinting is limited only to the TCP SYN packet. This means that it will not work on other protocols and will not match a currently established connection. Caveat: operating system fingerprints are occasionally wrong. There are three problems: an attacker can trivially craft his packets to appear as any operating system he chooses; an operating system patch could change the stack behavior and no fingerprints will match it until the database is updated; and multiple operating systems may have the same fingerprint.
仮にこういう極端な政策を取らなくても、しっかりとログを残しておいて、後で確認する事が出来る。/etc/pf.conf に、logってのを忍びこませておけばよい。
pass in log on egress proto tcp from any to egress port ssh modulate state
/var/log/pflogにtcpdumpの形式でログが作成されるようになる。
tcpdump -n -e -ttt -r /var/log/pflog tcpdump -n -e -ttt -i pflog0
だから、上のようにして、後で監査出来る。場合によってはリアルタイムでモニターしたい場合が有るかも知れない。そういう場合、pflogdを動かしておけば、pflog0なデバイスが作成されるので、それをアクセスしても良い。
tcpdumpには、-oオプションが用意されてて、それを併用すると、推測したOSを表記してくれる。
ob# tcpdump -o -r /var/log/pflog tcpdump: WARNING: snaplen raised from 116 to 160 05:39:33.158555 aa.bb.cc.1.61966 > aa.bb.cc.128.ssh: S (src OS: Windows 2000 RFC1323, Windows XP RFC1323) 1670164038:1670164038(0) win 64240 <mss 1460,nop,wscale 8,nop,nop,sackOK> (DF) 06:01:28.943776 aa.bb.cc.1.50083 > aa.bb.cc.128.ssh: S (src OS: Windows 2000 RFC1323, Windows XP RFC1323) 2859491309:2859491309(0) win 64240 <mss 1460,nop,wscale 8,nop,nop,sackOK> (DF) 06:14:47.883955 aa.bb.cc.129.50148 > aa.bb.cc.128.ssh: S (src OS: unknown) 3056956410:3056956410(0) win 64240 <mss 1460,sackOK,timestamp 3361790721 0,nop,wscale 7> (DF)
上記に対するloginのログ。分かり易いようにコメントを入れておいた。
ob# last sakae ttyp0 aa.bb.cc.129 06:14 still logged in ;; debian(64) sakae ttyp0 aa.bb.cc.1 06:01 - 06:03 (00:02) ;; openbsd from vbox sakae ttyp0 aa.bb.cc.1 06 05:39 - 05:43 (00:03) ;; freebsd from vbox reboot ~ 05:27
vboxからだと、パケットの転送はWindows10経由になるんで、Winddowって推測してる。同一サブネットのDebian(64)からだと、Linuxがパケットをハンドリングしているので、Linuxと指摘してもよさそう。
でも、残念ながら、pf.soのファイルが更新されていないので、検出出来ないのさ。 ここまで書いてきて、あれなんだけど、これお遊びだな。
tcpdump
普段はドキュメント(man)がきちんと整備されてるOpenBSDのお世話になっているんだけど、セカンドオピニオンとしてリナのmanを見る事もある(FreeBSDはどうしたってのもあるけど、こういう時は、系列が違う方が良い)。
で、linux man tcpdump なんてggしてみたのさ。そしたら manページ — TCPDUMP なんてのが引っかかってきた。 つらつら見てくと 特定フラグの組み合わせ (SYN-ACK, URG-ACK 等) による TCP パケットの捕捉 なんて言う興味深い例が載ってた。
SYNビットが立ったパケットだけをキャプチャする例(なんか、前回やったPFみたいな雰囲気だな)として、
tcpdump -i xl0 'tcp[13] & 2 == 2'
こんな例が挙げられていたぞ。ここで、大いなる疑問。リナのNIC表現にxl0なんて有るのか?これって、BSD系のNIC表現だよな。マニュアル原稿の盗用疑惑が浮上しました。なお、正真正銘ののdebianのマニュアルでも、同様。盗用元はFreeBSDだろうと推測。
FreeBSDの本家へ行き、言語を英語に切り替える(日本語だと、翻訳が間に合わないで掲載されていない場合がある為)。そして見て行くと、 FreeBSD Manual Pages(tcpdump) に同じ内容が出てました。
ああ、manualの最後にAUTHORSがあり、tcudumpの本家は tcpdump & libpcap だよと案内されてた。そういう事なのね。盗用を疑ってごめんね >りな。
早速実験。VMwareのsubnetに接続されてるOpenBSDからDebianにssh接続する時の状況を、Debian側で観測。
sakae@pen:/tmp$ sudo tcpdump -w OBLOG 'tcp[13] & 2 == 2' tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes ^C2 packets captured 2 packets received by filter 0 packets dropped by kernel
最初のパケはOpenBSDから発呼されてる。2番目はDebian側からの発呼ですな。
sakae@pen:/tmp$ sudo tcpdump -t -r OBLOG reading from file OBLOG, link-type EN10MB (Ethernet) IP aa.bb.cc.128.33778 > aa.bb.cc.129.ssh: Flags [S], seq 2874817133, win 16384, options [mss 1460,nop,nop,sackOK,nop,wscale 6,nop,nop,TS val 2780959048 ecr 0], length 0 IP aa.bb.cc.129.ssh > aa.bb.cc.128.33778: Flags [S.], seq 1933806790, ack 2874817134, win 65160, options [mss 1460,sackOK,TS val 1665140903 ecr 2780959048,nop,wscale 7], length 0
このログをOpenBSD側に送って、OSを推測してくれるか、確認してみる。
ob$ tcpdump -t -o -r OBLOG tcpdump: WARNING: snaplen raised from 116 to 262144 aa.bb.cc.128.33778 > aa.bb.cc.129.ssh: S (src OS: OpenBSD 6.1) 2874817133:2874817133(0) win 16384 <mss 1460,nop,nop,sackOK,nop,wscale 6,nop,nop,timestamp 2780959048 0> (DF) [tos 0x48] aa.bb.cc.129.ssh > aa.bb.cc.128.33778: S 1933806790:1933806790(0) ack 2874817134 win 65160 <mss 1460,sackOK,timestamp 1665140903 2780959048,nop,wscale 7> (DF)
tcpdumpがパケットをどれぐらいキャプチャするかがsnamplenで指定される。OpenBSDは、極々控え目の116byteなのに対し、debianでは、どかっと容量を増やしている。で、openbsd 6.1だろうと推測した。正解は6.9 です。
指紋
各所OSの指紋台帳から、OpenBSD族にどんなのが登録されてるか、確認。
ob$ grep OpenBSD /etc/pf.os # $OpenBSD: pf.os,v 1.27 2016/09/03 17:08:57 sthen Exp $ # traffic (OpenBSD pf with "scrub" enabled, for example) will, well, # ----------------- OpenBSD ----------------- 16384:64:0:60:M*,N,W0,N,N,T: OpenBSD:2.6::NetBSD 1.3 (or OpenBSD 2.6) 16384:64:1:64:M*,N,N,S,N,W0,N,N,T: OpenBSD:3.0-4.8::OpenBSD 3.0-4.8 16384:64:0:64:M*,N,N,S,N,W0,N,N,T: OpenBSD:3.0-4.8:no-df:OpenBSD 3.0-4.8 (scrub no-df) 57344:64:1:64:M*,N,N,S,N,W0,N,N,T: OpenBSD:3.3-4.0::OpenBSD 3.3-4.0 57344:64:0:64:M*,N,N,S,N,W0,N,N,T: OpenBSD:3.3-4.0:no-df:OpenBSD 3.3-4.0 (scrub no-df) 65535:64:1:64:M*,N,N,S,N,W0,N,N,T: OpenBSD:3.0-4.0:opera:OpenBSD 3.0-4.0 (Opera) 16384:64:1:64:M*,N,N,S,N,W3,N,N,T: OpenBSD:4.9::OpenBSD 4.9 16384:64:0:64:M*,N,N,S,N,W3,N,N,T: OpenBSD:4.9:no-df:OpenBSD 4.9 (scrub no-df) 16384:64:1:64:M*,N,N,S,N,W6,N,N,T: OpenBSD:6.1::OpenBSD 6.1 16384:64:0:64:M*,N,N,S,N,W6,N,N,T: OpenBSD:6.1:no-df:OpenBSD 6.1 (scrub no-df)
指紋鑑定
OpenBSDのtcpdumpは、オリジナルのそれを拡張してる。
-o Print a guess of the possible operating system(s) of hosts that sent TCP SYN packets. See pf.os(5) for a description of the passive operating system fingerprints.
刑事が被疑者の指紋を欲しかったとする。普通は令状がなければ採取出来ない。そこで、どうするか?
被疑者周辺の人に頼んで、被疑者が触れた物を回収してもらう。でも、密告されたら、警戒しちゃうだろう。そこで、色仕掛けですよ。まあ、色々あらーな。
今回の方法は、passiveと謳ってある通に、そっと検体を入手するんだな。多くはいらない。被疑者がだれかと通信しようと始めた、最初のパケットを採取するだけ。指紋を取られたと感じる事はない。
で、後はtcpdumpの解析機関に回すだけ。今回は、リナ野郎が採取したパケットを解析するんだな。
得意のソース嫁で、tcpdump.cを見たら、oflagが立った依頼は、指紋鑑定に回される。
print-tcp.c/tcp_print
/* OS Fingerprint */ if (oflag && (flags & (TH_SYN|TH_ACK)) == TH_SYN) { struct pf_osfp_enlist *head = NULL; struct pf_osfp_entry *fp; unsigned long left; left = (unsigned long)(snapend - (const u_char *)tp); if (left >= hlen) head = pf_osfp_fingerprint_hdr(ip, ip6, tp); if (head) { int prev = 0; printf(" (src OS:"); :
動きを追跡しよとしたんだけど、黙り込んじゃうなあ。root権限でも黙る。ただgdbを通さないと、普通に動く。
67499 p1 I 0:00.58 gdb -q tcpdump (egdb) 6159 p1 TX+ 0:00.01 /tmp/tcpdump -o -r OBLOG 53790 p1 IX+ 0:00.01 tcpdump: [priv] (tcpdump)
privの影響なの? 普通にtcpdumpを動かすと
22994 p1 S+p 0:16.25 ./tcpdump port 29825 56475 p1 S+pU 0:00.03 tcpdump: [priv] (tcpdump)
なんだか、オイラーの知らないstatusが立ってるなあ。このあたりがヒント? Xと言うフラグは、プロセスがdebug対象になってるよって事だった。tcpdumpのプロセスが2つ有るのは、権利制限の関係だった。なんか、gdbをgdbしたい気分だなあ。
try linux
河岸を変えてリナでやってみるか。いちいちgdbで追うのも面倒なので、uftraceのご厄介になってみる。取り合えずは、windowsからdebian(32)へsshした時のパケットをWINLOGとしてtcpdumした。それを読む時に、下記のように記録する。
root@debian:/tmp# uftrace record ./tcpdump -r WINLOG root@debian:/tmp# uftrace report Total time Self time Calls Function ========== ========== ========== ==================== 64.734 ms 90.650 us 1 main 48.996 ms 48.996 ms 20 linux:schedule 34.249 ms 21.999 us 1 pcap_loop 34.227 ms 6.357 us 2 print_packet 34.220 ms 29.543 us 2 pretty_print_packet 32.888 ms 6.146 us 2 ether_if_print 32.882 ms 6.215 us 2 ether_print 32.876 ms 10.338 us 2 ether_common_print 32.850 ms 11.104 us 2 ethertype_print 32.839 ms 43.373 us 2 ip_print 32.712 ms 11.104 us 2 ip_demux_print 32.701 ms 176.339 us 2 tcp_print 32.040 ms 12.504 us 4 get_ipaddr_string 32.027 ms 25.629 us 4 ipaddr_string 31.995 ms 965.126 us 2 gethostbyaddr 16.691 ms 3.213 us 1 exit_tcpdump 16.687 ms 800.094 us 1 exit :
2パケット分のデータが有るので、 tcp_print
等は、2回呼び出されている。
uftrace replay した結果は、4000行を越えてた。
# DURATION TID FUNCTION [ 11999] | main() { [ 11999] | nd_init() { : [ 11999] | pcap_loop() { [ 11999] | print_packet() { : 342.987 us [ 11999] | } /* tcp_print */ 8.101 us [ 11999] | } /* nd_pop_packet_info */ 406.053 us [ 11999] | } /* ip_print */ 409.265 us [ 11999] | } /* ethertype_print */ 422.186 us [ 11999] | } /* ether_common_print */ 425.259 us [ 11999] | } /* ether_print */ 428.332 us [ 11999] | } /* ether_if_print */ : 746.944 us [ 11999] | } /* pretty_print_packet */ 750.018 us [ 11999] | } /* print_packet */ 34.249 ms [ 11999] | } /* pcap_loop */ 3.352 us [ 11999] | fflush();
当たり前だけど、レイヤーの低い所から表示が始まって、レイヤーが高い所に入って行くって動作になってる。
pcap_loop
がtcpdup.cに置いてあるので、そこから、etagでタグって行こうかと思ったら、そんな関数無かった。で、しばし考えたらlibpcapに有るのね。そこから、必要なprotoに則り、callbackするって仕組みになってるとな。
/etc/protocolsに定義されてる、プロトコルは全部サポートしているのかな?
一応gdbが動くか、確認して億。
(gdb) bt #0 tcp_print (ndo=0xbfffe3f0, bp=0xb7948032 "\367\177", length=32, bp2=0xb794801e "E", fragmented=0) at ./print-tcp.c:176 #1 0x0045dea2 in ip_demux_print (ndo=0xbfffe3f0, bp=0xb7948032 "\367\177", length=32, ver=4, fragmented=0, ttl_hl=128, nh=6 '\006', iph=0xb794801e "E") at ./print-ip-demux.c:98 #2 0x0042d6ac in ip_print (ndo=0xbfffe3f0, bp=0xb794801e "E", length=52) at ./print-ip.c:474 #3 0x00428ffb in ethertype_print (ndo=0xbfffe3f0, ether_type=2048, p=0xb794801e "E", length=52, caplen=52, src=0xbfffe234, dst=0xbfffe22c) at ./print-ether.c:530 #4 0x00428b38 in ether_common_print (ndo=0xbfffe3f0, p=0xb794801e "E", length=52, caplen=52, print_switch_tag=0x0, switch_tag_len=0, print_encap_header=0x0, encap_header_arg=0x0) at ./print-ether.c:386 #5 0x00428c42 in ether_print (ndo=0xbfffe3f0, p=0xb7948010 "\256\r\314\376MI\204\357\030<\205\235\b", length=66, caplen=66, print_encap_header=0x0, encap_header_arg=0x0) at ./print-ether.c:442 #6 0x00428c90 in ether_if_print (ndo=0xbfffe3f0, h=0xbfffe36c, p=0xb7948010 "\256\r\314\376MI\204\357\030<\205\235\b") at ./print-ether.c:458 #7 0x00415fc2 in pretty_print_packet (ndo=0xbfffe3f0, h=0xbfffe36c, sp=0xb7948010 "\256\r\314\376MI\204\357\030<\205\235\b", packets_captured=1) at ./print.c:404 #8 0x004153ea in print_packet (user=0xbfffe3f0 "", h=0xbfffe36c, sp=0xb7948010 "\256\r\314\376MI\204\357\030<\205\235\b") at ./tcpdump.c:3075 #9 0xb7cb4bd2 in ?? () from /usr/lib/i386-linux-gnu/libpcap.so.0.8 #10 0xb7ca4d63 in pcap_loop () from /usr/lib/i386-linux-gnu/libpcap.so.0.8 #11 0x00414724 in main (argc=3, argv=0xbffff784) at ./tcpdump.c:2524
これが手に入れば、フレームを上り下りして、簡単に連鎖を把握出来る。etag使って、追いかけるよりも遥かに効率的で楽だ。
print-ether.c
switch (ether_type) { case ETHERTYPE_IP: => ip_print(ndo, p, length); : case ETHERTYPE_IPV6: : case ETHERTYPE_ARP: case ETHERTYPE_REVARP: : case ETHERTYPE_ATALK: : case ETHERTYPE_PPP: :
こんな具合に並んでいるけど、これらをまとめたファイルって、何処かに保持してないのかしらん?
このPPPってやつ、NTTが好きなんだな PPPoE(PPP over Ethernet)
そして、古いやつは遅いよと、CMの時間です。
OCN からの蜜
オイラーは古い人間。IPv4が使えればそれでOK。IPv6なんて、ユーザーに何のメリットが有るのと思っちゃうぞ。携帯屋の都合で、3G電波が使えなくなりますから4Gにしてくださいみたいなもの。
が、混雑してる都会では、IPv4が遅いってんで、IPv6に変える人がいるかと思ったら、お客さん、この契約すると、更に速くなりますよと、蜜を出してきた所がある。
重要事項』のご案内 - IPoEアドバンスをお申し込みのお客さまへ
所詮、頑張るけど保障はしないからね、の世界だからなあ。
まて、IPv6が未だ普及しないのは、日本の恥とか、何とか庁が言い出すんじゃなかろうか。そうなったら、蜜が普及するかも。 そのうちに、No IPv4 day とか言って、パケットをdropしちゃったりして。あるいは、徐々にIpv4の帯域を絞っていくとか。
アナログTVが一斉にデジタル式になったけど、そんな日が来ないとも限らないな。そうなった場合、定額制を止めて、従量制に移行しますとか、もどさくさ紛れに実施。これぞ、ISPの見果てぬ夢だ。なーに、携帯系は、既にそうなってますから。