
TCP : 연결지향적
데이터전송전>
Browser와 Server 간의 연결을 성립하는 과정이 데이터를 전송하는 과정전에 이루어짐
ex) 전화통화시 통화내용을 말하기 전에 상대편을 확인하는 작업과 동일
통신선로를 만들기 위해서는 3번의 데이터 전송이 일어나는데
이것을 three way handshake라고 함
그림참조 ) three way handshake

--> 정식데이터는 통신선로를 통해서 교환
--> TCP : 연결 지향 프로토콜이라고 부름
>> UDP 는 이러한 과정이 없이 단순히 데이터 전송
-->Datagram protocol
>.TCP Header : 최소 20바이트 만족 - 최대 60바이트
(가변적)
1) 출발지 포트(2byte)
2) 도착지 포트 (2byte)
* 중요
*3) Sequence Number(4byte)
*4) Acknouledge Number(4byte)
5) header length
*6) flag(6개 종류가 있다)
(2byte)
0 0 0 0 0 0
FIN(연결을 해지할때 사용)
SYN (동기화 요청)
RESET ( 세션을 초기화 )
PSH(push --> 데이터를 전달할때 >>cash 를 해놓고 데이터 통신 )
ACK(응답할때 사용)
URG( 긴급하게 전달할 데이터 )
7) window size (2byte) --> 실제 전송할 데이터의 크기
- QoS
8) checksum (2byte)
9) dummy(2byte) -->더미를 넣어서 크기를 맞춰준다
[ #vi tcp.py ]
import struct
class Tcp:
def __init__(self,data=None):
if data != None:
(self.src,)=struct.unpack('!H',data[:2])
(self.dst,)=struct.unpack('!H',data[2:4])
(self.seq,)=struct.unpack('!L',data[4:8])
(self.ack,)=struct.unpack('!L',data[8:12])
self.len=data[12]
self.len>>=2
self.flag=data[13]
(self.window,)=struct.unpack('!H',data[14:16])
(self.chksum,)=struct.unpack('!H',data[16:18])
(self.dummy,)=struct.unpack('!H',data[18:20])
self.data=data[20:]
else:
self.src=b''
self.dst=b''
self.sq_num=b''
self.ack_num=b''
self.len=b''
self.flag=b''
self.window=b''
self.chksum=b''
self.dummy=b''
self.data=b''
def get_header(self):
return self.src+self.dst+self.sq_num+self.ack_num+self.len+self.flag+self.window+self.chksum+self.un
def set_src(self,src):
self.src=struct.pack('!H',src)
def set_dst(self,dst):
self.dst=struct.pack('!H',dst)
def set_sq_num(self,sq_num):
self.sq_num=struct.pack('L',sq_num)
def set_ack_num(self,ack_num):
self.ack_num=struct.pack('!L',ack_num)
def set_len(self,len):
self.len=struct.pack('!B',len)
def set_flag(self,flag):
self.flag=struct.pack('!B',flag)
def set_window(self,window):
self.window=struct.pack('!H',window)
def set_chksum(self,chksum):
self.chksum=struct.pack('!H',chksum)
def set_dummy(self,dummy):
self.un=struct.pack('!H',dummy)
def set_data(self,data):
self.data=data.encode()
>> tcp 확인

[ #vi sniffer.py ]
import socket
import struct
import time
import ip as _ip
import eth as _eth
import udp as _udp
import tcp as _tcp
sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
sock.bind(('eth0', socket.SOCK_RAW))
while(True):
(raw,_) = sock.recvfrom(65535)
eth=_eth.Eth(raw[:14])
ip=_ip.Ip(raw[14:34])
if eth.type=='0x0800'and (ip.dst=='192.168.219.180'or ip.src=='192.168.219.180'):
if ip.type == 1 :
print('src:{:s} -> dst:{:s} '.format(eth.src,eth.dst))
print('src:{:s} -> dst:{:s} ,type:{:d}'.format(ip.src,ip.dst,ip.type))
(type,)=struct.unpack('!B', raw[34:35])
(code,)=struct.unpack('!B', raw[35:36])
print('type:{:d}, code:{:d}'.format(type,code))
if ip.type==17:
udp=_udp.Udp(raw[34:])
print('src:{:s} -> dst:{:s} '.format(eth.src,eth.dst))
print('src:{:s} -> dst:{:s} ,type:{:d}'.format(ip.src,ip.dst,ip.type))
print('src:{:d} -> dst:{:d}'.format(udp.src,udp.dst))
if ip.type==6:
tcp=_tcp.Tcp(raw[34:])
# print(raw[34:])
print('src:{:s} -> dst:{:s} '.format(eth.src,eth.dst))
print('src:{:s} -> dst:{:s} ,type:{:d}'.format(ip.src,ip.dst,ip.type))
print('src : {:d} -> dst :{:d} seq: 0x{:08x} | ack : 0x{:08x}:{:06b} '.format(tcp.src,tcp.dst,tcp.sq_num,tcp.ack_num,tcp.flag))
print()
>> 3way handshake ( 프로토콜 ) 기법
모든 tcp 통신
(ex_전화를 거는 것 )
1_SIN flag 활성화
flag : 000010
> SYN flag 활성화
ISN (sq_num와 같음) : 초기 시퀀스 넘버
( 사용자를 식별하는 세션 번호 )
2_ 서버응답
flag : 010010
>SYN/ACK flag활성화
ack -> client가 요청한 동기화 요청에 대한 응답
이때
sq_num : 서버의 ISN
ACK 의 역할 : 내가보낸 동기화요청에대한 응답인지를 확인
sq_num + : 규칙이있음 계속 변함
자기가 보낸 data 크기만큼 +해서 변화
3_ ACK만 세팅
flag : 010000
ACKNUM은 2의 시퀀스 넘버에 +1크기해서 돌려줌
SQNUM 은 1의 시퀀스 넘버에 +1 크기해서 돌려줌
>>> SYN-->SYN
ACK--> ACK
1) 192.168.219.130서버에서 tcp_server.py 을 실행
2) 192.168.219.115 하나는 sniffer.py 실행
3) 192.168.219.115 # python3 tcp_client.py 192.168.219.115 10000 을 실행
