티스토리 뷰
출처 : http://egloos.zum.com/iryna7/v/2811423
DHCP SERVER는 다양한 방식으로 이용이 되고 있지만 KERNEL상에서 DHCP 서버 역할을 하는 프로그램의 제작 방법을 알아 봅니다. 원래 사용 목적은 VPN tunnel interface를 위하여 제작되었지만 나름 필요 하신분이 있으실것 같아 블로그에 게시합니다.
실제 패킷은 KERNEL상에서 동작되는것은 아니고 사용자 영역에 복사되어 패킷을 디코딩하여 커널 패킷을 작성하여 전송되는 방식입니다. 즉, 실질 적인 모든(이더넷 프레임 포함) 데이터는 KERNEL영역이 아닌 사용자 영역에서 처리가 이루어 지는것입니다.
DHCP 패킷의 구성 :
DHCPD | DHCPC | 기타 | ||
1 | <--------------- | DISCOVER | 클라이언트측 전송 요청 | |
2 | OFFER | ---------------> | 서버측 할당 IP 정보 전송 | |
3 | <--------------- | REQUEST | 클라이언트측 확정 요청 | |
4 | ACK | ---------------> | 서버측 할당 IP 확정 전송 |
DHCP은 보통 Discover / Offer / Request / Acknowledge등으로 구성이 되는데 모든 패킷은 UDP 형태로 전송이 되며 각각의 목적에 맞게 전송되는 데이터 타입이 존재하거나 존재하지 안거나 합니다. 예를 들면 최초 DHCP 요청의 경우에는 1,2,3,4의 형태로 전송이 되지만 이미 한번 받았던 DHCP IP가 존재할경우에 클라이언트는 3번 부터 시도를 하게 됩니다. 물론 서브측에서는 3번의 요청이 들어와도 IP가 이미 사용되어질때에는 NAK 패킷을 전송하고 클라이언트는 재 시도를 하게끔 합니다.
자세한 DHCP의 동작 원리는 RFC1531 / RFC1541 / RFC2131 을 참조 하시면 알수 있습니다. 여기서는 언급하지 안도록 하겠습니다.
# | 헤더 프레임 | 설 명 |
1 | Ethernet Header | SRC/DST의 MAC 정보 |
2 | IP Header | SRC /DST의 IP정보및 길이등 |
3 | UDP Header | 전송 데이터의 프로토콜및 길이등 |
4 | PAYLOAD | 실제 정송되는 DHCP 패킷 |
DHCP Discover :
데이터는 Ethernet Header부터 검증을 하여 정확히 DHCP 브로드캐스팅 패킷인지 파악하여 해당 MAC에게 OFFER 패킷을 전송할수 있어야만 합니다. 특히 헤더 부분의 길이를 조작하여 다양한 공격 패킷들이 존재하니 주의를 하셔야만 합니다. DHCP OPTION에 해당되는 부분은 옵션번호+길이+값과 같은 형태로 존재하니 이를 바탕으로 파싱을 하여야만 합니다.
프레임 | 설명 | ||
1 | Ethernet Header | SRC : 00:0B:82:01:FC:42 DST : FF:FF:FF:FF:FF:FF | 브로드케스트 |
2 | IP Header | SRC : 0.0.0.0 DST : 255.255.255.255 | |
3 | PROTOCOL : UDP(17) | ||
4 | SRC PORT : 68 DST PORT : 67 | ||
5 | ID : 0x3D1D | 클라이언트측 XID | |
해당 패킷은 Wireshrak 샘플입니다.
0000 00 0b 82 01 fc 42 00 08 74 ad f1 9b 08 00 45 00 .....B..t.....E.0010 01 48 04 45 00 00 80 11 00 00 c0 a8 00 01 c0 a8 .H.E............0020 00 0a 00 43 00 44 01 34 22 33 02 01 06 00 00 00 ...C.D.4"3......0030 3d 1d 00 00 00 00 00 00 00 00 c0 a8 00 0a c0 a8 =...............0040 00 01 00 00 00 00 00 0b 82 01 fc 42 00 00 00 00 ...........B....0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0110 00 00 00 00 00 00 63 82 53 63 35 01 02 01 04 ff ......c.Sc5.....0120 ff ff 00 3a 04 00 00 07 08 3b 04 00 00 0c 4e 33 ...:.....;....N30130 04 00 00 0e 10 36 04 c0 a8 00 01 ff 00 00 00 00 .....6..........0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0150 00 00 00 00 00 00 ......
DHCP Offer :
데이터는 전송시에는 반드시 해당 패킷의 길이를 정확히 계산해서 전송해주어야만 합니다.
전체 전송되는 패킷의 구조 :
struct udp_dhcp_packet {
struct ethhdr eth;
struct iphdr ip;
struct udphdr udp;
struct dhcp_packet_ data;
} __attribute__((packed));
UDP Length :
UDP Length = UDP Header Length + DHCP PAYLOAD Lengthpacket.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcp_packet_));
IP Length :
IP Length = IP Header + UDP Header + DHCP PAYLOAD Lengthpacket.ip.tot_len = htons(sizeof(struct udp_dhcp_packet) - sizeof(struct ethhdr) );
여기서 주의 할점은 IP 길이는 반드시 UDP Header및 DHCP PAYLOAD부분 패킷을 구성한 후에 계산해야 한다는 점입니다.
프레임 | 설명 | ||
1 | Ethernet Header | SRC : 00:08:74:AD:F1:9 DST : 00:0B:82:01:FC:42 | |
2 | IP Header | SRC :192.168.0.1 DST : 192.168.0.10 | |
3 | PROTOCOL : UDP(17) | ||
4 | SRC PORT : 67 DST PORT : 68 | ||
5 | ID : 0x3D1D | 클라이언트가 전송해준 XID | |
DHCP SERVER : 192.168.0.1 DHCP CLIENT : 192.168.0.10 |
해당 패킷은 Wireshrak Offer 샘플입니다.
0000 00 0b 82 01 fc 42 00 08 74 ad f1 9b 08 00 45 00 .....B..t.....E.0010 01 48 04 45 00 00 80 11 00 00 c0 a8 00 01 c0 a8 .H.E............0020 00 0a 00 43 00 44 01 34 22 33 02 01 06 00 00 00 ...C.D.4"3......0030 3d 1d 00 00 00 00 00 00 00 00 c0 a8 00 0a c0 a8 =...............0040 00 01 00 00 00 00 00 0b 82 01 fc 42 00 00 00 00 ...........B....0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................00f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0110 00 00 00 00 00 00 63 82 53 63 35 01 02 01 04 ff ......c.Sc5.....0120 ff ff 00 3a 04 00 00 07 08 3b 04 00 00 0c 4e 33 ...:.....;....N30130 04 00 00 0e 10 36 04 c0 a8 00 01 ff 00 00 00 00 .....6..........0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................0150 00 00 00 00 00 00 ......
시간이 나는데로 좀더 자세한 구성을 적어 올리겠습니다.
'Linux' 카테고리의 다른 글
Nginx와 Apache 튜닝 포인트 비교 (0) | 2017.08.08 |
---|---|
Resize partions at Linux – 리눅스에서 파티션 사이즈 변경하기 (0) | 2016.10.19 |
FUSE 란? (0) | 2016.08.17 |
서버 성능측정 with sysbench (1) | 2016.07.14 |
IOzone 을 이용한 Disk 성능 측정법. (0) | 2016.07.13 |