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の時間です。

IPoE接続とPPPoE接続との違い

OCN からの蜜

オイラーは古い人間。IPv4が使えればそれでOK。IPv6なんて、ユーザーに何のメリットが有るのと思っちゃうぞ。携帯屋の都合で、3G電波が使えなくなりますから4Gにしてくださいみたいなもの。

が、混雑してる都会では、IPv4が遅いってんで、IPv6に変える人がいるかと思ったら、お客さん、この契約すると、更に速くなりますよと、蜜を出してきた所がある。

OCN 光 + IPoEアドバンス

重要事項』のご案内 - IPoEアドバンスをお申し込みのお客さまへ

所詮、頑張るけど保障はしないからね、の世界だからなあ。

まて、IPv6が未だ普及しないのは、日本の恥とか、何とか庁が言い出すんじゃなかろうか。そうなったら、蜜が普及するかも。 そのうちに、No IPv4 day とか言って、パケットをdropしちゃったりして。あるいは、徐々にIpv4の帯域を絞っていくとか。

アナログTVが一斉にデジタル式になったけど、そんな日が来ないとも限らないな。そうなった場合、定額制を止めて、従量制に移行しますとか、もどさくさ紛れに実施。これぞ、ISPの見果てぬ夢だ。なーに、携帯系は、既にそうなってますから。


This year's Index

Home