创建python 脚本 self_connect.py
#!/usr/bin/python
import errno
import socket
import sys
import time
if len(sys.argv) < 2:
print "must input port."
print "port should in net.ipv4.ip_local_port_range"
exit()
port = int(sys.argv[1])
for i in range(65536):
try:
sock = socket.create_connection(("127.0.0.1", port))
print "connected", sock.getsockname(), sock.getpeername()
time.sleep(60*60) # to netstat port
except socket.error, e:
if e.errno != errno.ECONNREFUSED:
print e.errno, errno.ECONNREFUSED
break
执行该脚本,可以看到结果为:
从截图可以看到,同一ip下的同一端口,相互连接。
这不是内核bug
2.1 连接的时候,没有指定本地端口(local port),Linux系统会在 net.ipv4.ip_local_port_range 指定的端口范围内分配一个未被占用的端口。比如选择了端口N,如果N端口拒绝连接,就会发送包含RST标志的TCP报文段,本地
2.2 TCP协议支持同时打开
(RFC 793 TRANSMISSION CONTROL PROTOCOL 3.4. Establishing a connection)
上面python脚本过程说明: python self_connection.py 33000
ip 都是127.0.0.1
(1) 内核选择端口N与port: 33000 连接, 33000端口未打开,内核给 N端口返回 RST 标示的TCP报文段。
(2) 选择端口N+1,N+2,…, 直到 33000
33000 ----------->(SYN) 33000
33000 (ACK)<---------- 33000
33000 端口 ENSTABLISHED
自连接
3.1 TCP 同时打开
(1) TCP 协议允许同时打开: RTC793 TRANSMISSION CONTROL PROTOCO figure 8
TCP A TCP B
1. CLOSED CLOSED
2. SYN-SENT --> 100> ...
3. SYN-RECEIVED <-- 300> <-- SYN-SENT
4. ... 100> --> SYN-RECEIVED
5. SYN-RECEIVED --> 100>301> ...
6. ESTABLISHED <-- 300>101> <-- SYN-RECEIVED
7. ... 101>301> --> ESTABLISHED
Simultaneous Connection Synchronization
Figure 8.
3.2 自连接
(1) 根据tpcdump 查看TCP报文段(握手和挥手)
21:45:17.452481 IP 127.0.0.1.33000 > 127.0.0.1.33000: Flags [S], seq 2122155273, win 43690, options [mss 65495,sackOK,TS val 214381031 ecr 0,nop,wscale 7], length 0
21:45:17.452485 IP 127.0.0.1.33000 > 127.0.0.1.33000: Flags [S.], seq 2122155273, ack 2122155274, win 43690, options [mss 65495,sackOK,TS val 214381031 ecr 214381031,nop,wscale 7], length 0
21:45:17.452488 IP 127.0.0.1.33000 > 127.0.0.1.33000: Flags [.], ack 2122155274, win 342, options [nop,nop,TS val 214381031 ecr 214381031], length 0
21:45:23.601611 IP 127.0.0.1.33000 > 127.0.0.1.33000: Flags [F.], seq 2122155274, ack 2122155274, win 342, options [nop,nop,TS val 214382568 ecr 214381031], length 0
21:45:23.601624 IP 127.0.0.1.33000 > 127.0.0.1.33000: Flags [.], ack 2122155275, win 342, options [nop,nop,TS val 214382568 ecr 214382568], length 0
SYN报文段和FIN报文段比较特殊,会消耗一个序列号
(2) TCP 协议允许自连接
RTC793 TRANSMISSION CONTROL PROTOCO figure 7
TCP A TCP B
1. CLOSED LISTEN
2. SYN-SENT --> <SEQ=100><CTL=SYN> --> SYN-RECEIVED
3. ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED
4. ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK> --> ESTABLISHED
5. ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED
Basic 3-Way Handshake for Connection Synchronization
Figure 7.
连接以后,根据连接的socket获取本地和目标的地址(ip+port),然后比较地址是否相等即可。
根据 getpeername和getsockname 分别获取目标和本地地址。
http://gad.qq.com/article/detail/26391
https://blog.csdn.net/wohenfanjian/article/details/51867950
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=24716553&id=5602432
https://tools.ietf.org/html/rfc793#section-3.4