TCPのコネクション拒否 (connection refused)
TCPでデータを転送する場合、データの転送を行う前にコネクションを確立する必要があります。
TCPのコネクション拒否は、TCPクライアントがコネクション確立要求に対して、コネクションを拒否する要求が返った場合に発生します。
TCPのコネクションについての詳細は以下のエントリを参照してください。
上記のコネクション確立要求に対して、コネクションを拒否する要求が返る振る舞いをtcpdumpコマンドで実際に確認して行きます。
tcpdumpで理解するTCPのコネクション拒否 (connection refused)
使用するネットワークコマンド
本エントリでは、以下のLinuxコマンドを使用します。
- tcpdump
- ネットワーク上のパケットを出力するために使用します。
- nc,telnet
- tcpサーバー/クライアントとして使用します。
- netstat
- コネクションの状態を確認するために使用します。
上記コマンドがインストールされていない場合、以下のコマンドでインストールします。
$ sudo yum -y install tcpdump nc telnet net-tools
1. コネクション確立の拒否
一番単純にコネクション確立の拒否を確認する方法はListenしていないportにコネクション確立要求を発行することです。
ここでは、12345portにコネクション確立要求を発行します。
$ telnet 127.0.0.1 12345
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
$
即時にTCPのコネクション拒否(Connection refused)が発生します。
これで、TCPのコネクション拒否をtcpdumpで確認する準備ができました。
2. tcpdumpでのコネクション拒否を目視する。
tcpdumpコマンドでlocal interfaceのport12345を指定して実行します。
$ sudo tcpdump -i lo -nnn port 12345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
1.の手順と同様にtelnetコマンドを実行します。
$ telnet 127.0.0.1 12345
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
$
tcpdumpの出力を確認します。
12:43:40.125255 IP 127.0.0.1.60642 > 127.0.0.1.12345: Flags [S], seq <seq num> ...
12:43:40.125277 IP 127.0.0.1.12345 > 127.0.0.1.60642: Flags [R.], seq 0, ...
上記のtcpdumpの出力フォーマットは以下の通りです。
timestamp src > dst: flags data-seqno
- timestamp: タイムスタンプ
- src: 送信元IP.ポート
- dst: 送信先IP.ポート
- flags: フラグ S (SYN), R(RST), ‘.’ (no flags)
- data-seqno: シーケンス番号(上記はSYNパケットのみなので初期シーケンス番号)
上記のパケットキャプチャは、TCPクラアントがコネクション確立要求(SYN)を送信したが、対象のportがListenしていないため、コネクション拒否(RST)が返ったことを示します。
以下はシーケンスの概要です。
おまけ: straceコマンドでTCPのコネクション拒否(Connection refused)を確認する
straceコマンドにtelnetコマンドを渡してListenしていないportにコネクション確立要求を送信します。以下のようにconnectシステムコールにECONNREFUSED(Connection refused)が返っていることが確認できます。
[vagrant@centos601 ~]$ strace -Ttt -e trace=network telnet 127.0.0.1 12345
Trying 127.0.0.1...
00:31:31.345795 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 <0.000021>
00:31:31.345912 setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0 <0.000013>
00:31:31.345956 connect(3, {sa_family=AF_INET, sin_port=htons(12345), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused) <0.000057>
telnet: connect to address 127.0.0.1: Connection refused
00:31:31.346192 +++ exited with 1 +++
$
$ man 2 connect
...
ECONNREFUSED
No-one listening on the remote address.
...
$
$
$ grep ECONNREFUSED /usr/include/asm-generic/errno.h
#define ECONNREFUSED 111 /* Connection refused */
$