TCP 통신 직접 만들어 보기(raw) / tcping.py에 대해서 정리한다.
! 로우 소켓을 이용한 TCP 통신을 직접 만들어봄으로써 TCP 통신 과정을 이해한다.
1. tcp 동기화
2. 데이터 송/수신
3. 동기화 해제
- raw 패킷으로 TCP 통신 직접 구현
* 직접 만들어보면서 TCP 통신을 이해하는 과정이기 때문에 순서대로 하나씩 구현 해봤다.
* TCP 통신을 하기 위해서 이전에 만들었던 TCP 에코서버를 사용했다.
* 클라이언트 측에서 SYN 패킷을 보내면 서버와 3-way handshake 과정을 거치고 서로 간의 세션 연결이 되면
클라이언트 측에서 'hello'라는 데이터를 PSH+ACK을 보내게 되고 에코 서버이기 때문에
클라이언트가 보낸 데이터를 그대로 다시 보내주게 된다. 그 이후에 서버쪽에서 close()가 실행 되면서 FIN을
보내면 클라이언트는 ACK로 응답해주고 마찬가지로 FIN을 서버에게 보낸다음 서버가 ACK 응답을 하게 되면
서로 간의 세션 연결이 종료된다.
( 실습 했던 내용을 말로 그대로 풀어쓴 내용이다 )
서버 ↔ 클라이언트 TCP 통신
( 위에 TCP 통신 실습 내용을 간단하게 정리하면 아래와 같고 서버와 클라이언트를 색으로 구분했다 )
* 세션 연결 과정 ( 3-way handshake ) : SYN -> SYN + ACK -> ACK
데이터 송/수신 과정 : PSH + ACK -> ACK
세션 종료 과정 ( 4-way handshake ) : FIN -> ACK -> FIN -> ACK
( 저번에도 적어놨지만 세션 종료 과정에는 꼭 4-way handshake 상황만 있는게 아니라 3번이나 1번만에 끝나는 상황들도 있다 )
tcping.py
from header.eth import *
from header.ip import *
from header.tcp import *
from header.packet import *
import socket
import struct
import random
def make_chksum( header ):
size = len( header )
if size % 2:
header = header + b'\x00'
size = len( header )
size = size // 2
header = struct.unpack('!' + str(size) + 'H', header )
chksum = sum( header )
carry = chksum & 0xFF0000
carry = carry >> 16
while carry != 0:
chksum = chksum & 0xFFFF
chksum = chksum + carry
carry = chksum & 0xFF0000
carry = carry >> 16
chksum = chksum ^ 0xFFFF
return chksum
port = random.randrange( 1, 65535 )
client_seq = random.randrange( 1, 4000000000 )
server_seq = 0
sock = socket.socket( socket.AF_PACKET, socket.SOCK_RAW )
sock.bind( ('eth0', socket.SOCK_RAW) )
eth = Eth()
ip = Ip()
tcp = Tcp()
tcp.src = port
tcp.dst = 63751
tcp.seq = client_seq
tcp.ack = 0
tcp.flag = 2
tcp.length = 0
tcp.window_size = 65535
tcp.chksum = 0
tcp.point_or_dummy = 0
tcp.data = ''
tcp.length = len( tcp.header )
ip.ver = 4
ip.length = 20
ip.service = 0
ip.total = ip.length + tcp.length
ip.id = 0x1234
ip.flag = 0
ip.offset = 0
ip.ttl = 64
ip.type = 6
ip.chksum = 0
ip.src = '192.168.30.112'
ip.dst = '192.168.30.116'
ip.chksum = make_chksum( ip.header )
length = struct.pack('!H', tcp.length)
pseudo_header = ip._src + ip._dst + b'\x00' + ip._type + length + tcp.header
tcp.chksum = make_chksum( pseudo_header )
eth.dst = 00:0c:29:a0:43:a2
eth.src = 00:0C:29:DC:F9:73
eth.type = 0x0800
# SYN
sock.send( eth.header + ip.header + tcp.header )
packet=''
while True:
data, addr = sock.recvfrom( 65535 )
packet = Packet( data )
if packet.eth.type == 0x0800 and packet.ip.dst == '192.168.30.112' and packet.ip.type == 6 \
and packet.tcp.dst == port and packet.tcp.ack == client_seq + 1:
print( packet.ip.src + ':' + str(packet.tcp.src) + ' -> ' + \
packet.ip.dst + ':' + str(packet.tcp.dst) )
print( "seq: " + str( packet.tcp.seq ) + ' | ' + "ack: " + str( packet.tcp.ack ) )
print( "flag: " + str( packet.tcp.flag ) )
# SYN/ACK
break
server_seq = packet.tcp.seq
client_seq = client_seq + 1
server_seq = server_seq + 1
tcp.seq = client_seq
tcp.ack = server_seq
tcp.chksum = 0
tcp.flag = 16
tcp.length = len( tcp.header )
length = struct.pack('!H', tcp.length)
pseudo_header = ip._src + ip._dst + b'\x00' + ip._type + tcp.header
tcp.chksum = make_chksum( pseudo_header )
# ACK
sock.send( eth.header + ip.header + tcp.header )
client_seq = client_seq
server_seq = server_seq
tcp.seq = client_seq
tcp.ack = server_seq
tcp.chksum = 0
tcp.length = 0
tcp.flag = 24
tcp.data = 'hello'
tcp.length = len( tcp.header ) - len( tcp.data )
ip.total = len( ip.header ) + len( tcp.header )
ip.chksum = 0
ip.chksum = make_chksum( ip.header )
length = tcp.length + len(tcp.data)
length = struct.pack('!H', length)
pseudo_header = ip._src + ip._dst + b'\x00' + ip._type + tcp.header
tcp.chksum = make_chksum( pseudo_header )
# PSH/ACK
sock.send( eth.header + ip.header + tcp.header )
packet=''
while True:
data, addr = sock.recvfrom( 65535 )
packet = Packet( data )
if packet.eth.type == 0x0800 and packet.ip.dst == '192.168.30.112' and packet.ip.type == 6 \
and packet.tcp.dst == port and packet.tcp.ack == client_seq + len(tcp.data):
print( packet.ip.src + ':' + str(packet.tcp.src) + ' -> ' + \
packet.ip.dst + ':' + str(packet.tcp.dst) )
print( "seq: " + str( packet.tcp.seq ) + ' | ' + "ack: " + str( packet.tcp.ack ) )
print( "flag: " + str( packet.tcp.flag ) )
# ACK
break
client_seq = client_seq + len( tcp.data )
packet=''
while True:
data, addr = sock.recvfrom( 65535 )
packet = Packet( data )
if packet.eth.type == 0x0800 and packet.ip.dst == '192.168.30.112' and packet.ip.type == 6 \
and packet.tcp.dst == port and packet.tcp.ack == client_seq:
print( packet.ip.src + ':' + str(packet.tcp.src) + ' -> ' + \
packet.ip.dst + ':' + str(packet.tcp.dst) )
print( "seq: " + str( packet.tcp.seq ) + ' | ' + "ack: " + str( packet.tcp.ack ) )
print( "flag: " + str( packet.tcp.flag ) )
# PSH/ACK
break
server_seq = server_seq + len( packet.tcp.data )
tcp.seq = client_seq
tcp.ack = server_seq
tcp.chksum = 0
tcp.length = 0
tcp.flag = 16
tcp.data = ''
tcp.length = len( tcp.header ) - len( tcp.data )
ip.total = len( ip.header ) + len( tcp.header )
ip.chksum = 0
ip.chksum = make_chksum( ip.header )
length = tcp.length + len(tcp.data)
length = struct.pack('!H', length)
pseudo_header = ip._src + ip._dst + b'\x00' + ip._type + tcp.header
tcp.chksum = make_chksum( pseudo_header )
# ACK
sock.send( eth.header + ip.header + tcp.header )
packet=''
while True:
data, addr = sock.recvfrom( 65535 )
packet = Packet( data )
if packet.eth.type == 0x0800 and packet.ip.dst == '192.168.30.112' and packet.ip.type == 6 \
and packet.tcp.dst == port and packet.tcp.ack == client_seq:
print( packet.ip.src + ':' + str(packet.tcp.src) + ' -> ' + \
packet.ip.dst + ':' + str(packet.tcp.dst) )
print( "seq: " + str( packet.tcp.seq ) + ' | ' + "ack: " + str( packet.tcp.ack ) )
print( "flag: " + str( packet.tcp.flag ) )
# FIN
break
server_seq = server_seq + 1
tcp.seq = client_seq
tcp.ack = server_seq
tcp.chksum = 0
tcp.flag = 16
tcp.data = ''
tcp.length = len( tcp.header )
ip.total = len( ip.header ) + len( tcp.header )
ip.chksum = 0
ip.chksum = make_chksum( ip.header )
length = struct.pack('!H', tcp.length)
pseudo_header = ip._src + ip._dst + b'\x00' + ip._type + tcp.header
tcp.chksum = make_chksum( pseudo_header )
# ACK
sock.send( eth.header + ip.header + tcp.header )
tcp.seq = client_seq
tcp.ack = server_seq
tcp.chksum = 0
tcp.flag = 1
tcp.data = ''
tcp.length = len( tcp.header )
ip.total = len( ip.header ) + len( tcp.header )
ip.chksum = 0
ip.chksum = make_chksum( ip.header )
length = struct.pack('!H', tcp.length)
pseudo_header = ip._src + ip._dst + b'\x00' + ip._type + tcp.header
tcp.chksum = make_chksum( pseudo_header )
# FIN
sock.send( eth.header + ip.header + tcp.header )
packet=''
while True:
data, addr = sock.recvfrom( 65535 )
packet = Packet( data )
if packet.eth.type == 0x0800 and packet.ip.dst == '192.168.30.112' and packet.ip.type == 6 \
and packet.tcp.dst == port and packet.tcp.ack == client_seq + 1:
print( packet.ip.src + ':' + str(packet.tcp.src) + ' -> ' + \
packet.ip.dst + ':' + str(packet.tcp.dst) )
print( "seq: " + str( packet.tcp.seq ) + ' | ' + "ack: " + str( packet.tcp.ack ) )
print( "flag: " + str( packet.tcp.flag ) )
# ACK
break
'프로그래밍 > NETWORK HACKING' 카테고리의 다른 글
[네트워크 보안] DHCP 동작 및 역이용 스니핑 / DNS 개념 (0) | 2017.07.20 |
---|---|
[네트워크 보안] DHCP / wireshark 사용법 (0) | 2017.07.20 |
[네트워크 보안] TCP SYN Flooding (0) | 2017.07.15 |
[네트워크 보안] TCP 포트 스캔 / TCP SYN 패킷 전송 (0) | 2017.07.14 |
[네트워크 보안] 스니퍼를 이용한 TCP 이해 (0) | 2017.07.12 |
댓글