iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
0

上一回說了這三個函數_buildEthHeader()、 _buildIPHeader()、 _buildTCPHeader(tcp_len, seq, ack_num, flags, window) 如何建立header,接下來說如何利用這三個函數完成三方交握,先複習一下三方交握的的過程

  1. HostA 傳送SYN過去 HostB
  2. HostB 收到SYN,傳ACK和SYN回去 HostA
  3. HostA 收到ACK和SYN,傳送ACK回去給 HostB,連線成立

接下來程式碼有點多,建議打開https://gist.github.com/kaichiachen/283f1b57e517f9ed558de6c2d15daf62 配合著看

第一步,我們要從client發送syn,配合著程式裡的send_syn函數

packet = eth_header + ip_header + _buildTCPHeader(tcp_len=5, seq=0, ack_num=0, flags=2, window=29200)
sock.send(packet)

其中seq和ack_num可以隨意給,但是flags必須設定為2,代表2^1,一次方代表flags第二個參數SYN,然後tcp_len必須是5以下,如果有特殊的需求才會5以上,詳情可以差維基百科
第二步
立即監聽從server端發過來的ACK和SYN,如何收packet在前面已經講過,這部分先略過,只要記得判斷packet的時候,tcp裡header的flag必須是18,代表2^4 + 2^1,如果收到這個packet才有下一步
第三步
監聽到來自server端的ACK和SYN,要立即發送ACK回去,否則server端會一直發送直到timeout,此時,發送回去的ACK裡的ACK_NUM和SYN不能隨便亂設定了,必須根據server端傳過來的ACK_NUMS和SEQ,這裡傳回去的ACK_NUM和SEQ分別為server的SEQ+1和ACK_NUM

self.seq = server.ack_num
self.ack_num = server.seq+1

所以程式如下

packet = eth_header + ip_header + _buildTCPHeader(tcp_len=5, seq=server.ack_num, ack_num= server.seq+1, flags=16, window=29200)
sock.send(packet)

最後來實驗一下,我們在hostA上跑監聽tcp port=80的server
nc -l 172.17.0.5 80
然後在router啟動我們的封包監聽script
Python3 main.py
最後,在hostB上跑tcp的handshake,跑之前需要先把系統自動發出的RST flag封包給擋掉

iptables -t filter -I OUTPUT -p tcp --sport 20 --tcp-flags RST RST -j DROP
Python3 tcp.py

可以看到如下結果,代表我們成功自己實作了三方交握

2020-09-18 11:37:30 AM INFO  Source Mac: 02:42:ac:11:00:02 Destination Mac: 02:42:ac:11:00:05 Protocol: IPv4 Version: 4 Type of Service: 0 Packet ID: 123 TTL: 64 Protocol: TCP Source IP: 172.17.0.2 Destination IP: 172.17.0.5
{'SRC_PORT': 20, 'DEST_PORT': 80, 'SEQ': 0, 'ACK_NUM': 0, 'Flags': '_,_,_,_,_,_,SYN,_', 'RESERVE': 0, 'TCP_LENGTH': 5, 'WINDOW': 29200, 'CHECKSUM': 58692, 'PTR': 0, 'data': b''}
------------------------
2020-09-18 11:37:30 AM INFO  Source Mac: 02:42:ac:11:00:05 Destination Mac: 02:42:ac:11:00:02 Protocol: IPv4 Version: 4 Type of Service: 0 Packet ID: 0 TTL: 64 Protocol: TCP Source IP: 172.17.0.5 Destination IP: 172.17.0.2
{'SRC_PORT': 80, 'DEST_PORT': 20, 'SEQ': 692864110, 'ACK_NUM': 1, 'Flags': '_,_,_,ACK,_,_,SYN,_', 'RESERVE': 0, 'TCP_LENGTH': 6, 'WINDOW': 29200, 'CHECKSUM': 22600, 'PTR': 0, 'data': b''}
------------------------
2020-09-18 11:37:30 AM INFO  Source Mac: 02:42:ac:11:00:02 Destination Mac: 02:42:ac:11:00:05 Protocol: IPv4 Version: 4 Type of Service: 0 Packet ID: 123 TTL: 64 Protocol: TCP Source IP: 172.17.0.2 Destination IP: 172.17.0.5
{'SRC_PORT': 20, 'DEST_PORT': 80, 'SEQ': 1, 'ACK_NUM': 692864111, 'Flags': '_,_,_,ACK,_,_,_,_', 'RESERVE': 0, 'TCP_LENGTH': 5, 'WINDOW': 29200, 'CHECKSUM': 30586, 'PTR': 0, 'data': b''}

上一篇
Day21 自幹TCP三向交握(1)
下一篇
Day23 題外話 - 如何利用TCP四向交握取得鄰居的Wi-Fi密碼
系列文
那些年還給老師的TCP/IP五層結構 - 用Python進行網路封包分析30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言