TCPのタイムアウトまでの時間を確認

## 簡単な確認方法

```sh
# 存在しないIP宛にtelnetするとタイムアウトまでの時間がわかる。

$ time telnet 192.168.9.12
Trying 192.168.9.12...
telnet: connect to address 192.168.9.12: Connection timed out

real	2m7.001s
user	0m0.000s
sys	0m0.001s
```

```sh
# リトライ回数の設定は以下で確認ができます。
$ cat /proc/sys/net/ipv4/tcp_syn_retries 
5
```

CentOS 5 の tcp_syn_retries値

| 値 | タイムアウト | 備考 |
|:--|:--|:--|
| 5 | 3m9.132s | 初期値 |
| 6 | 5m9.178s | |

CentOS 6.10 の tcp_syn_retries値

| 値 | タイムアウト | 備考 |
|:--|:--|:--|
| 5 | 1m3.043s | 初期値 |
| 6 | 2m7.001s | |
| 7 | 4m7.001s | |
| 8 | 6m7.001s | |

(TCP_RTO_MAX値が120なため２分づつ増える)



※キャッシュが有効になっているのか、すぐにタイムアウトすることもあれば、期待値より半分の時間の場合もあった。


## tcpdumpを使った確認方法

```sh
# eth0のtelnetポートを監視
sudo /usr/sbin/tcpdump -i eth0 port 23
```

```sh
# 到達できないIPを指定してtelnet
telnet 192.168.9.9
```

> Trying 192.168.9.9...
> telnet: Unable to connect to remote host: Connection timed out

となるまで tcpdump の出力を確認。

### 理論上

```sh
# CentOS 6.10
$ cat /proc/sys/net/ipv4/tcp_syn_retries
5
# 結果
0秒(最初のSYN)
+  1秒(1回)
+  2秒(2回)
+  4秒(3回)
+  8秒(4回)
+ 16秒(5回)
+ 32秒(タイムアウト)
= 63秒
```

```sh
# CentOS 5
$ cat /proc/sys/net/ipv4/tcp_syn_retries
5
# 結果
0秒(最初のSYN)
+  3秒(1回)
+  6秒(2回)
+ 12秒(3回)
+ 24秒(4回)
+ 48秒(5回)
+ 96秒(タイムアウト)
= 189秒
```

```sh
# Ubuntu 19.10
$ cat /proc/sys/net/ipv4/tcp_syn_retries
6
# 結果
0秒(最初のSYN)
+  1秒(1回)
+  2秒(2回)
+  4秒(3回)
+  8秒(4回)
+ 16秒(5回)
+ 32秒(6回)
+ 64秒(タイムアウト)
= 127秒
```

## TCP_TIMEOUT_INIT値をソースで確認

```sh
# CentOSの場合
yum install -y kernel-devel

# ubuntuの場合
apt install -y linux-source
```


```sh:ソース確認
# CentOS6.9の場合
vim -R /usr/src/kernels/2.6.32-754.23.1.el6.x86_64/include/net/tcp.h

# Ubuntu19.10の場合
vim -R /usr/src/linux-headers-5.3.0-19/include/net/tcp.h
```

* CentOS6.9 も Ubuntu19.10 も同じ1秒だった。

![スクリーンショット_2019-10-23_13-14-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/8852f2fe-037e-2805-a1d3-430a9f77911f.png)

* CentOS 5 では以下のように 3秒

![スクリーンショット_2019-10-23_13-29-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/ea9ad14b-d350-be5a-49f9-271a6794c7af.png)


### TCP SYN のリトライ回数を変更する方法

```sh
$ cat /proc/sys/net/ipv4/tcp_syn_retries 
5

$ sudo sh -c "echo 6 > /proc/sys/net/ipv4/tcp_syn_retries"

$ cat /proc/sys/net/ipv4/tcp_syn_retries 
6
```

* 恒久的に変える場合

CentOS6以降から /etc/sysctl.d/ があります。
CentOS5では /etc/sysctl.conf に書き込みましょう。

```sh:/etc/sysctl.d/custom.confに追記
net.ipv4.tcp_syn_retries = 6
```

```sh:再起動せずに適用したい場合
sysctl -p
```

## docker

* http://docs.docker.jp/engine/reference/commandline/run.html#sysctl

```sh
# CentOS8コンテナ で 標準のタイムアウト値が 1m15.530s から 6m12.036s に増えたことを確認した。
docker run \
 --sysctl net.ipv4.tcp_syn_retries=8
(略)
```

## 参考

* [Man page of TCP](https://linuxjm.osdn.jp/html/LDP_man-pages/man7/tcp.7.html)

> tcp_syn_retries (integer; default: 5; Linux 2.2 以降)
    アクティブな TCP 接続に初期 SYN の再送を試みる最大回数。 この数値は 255 よりも大きくすべきではない。 デフォルトの値は 5 で、およそ 180 秒に対応する。 

* [TCPの再送時間について | nonbiriEnginnerBLOG](https://blog.hashihei.com/2019/02/02/tcp%E3%81%AE%E5%86%8D%E9%80%81%E6%99%82%E9%96%93%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/)

* [LinuxのTCP SYNの再送間隔の初期値が3秒から1秒に変更されていた - 元RX-7乗りの適当な日々](https://www.na3.jp/entry/20131129/p1)

* [JF: Linux Kernel 2.4 Documentation: ip-sysctl.txt](http://archive.linux.or.jp/JF/JFdocs/kernel-docs-2.4/networking/ip-sysctl.txt.html)