1 tcp_tw_reuseとは?
tcp_tw_reuseは、TCPコネクション確立時に使用していたローカルポートをTIME-WAIT状態のソケットで使用できるかどうかを指定するカーネルパラメータです。
tcp_tw_reuseが1の場合、クライアントが時刻T1のときに使用していたローカルポート(P1)を使って、時刻T2でサーバとTCPコネクションを確立することができます。一方、tcp_tw_reuseが2(デフォルト値)の場合、このようなことはできません。クライアントがP1を使ってサーバとTCPコネクションを確立するには、時刻T3でソケットの状態がTIME-WAITからCLOSEDになってからです。なお、TCPの状態については、TCPの各種状態の作り方 - hana_shinのLinux技術ブログを参照してください。
TIME client server | | | | | | T1 IP1,P1 |<-- TCP established connection --->| IP2,P2 | | | | | | | close() |--------------- FIN -------------->| | |<----------- FIN + ACK ------------| | -*- |--------------- ACK -------------->| | | | | | | | | | | | | | | | | | | | | | TIME-WAIT | | | (60s) | | | | | | T2 | | | | | | | | | | | | -*- | | | | | T3 IP1,P1 |<-- TCP established connection --->| IP2,P2 | | | (*) IP1,IP2はIPアドレス、P1,P2はポート番号
(注)本パラメーラを変更すると、システム上の全てのアプリケーションに影響がでます。TCPコネクション単位でTIME-WAIT状態のソケットを再利用できるようにするには、ソケットオプション(SO_REUSEADDR)を使用してください。
2 検証環境
2.1 ネットワーク構成
サーバとクライアントの2台構成です。図中のenp1s0はNICの名前です。
192.168.122.0/24 client(enp1s0) ------------------------------------------(enp1s0) server .177 .68
2.2 版数
サーバとクライアントのAlmaLinuxの版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release AlmaLinux release 8.6 (Sky Tiger)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 4.18.0-372.9.1.el8.x86_64
3 事前準備
クライアントからサーバの11111番ポートにアクセスできるようにするため、TCPの11111番ポートを解放します。なお、firewall-cmdコマンドの使い方は、firewall-cmdの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# firewall-cmd --add-port=11111/tcp
設定を確認します。11111番ポートへのアクセスを許可するルールが追加されたことがわかります。
[root@server ~]# firewall-cmd --list-ports 11111/tcp
カーネルパラメータ(ip_local_port_range)を変更して、クライアントのncプロセスが常に同じローカルポートを使用できるようにします。ここでは、ncプロセスが50001番のローカルポートを使用できるようにします。なお、ip_local_port_rangeの使い方は、カーネルパラメータの使い方(ip_local_port_range編) - hana_shinのLinux技術ブログを参照してください。
[root@client ~]# sysctl -w net.ipv4.ip_local_port_range="50001 50001" net.ipv4.ip_local_port_range = 50001 50001
変更したカーネルパラメータの値を確認します。
[root@client ~]# sysctl -n net.ipv4.ip_local_port_range 50001 50001
4 tcp_tw_reuseが2の場合(デフォルト時)の動作確認
tcp_tw_reuseのデフォルト値は以下のとおりです。
[root@client ~]# sysctl -n net.ipv4.tcp_tw_reuse 2
サーバでncコマンドを実行します。なお、ncコマンドのインストール方法、使い方は、ncコマンドの使い方(ネットワーク実験の幅が広がるなぁ~) - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# nc -kl 11111
クライアントでncコマンドを実行します。ncコマンドを実行すると、サーバ/クライアント間でTCPコネクションが確立されます。
[root@client ~]# nc 192.168.122.68 11111
クライアントでssコマンドを実行します。サーバ/クライアント間でTCPコネクションが確立されていることがわかります(ssコマンド実行結果の一番下の行)。そして、ncプロセスが使用しているローカルポート番号が50001であることがわかります。なお、ssコマンドの使い方は、ssコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@client ~]# ss -natop4 State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=830,fd=5)) ESTAB 0 0 192.168.122.177:22 192.168.122.1:60012 users:(("sshd",pid=1529,fd=5),("sshd",pid=1525,fd=5)) timer:(keepalive,88min,0) ESTAB 0 0 192.168.122.177:22 192.168.122.1:59994 users:(("sshd",pid=1437,fd=5),("sshd",pid=1421,fd=5)) timer:(keepalive,44min,0) ESTAB 0 0 192.168.122.177:50001 192.168.122.68:11111 users:(("nc",pid=1600,fd=3))
Ctrl+cを押下して、ncコマンドを終了します。
[root@client ~]# nc 192.168.122.68 11111 ^C
ncコマンドの終了直後、ssコマンドを実行します。ソケットの状態を確認するとTIME-WAIT状態の残り時間が58秒であることがわかります。
[root@client ~]# ss -natop4 State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=830,fd=5)) ESTAB 0 0 192.168.122.177:22 192.168.122.1:60012 users:(("sshd",pid=1529,fd=5),("sshd",pid=1525,fd=5)) timer:(keepalive,98min,0) ESTAB 0 0 192.168.122.177:22 192.168.122.1:59994 users:(("sshd",pid=1437,fd=5),("sshd",pid=1421,fd=5)) timer:(keepalive,54min,0) TIME-WAIT 0 0 192.168.122.177:50001 192.168.122.68:11111 timer:(timewait,58sec,0)
ssコマンド実行直後、クライアントでncコマンドを実行します。TCPの状態がTIME-WAITなので、ncコマンドが終了してしまいます。TIME-WAIT状態のときは、ncコマンド終了直前に使用していたローカルポートを使ってTCPコネクションを確立することができないことがわかります。
[root@client ~]# nc 192.168.122.68 11111 [root@client ~]#
Ctrl+cを押下して60秒経過したあとssコマンドを実行します。60秒経過したのでTCPの状態がTIME-WAITのソケットがなくなったことがわかります。
[root@client ~]# ss -natop4 State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=830,fd=5)) ESTAB 0 0 192.168.122.177:22 192.168.122.1:60012 users:(("sshd",pid=1529,fd=5),("sshd",pid=1525,fd=5)) timer:(keepalive,97min,0) ESTAB 0 0 192.168.122.177:22 192.168.122.1:59994 users:(("sshd",pid=1437,fd=5),("sshd",pid=1421,fd=5)) timer:(keepalive,53min,0)
再度、ncコマンドを実行します。サーバとTCPコネクションを確立できることがわかります。
[root@client ~]# nc 192.168.122.68 11111
5 tcp_tw_reuseが1の場合の動作確認
TIME-WAIT状態のソケットを利用できるように、カーネルパラメータを変更します。
[root@client ~]# sysctl -w net.ipv4.tcp_tw_reuse=1 net.ipv4.tcp_tw_reuse = 1
設定変更したカーネルパラメータの値を確認します。
[root@client ~]# sysctl -n net.ipv4.tcp_tw_reuse 1
サーバでncコマンドを実行します。
[root@server ~]# nc -kl 11111
クライアントでssコマンドを実行します。
[root@client ~]# nc 192.168.122.68 11111
クライアントでssコマンドを実行します。サーバ/クライアント間でTCPコネクションが確立されていることがわかります(ssコマンド実行結果の一番上の行)。
[root@client ~]# ss -nato4 State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* ESTAB 0 0 192.168.122.177:50001 192.168.122.68:11111 ESTAB 0 0 192.168.122.177:22 192.168.122.1:48296 timer:(keepalive,98min,0) ESTAB 0 0 192.168.122.177:22 192.168.122.1:48298 timer:(keepalive,102min,0)
Ctrl+cを押下して、ncコマンドを終了します。
[root@client ~]# nc 192.168.122.68 11111 ^C
ncコマンドの終了直後、ssコマンドを実行します。ソケットの状態を確認するとTCPがTIME-WAIT状態で、残り時間が58秒であることがわかります。
[root@client ~]# ss -nato4 State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* TIME-WAIT 0 0 192.168.122.177:50001 192.168.122.68:11111 timer:(timewait,58sec,0) ESTAB 0 0 192.168.122.177:22 192.168.122.1:48296 timer:(keepalive,95min,0) ESTAB 0 0 192.168.122.177:22 192.168.122.1:48298 timer:(keepalive,99min,0)
ssコマンド実行直後、クライアントでncコマンドを実行します。今度は、tcp_tw_reuseが有効になっているため、サーバ/クライアント間でTCPコネクションが確立できることがわかります。
[root@client ~]# nc 192.168.122.68 11111
クライアントでssコマンドを実行します。サーバ/クライアント間でTCPコネクションが確立されていることがわかります(ssコマンド実行結果の一番上の行)。
[root@client ~]# ss -nato4 State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* ESTAB 0 0 192.168.122.177:50001 192.168.122.68:11111 ESTAB 0 0 192.168.122.177:22 192.168.122.1:48296 timer:(keepalive,95min,0) ESTAB 0 0 192.168.122.177:22 192.168.122.1:48298 timer:(keepalive,99min,0)
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ
TCPの状態遷移については、TCPの各種状態の作り方 - hana_shinのLinux技術ブログを参照してください。