학사 나부랭이
Network - Internet Protocol 본문
IP
용량이 큰 파일을 서버에서 내려받을 때, 파일은 패킷 단위로 쪼개져 전송되며, 도착지 호스트 기기에서 CPU가 재조립해요. IP 프로토콜은 패킷의 분할과 재조합에서 사용되며 출발지와 목적지의 IP와 라우터 설정을 포함해요.
IP 헤더 구조
그림에서 한 칸은 1bit인데 네트워크 정보를 나타내는 단위에는 4가지가 있어요.
- 1bit = 0|1
- 1byte = 8bits
- 4bits = 1nibble
- 1word = 4bytes
IP 헤더의 각 항목은 다음과 같아요.
- Version: IPv4나 IPv6를 나타내요.
- IHL (IP Header Length): IP 헤더의 길이를 워드 단위로 나타내요.
- TOS (Type Of Service): 서비스에서 우선순위를 지원하도록 라우터에게 요구해요.
- Total Length: 헤더의 총길이를 바이트 단위로 나타내요.
- Identification: 패킷을 결합할 때 사용되는 고윳값이에요. 예를 들어, 분할된 패킷끼리는 같은 값을 가지죠.
- IP Flags: 첫 번째 비트는 0으로, 사용되지 않아요. 두 번째 필드는 Do Not Fragment이며, 값이 1인 경우, 패킷을 분할하지 않죠. 세 번째 필드인 More Fragment는 분할된 패킷들 중, 마지막 패킷이라면 0, 아니면 1을 가져요.
- Fragment Offset: 원본 데이터의 바이트 범위를 나타내요. {단편화할 패킷 크기 - 20bytes(ip 헤더)}/8bytes 크기만큼 증가해요.
- Time To Live: 패킷은 라우터를 거치면서 TTL 값이 1씩 줄어들어요. 네트워크에서 패킷이 계속 라우터를 떠도는 것을 방지하죠. 1byte며, 최댓값은 255이에요.
- Protocol: 상위 계층의 프로토콜을 나타내요. ICMP(=1), TCP(=6), UDP(=17), ESP(==50), AH(=51) 등이 있어요.
- Header Checksu,: 패킷의 오류를 검출해요.
- Source Address: 패킷 출발지의 IP 주소예요. 4bytes며, 각 byte마다 0~255를 나타내므로 0.0.0.0~255.255.255.255 만큼의 IP 주소를 나타낼 수 있어요.
- Destination Address: 패킷의 목적지 IP 주소예요.
- IP Option: 주로 테스트나 디버깅 용도로 사용되며 통신에는 관여하지 않아요. 대부분 사용하지 않는 편이에요.
IP Option 필드를 제외하면 IP 헤더는 주로 20bytes로 고정되어 있어요.
# IP 헤더 분석
from socket import *
import os
import struct
# 패킷을 byte 형태로 받으면 헤더와 나머지를 리턴
def ParseIpHeader(ip_header):
# struct 모듈로 byte를 편하게 다룸, unpack의 첫 번째 인자의 알파벳에 따라 앞에서부터 byte를 끊어 튜플 형태로 반환, 두 번째 인자는 언팩 할 byte를 받음
# B: 정수-1byte, H: 정수-2bytes, s: bytes-1byte, L: 정수-4bytes, Q: 정수-8bytes
# byte 배열에서 'BBHHHBBH4s4s'는 '2B3H2BH4s4s'로 표현
ip_headers = struct.unpack("!BBHHHBBH4s4s", ip_header[:20])
ip_payloads = ip_header[20:]
return ip_headers, ip_payloads
# 숫자를 byte 형태로 변환 후, bit 형태로 다시 출력
def FlagsAndOffset(int_num):
# .to_bytes()는 정수를 byte 배열로 리턴, 뒤의 인자는 2bytes 길이의 Big endian 방식을 의미
byte_num = int_num.to_bytes(2, byteorder="big")
x = bytearray(byte_num)
# 1byte는 8bits므로 zfill() 함수로 자릿수를 맞춰 줌
flags_and_fragment_offset = bin(x[0])[2:].zfill(8) + bin(x[1])[2:].zfill(8)
return (flags_and_fragment_offset[:3], flags_and_fragment_offset[3:])
def parsing(host):
# NT계열 운영체제면(Windows)
if os.name == "nt":
socket_protocol = IPPROTO_IP
# 리눅스나 유닉스 계열이면
else:
socket_protocol = IPPROTO_ICMP
# AF_INET: IPv4 주소(AF_INET6: IPv6), Raw 소켓을 사용하겠다, 프로토콜 지정|생략(IP방식 = 0, ICMP방식 = 1)
sock = socket(AF_INET, SOCK_RAW, socket_protocol)
# 호스트의 IP주소와 포트를 연결(인자: ('호스트', '포트 번호')<=튜플 형태|자동 지정)
sock.bind((host, 0))
# 소켓에 옵션 추가(대상 소켓, 옵션(여기서는 IP헤더를 포함하는 옵션), 옵션의 설정 값(여기서는 True, if 0: 커널이 자동으로 IP헤더 작성))
sock.setsockopt(IPPROTO_IP, IP_HDRINCL, 1)
# Promiscuous mode, 윈도우에서 필요, 목적지 Network Interface Card의 MAC 주소가 자신이 아니더라도 패킷을 수신
if os.name == "nt":
sock.ioctl(SIO_RCVALL, RCVALL_ON)
# 소켓에서 데이터를 수신할 버퍼의 크기, data변수에 넣음
packet_number = 0
try:
while True:
packet_number += 1
data = sock.recvfrom(65535)
# IP 헤더 20bytes의 ip_headers와 나머지 데이터인 ip_payloads를 튜플 형태로 반환 받음
ip_headers, ip_payloads = ParseIpHeader(data[0])
print(f"{packet_number}th packet\n")
# ip_headers[0]는 1byte이며 bit 연산자를 이용해 특정한, 왼쪽 4bits에 해당하는 값이 IP의 버전
print("version: ", ip_headers[0] >> 4)
# IP 헤더의 길이는 ip_headers[0]의 오른쪽 4bits이며 출력한 값은 word 단위이므로 byte로 계산하려면 4를 곱해줘야 함
print("header length: ", ip_headers[0] & 0x0F)
print("TOS (Type Of Service): ", ip_headers[1])
print("total length: ", ip_headers[2])
print("identification: ", ip_headers[3])
# IP 플레그와 프레그먼트 오프셋은 bit 형태로 출력, Do not Fragment가 참이면 010이 출력된다.
print("IP flags, fragment offset: ", FlagsAndOffset(ip_headers[4]))
print("TTL (Time To Live): ", ip_headers[5])
print("protocol: ", ip_headers[6])
print("header checksum: ", ip_headers[7])
# inet_ntoa: byte 형을 읽을 수 있는 IP 주소 체계(*.*.*.*)로 보여줌
print("source address: ", inet_ntoa(ip_headers[8]))
print("destination address: ", inet_ntoa(ip_headers[9]))
print("=" * 50)
except KeyboardInterrupt: # Ctrl+C
# Off Promiscuous mode
if os.name == "nt":
sock.ioctl(SIO_RCVALL, RCVALL_OFF)
sock.close()
if __name__ == "__main__":
host = "192.168.0.9"
print(f"Listening at [{host}]")
parsing(host)
'自習 > Network' 카테고리의 다른 글
Network - Ping sweep scaner (0) | 2021.07.12 |
---|---|
Network - Internet Control Message Protocol (0) | 2021.07.01 |
Network - IDS, IPS, Snort, UTM (0) | 2021.05.23 |
Network - Firewall (0) | 2021.05.23 |
Network - OSI 7 Layer Model (0) | 2021.05.23 |
Comments