net.ipv4.tcp_timestamps

おおはまりしたので、記録。

あるシステムでのトラブル。サーバはよそのところ。こっちはクライアント。まったく同一の OS、同一の設定なのに、ホストによってあちらのサーバにアクセスできたりできなかったりする。以前から動いていたホストは問題ない。後から追加したホストがダメ。

http://ya.maya.st/d/200804c.html#s20080430_2

これに近似した状況。

web サーバにエラーログだけは出る。

[Mon Jun 11 12:34:08.181627 2018] [proxy:error] [pid 1380] (70007)The timeout specified has expired: AH00957: HTTP: attempt to connect to xx.xx.xx.xx:80 (xx.xx.jp) failed

で、先方に問い合わせてもアクセスの形跡が無いと言われてしまう。
真面目に調べてくれてないだけという可能性もあるけど、そういわれてしまうと証明しないとならない。


2台構成のサービスで、タイムアウトは片方のサーバでしか発生しない。
まずやったことは1台構成に縮退してみる。
結果:1台だとうまいこと動く。


web サーバの設定差を疑ったが、この時点でその線は消えた。

次に、NAT 経由でのアクセスであるため、NAT が怪しいと思い、NAT を交換。
結果:だめ


それでも NAT しかないやろと思い、NAT を1インスタンス1台という、
専用構成にしてみる。インスタンス毎にサブネットを別々にしていたのが幸いし、
これはルートテーブルを差し替えるだけで簡単に試せる。
結果:OK


いやいやそんなことあります?未曾有の経験。つまり NAT も NAT として
機能している。


次にやったことが、タイムアウトするまでの間に netstat してみる。

[ ~]$ netstat -n -t | grep xx.xx.xx.xx
tcp        0      1 xx.xx.xx.xx:52136           xx.xx.xx.xx:80           SYN_SENT    

ん?SYN_SENT でとまってる・・・。
つまり、TCP のハンドシェイクの時点で待ちになっちゃっているということ。
もし先方までアクセスが到達していたとしても、これじゃアクセスログは残らない・・・。

次。
どこまでアクセスは到達してるのか。

sudo tcpdump host xxx.xxx.xxx.xxx -w nat &
sudo tcpdump host xxx.xxx.xxx.xxx -w 1a &
sudo tcpdump host xxx.xxx.xxx.xxx -w 1c &

tcpdump してみて、プロトコルアナライザで見てみる。
ちなみに、Wireshark を使いました。
結果:
NAT まで到達して、先方までちゃんとアクセスを投げている!

しかし、TCP の SYN を送った後、先方から ACK が返ってこず、
数回リトライしてタイムアウトしている!


・・・この時点で、グーグルさんに登場願う。
「nat syn timeout」みたいな適当なキーワードでぐぐると、
出てくる出てくる、類似事例が。


一番まとまっているように見えたのが上記の方のページ。
先方の設定を変えてもらうことは出来ないので、各インスタンスに、

sysctl -w net.ipv4.tcp_timestamps=0
cat << 'EOS' > /etc/sysctl.d/tcp_timestamp.conf
net.ipv4.tcp_timestamps = 0
EOS

って感じで設定。


あっさりと問題は解決した。
この感謝の気持ちを込めて、キーワード入りのブログを残す。
お役に立てば幸いです。


その他にも実際にはいろいろ調べたけれども、結局 OS 依存するところが多いため、
あまり参考にならないと思われるので、割愛。