ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

ipfw と completely duplicate packets

netstat -s -p tcpTCPプロトコルスタック統計が見られます。
その中の項目、「completely duplicate packets」。


こっちから送った ACK が落ちたときに、
向こうからパケットが再送されてカウントされるものです。


せっかくなので MRTG でグラフ化してみたところ、
200packets/minute を叩きだし、「ぇー……」と思って詳しく調査したところ、
思いがけない結論に達したのでメモ書きを残す。


まずは該当する tcpdump -i lo0。
インターフェースが lo0 ってあたり、既に「ぇー…」ですが、

16:06:42.945550 IP6 client.example.net.61971 > server.example.net.ldap: Flags [S], seq 4054001667, win 65535, options [mss 16324,nop,wscale 6,sackOK,TS val 2061573 ecr 0], length 0
16:06:42.945573 IP6 server.example.net.ldap > client.example.net.61971: Flags [S.], seq 1721556881, ack 4054001668, win 65535, options [mss 16324,nop,wscale 6,sackOK,TS val 2786106269 ecr 2061573], length 0
16:06:42.945610 IP6 client.example.net.61971 > server.example.net.ldap: Flags [.], ack 1, win 1274, options [nop,nop,TS val 2061573 ecr 2786106269], length 0
16:06:42.945679 IP6 client.example.net.61971 > server.example.net.ldap: Flags [P.], seq 1:15, ack 1, win 1274, options [nop,nop,TS val 2061573 ecr 2786106269], length 14
16:06:42.945978 IP6 server.example.net.ldap > client.example.net.61971: Flags [P.], seq 1:15, ack 15, win 1274, options [nop,nop,TS val 2786106269 ecr 2061573], length 14
16:06:42.946094 IP6 client.example.net.61971 > server.example.net.ldap: Flags [P.], seq 15:108, ack 15, win 1274, options [nop,nop,TS val 2061573 ecr 2786106269], length 93
16:06:42.946340 IP6 server.example.net.ldap > client.example.net.61971: Flags [P.], seq 15:29, ack 108, win 1274, options [nop,nop,TS val 2786106269 ecr 2061573], length 14
16:06:42.946764 IP6 client.example.net.61971 > server.example.net.ldap: Flags [P.], seq 108:255, ack 29, win 1274, options [nop,nop,TS val 2061574 ecr 2786106269], length 147
16:06:42.947396 IP6 server.example.net.ldap > client.example.net.61971: Flags [P.], seq 29:80, ack 255, win 1274, options [nop,nop,TS val 2786106270 ecr 2061574], length 51
16:06:43.047712 IP6 client.example.net.61971 > server.example.net.ldap: Flags [.], ack 80, win 1274, options [nop,nop,TS val 2061675 ecr 2786106270], length 0
16:11:24.660499 IP6 client.example.net.61971 > server.example.net.ldap: Flags [.], ack 80, win 0, length 0
16:11:24.660609 IP6 server.example.net.ldap > client.example.net.61971: Flags [.], ack 255, win 1274, options [nop,nop,TS val 2786387984 ecr 2061675], length 0

うーん?なんだこの5分後に送られてる謎の ACK は。
しかもなんかおかしい。RFC 1323 に対応するためのオプションデータが載ってない上に
win が 0 になってる。


TCP の keepalive とはタイミングが違う。

net.inet.tcp.keepidle: 7200000
net.inet.tcp.keepintvl: 75000
net.inet.tcp.keepinit: 75000


最終的にはカーネルにパッチをあててまで調査した結果、
ipfw が悪さをしてるところまで特定。

net.inet.ip.fw.dyn_keepalive: 1
net.inet.ip.fw.dyn_short_lifetime: 5
net.inet.ip.fw.dyn_udp_lifetime: 10
net.inet.ip.fw.dyn_rst_lifetime: 1
net.inet.ip.fw.dyn_fin_lifetime: 1
net.inet.ip.fw.dyn_syn_lifetime: 20
net.inet.ip.fw.dyn_ack_lifetime: 300

おまえか!!!!!


というわけでまとめ。

  • ipfw は動的ルールの keepalive のためにパケットを作成する
  • そしてそれは RFC 1323 に対応してない
  • しかも window 幅を 0 にしてくれる

これ、バグじゃないの??


とりあえず、動的フィルタによる keepalive を殺して、
RFC1323 も無効化することでグラフはかなり落ち着いた。
send-pr してみるか...