리뷰
-
클라우드 네트워킹
-
쿠버네티스 네트워킹
- 컨테이너 네트워크 인터페이스 > cilium, flannel
-
그 중에서도 리눅스 네트워킹
- bridge, vlan, vxlan, ipvlan, veth(표준 없음)
- netfilter
OSI 7 Layer
-
Physical Layer
-
Data Link
-
Network
-
Transport
- L4
- 엔드포인트는 프로세스
- 엔드포인트들끼리 데이터를 어떻게 주고 받을까
- 포트 뿐만 아니라 연결지향, 비연결 지향할 것 인지
-
Session
- L5
- 내가 의도한대로 데이터를 보내거나, 정지하거나를 정의
-
Presentaion
-
Application
TCP / IP - 2347!
- Internet protocol suite
- 4계층모델
- TCP, UDP, IP 기반
- 초기에 미국 국방부(DoD)에서 자금을 지원하여 DoD 모델이라고도 불림
- 1982.03. 미국 군용 컴퓨터 네트워킹 표준 선언
- IETF 인터넷 표준 (RFC 1122)
- Physical 계층을 덧붙여서 5계층으로 설명하기도함
- 보낼 때는 아래 방향으로
- 받을 때는 위의 방향으로
- Internet, Transport Layer 의 목적
Wireshark 을 이용한 Raw Socket Programming
scp 작업을 피하기 위한 wireshark ssh 설정
- server adress 에
ubuntu@ec2-3-38-182-98.ap-northeast-2.compute.amazonaws.com
- eth0 의 덤프를 뜰 것이므로 Capture 설정
- Remote capture filter 비워둘 것
- 이것이 EC2 서버인지를 어떻게 알까?
- 지금은 icmp 를 사용하지 않는 상태
- icmp 를 보내 보면 됨
- icmp 를 보내고 있음 - google.co.kr 에 핑때리는 중
scapy로 보낸 packet과 ping command로 보낸 차이 찾기
- ping command - second instance
- ping command - google.co.kr
- scapy - mySocket / mySocket2
ping command 와 scapy로 보낸 덤프의 차이
- ICMP header 의 정보와 ping manual 로 보면 알 수 있음
- ICMP header
차이점
- Length 가 다름
- Ping 은 데이터를 보내줌
ping 처럼 scapy로 ICMP 패킷을 똑같이 만들어 보기
- id, seq, data
- data 에 euijoo 를 싣어서 보내보기
>>> data = 'euijoo'
>>> myPacket = IP(dst='172.31.1.49')/ICMP()/Raw(load=data)
>>> myPacket
<IP frag=0 proto=icmp dst=172.31.1.49 |<ICMP |<Raw load='euijoo' |>>>
>>> send(myPacket)
.
Sent 1 packets.
실습
from scapy.all import *
from threading import Thread
ICMP_TYPE_AND_CODE = {
3: range(0, 16),
5: range(0, 4),
11: range(0, 2),
12: range(0, 3),
43: range(0, 5),
}
def work(p, result):
reply = sr1(p, timeout=0.05)
if reply:
result.append(reply)
ip = IP(dst='google.co.kr')
result = []
total_case = 0
thread_pool = []
for i in range(0, 256):
if ICMP_TYPE_AND_CODE.get(i):
for j in ICMP_TYPE_AND_CODE.get(i):
p = ip/ICMP(type=i, code=j)/'kakaocloudschool'
t = threading.Thread(target=work, args=(p, result))
t.start()
thread_pool.append(t)
total_case += 1
else:
p = ip/ICMP(type=i, code=0)
t = threading.Thread(target=work, args=(p, result))
t.start()
thread_pool.append(t)
total_case += 1
for thread in thread_pool:
thread.join()
print("total_case = ", total_case)
print("reply_case = ", len(result))
print("====================")
for i in result:
print(i)
TCP / UDP
TCP / UDP 공통점
- 포트 번호를 이용하여 주소를 지정
- 데이터 오류 검사를 위한 체크섬이 존재한다
TCP / UDP 차이점
-
통신 유무
- TCP
- 연결이 성공해야 통신 가능 - 연결형 protocol
- UDP
-
데이터의 경계
- TCP
- 데이터의 경계를 구분하지 않음 - Byte Stream
- UDP
-
신뢰성
-
통신 방법
TCP handshake
각자 상대방으로 부터 받은 시퀀스 번호에 1을 더해 보낸다
- 클라이언트에서 2개의 데이터를 전송
- 시퀀스 넘버: 클라이언트에서 랜덤으로 생성한 시퀀스 넘버 x
- SYN 플래그: 연결 설정 요청 플래그
- 서버에서는 4개의 데이터를 전송
- 시퀀스 넘버: 서버에서 랜덤으로 생성한 시퀀스 넘버 y
- ACK 넘버: 클라이언트로부터 받은 시퀀스 넘버에 1을 더한 값, 즉 x + 1
- SYN 플래그: 서버에서 클라이언트로 연결 설정 요청을 나타내는 플래그
- ACK 플래그: 상대방이 이전에 보낸 데이터를 제대로 수신했음을 나타내는 플래그
- 클라이언트에서 다시 3개의 데이터를 전송
- 시퀀스 넘버: 처음 보냈던 시퀀스 넘버 x
- ACK 넘버: 서버에서 보낸 시퀀스 넘버에 1을 더한 값, 즉 y + 1
- ACK 플래그: 상대방이 이전에 보낸 데이터를 제대로 수신했음을 나타내는 플래그
연결이 설정됐으면 데이터 교환 과정을 거친다
- 이 과정에서도 클라이언트와 서버는 데이터를 잘 수신했다는 ACK 넘버를 상대방에게 보내는데, 데이터 교환 과정에서는 상대방에게서 마지막으로 받은 시퀀스 넘버에 수신한 데이터(세그먼트)의 바이트 수 + 1 만큼을 더한 값을 보내게 된다.
- 클라이언트에서 서버로 데이터를 전송
- 시퀀스 넘버: 세그먼트의 바이트 길이만큼 다음 시퀀스 넘버를 증가시킴
- ACK 플래그: 상대방이 이전에 보낸 데이터를 제대로 수신했음을 나타내는 플래그
- 서버에서 클라이언트로 데이터를 전송
- 시퀀스 넘버: 세그먼트의 바이트 개수만큼 다음 시퀀스 넘버를 증가시킴
- ACK 넘버: 상대방으로 처음 받은 시퀀스 넘버에 현재까지 수신한 바이트 길이를 더한 값 + 1
- ACK 플래그: 상대방이 이전에 보낸 데이터를 제대로 수신했음을 나타내는 플래그
연결 종료 단계는 4단계의 핸드셰이크 과정을 거친다
- 상대방은 연결이 끊어졌는지 지속되고 있는지를 알 방법이 없기 때문에 종료과정은 반드시 필요하다
- 종료 단계에서는 FIN 플래그를 교환하는 것에 의의를 두며, 연결 설정 단계 처럼 상대방에게서 받은 시퀀스 번호에 1을 더해 ACK 넘버를 전송한다.
- 클라이언트에서 서버로 4개의 데이터를 전송
- 시퀀스 넘버, ACK 넘버, ACK 플래그
- FIN 플래그: 종료 의사를 표현하는 플래그
- 서버에서 클라이언트의 종료 의사를 수신
- 서버에서 데이터를 모두 보낸 경우, 4개의 데이터를 전송
- 시퀀스 넘버, ACK 넘버, ACK 플래그
- FIN 플래그: 종료 의사를 표현하는 플래그
- 클라이언트에서 서버의 종료 의사를 수신
참고
https://wormwlrm.github.io/2021/09/23/Overview-of-TCP-and-UDP.html
https://velog.io/@hidaehyunlee/TCP-%EC%99%80-UDP-%EC%9D%98-%EC%B0%A8%EC%9D%B4