실습 목표#
- 랜선을 이용하여 노트북과 라즈베리파이를 연결하고, 고정 IP를 할당하여 연결을 확인한다.
- ARP, ICMP, UDP 통신을 해보고 Wireshark를 통해 패킷을 분석한다.
실습 환경 설정#
라즈베리파이 고정 IP 설정#
랜선을 라즈베리파이와 노트북의 이더넷 포트에 직접 연결 후, vscode에서 ssh로 라즈베리파이를 연결한다. 라즈베리파이 터미널에 다음 명령어들을 입력하여 고정 IP를 설정한다.
sudo nmcli con add type ethernet ifname eth0 con-name lab-static \
ip4 192.168.10.2/24
sudo nmcli con up lab-static
ip addr show eth0
관찰 포인트
ip addr 출력의 eth0 항목에 ip4 192.168.10.2/24가 보이면 성공이다.
노트북 고정 IP 설정#
다음과 같이 윈도우 설정에서 이더넷 어댑터의 IP를 수동으로 지정한다.
설정 → 네트워크 및 인터넷 → 이더넷 → IP 할당 → 설정 편집

이더넷 연결 확인#
노트북과 라즈베리파이 각각에서 ping 명령어로 연결 상태를 확인한다. 응답이 오면 연결 성공, 타임 아웃이 발생하면 연결 실패이다.
ping 192.168.10.2
ping 192.168.10.1
실습 1. ARP 캡처#
실습 진행#
ARP(Address Resolution Protocol)는 상대 IP의 MAC 주소를 알아내는 프로토콜이다. 라즈베리파이의 IP 주소만 알고 MAC 주소를 모르기 때문에 ARP를 통해 MAC 주소를 알아낸다.
WireShark에서 라즈베리파이와 연결된 이더넷 어댑터 더블 클릭 → 필터 'arp'로 설정하여 캡처를 시작한다.

캐시 삭제 후, ping 명령어를 실행한다.
arp -d *
ping 192.168.10.2
관찰 포인트
이 때 요청과 응답이 한 쌍으로 잡히는지, 각각의 Dst MAC이 무엇인지 확인한다.
상대방의 MAC Address를 모르기 때문에 Broadcasting을 통해 요청한다. 한 번 알아낸 MAC Address는 ARP Cache에 저장하고 이후 통신에서는 ARP를 사용하지 않고 Cache를 참조한다.
Destination을 보면 Broadcast라고 되어있는 것을 확인할 수 있다.
ARP Request 분석#
다음 표를 참고하여 ARP Request를 분석한다.
ff ff ff ff ff ff 11 22 33 44 55 66 08 06 00 01
08 00 06 04 00 01 11 22 33 44 55 66 c0 a8 0a 01
00 00 00 00 00 00 c0 a8 0a 02
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 0~5 | ff ff ff ff ff ff |
Dst MAC | Broadcast |
| 6~11 | 11 22 33 44 55 66 |
Src MAC | 노트북 MAC Address |
| 12 ~ 13 | 08 06 |
Type | ARP |
| 14~15 | 00 01 |
Hardware Type | 이더넷 |
| 16~17 | 08 00 |
Protocol Type | IPv4 |
| 18 | 06 |
Hardware Size | MAC Address Size |
| 19 | 04 |
Protocol Size | IP Address Size |
| 20 ~ 21 | 00 01 |
Opcode | Request |
| 22 ~ 27 | 11 22 33 44 55 66 |
Sender MAC | 노트북 MAC Address |
| 28 ~ 31 | c0 a8 0a 01 |
Sender IP | 192.168.10.1 |
| 32 ~ 37 | 00 00 00 00 00 00 |
Target MAC | Broadcast |
| 38 ~ 41 | c0 a8 0a 02 |
Target IP | 192.168.10.2 |
ARP Response 분석#
다음 표를 참고하여 ARP Response를 분석한다.
11 22 33 44 55 66 aa bb cc dd ee ff 08 06 00 01
08 00 06 04 00 02 aa bb cc dd ee ff c0 a8 0a 02
11 22 33 44 55 66 c0 a8 0a 01 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 0 ~ 5 | 11 22 33 44 55 66 |
Dst MAC | 노트북 MAC Address |
| 6 ~ 11 | aa bb cc dd ee ff |
Src MAC | 라즈베리파이 MAC Address |
| 12 ~ 13 | 08 06 |
Type | ARP |
| 14 ~ 15 | 00 01 |
Hardware Type | 이더넷 |
| 16 ~1 7 | 08 00 |
Protocol Type | IPv4 |
| 18 | 06 | Hardware Size |
MAC Address Size |
| 19 | 04 | Protocol Size |
IP Address Size |
| 20 ~ 21 | 00 02 |
Opcode | Response |
| 22 ~ 27 | aa bb cc dd ee ff |
Sender MAC | 라즈베리파이 MAC Address |
| 28 ~ 31 | c0 a8 0a 01 |
Sender IP | 192.168.10.2 |
| 32 ~ 37 | 11 22 33 44 55 66 |
Target MAC | 노트북 MAC Address |
| 38 ~ 41 | c0 a8 0a 02 |
Target IP | 192.168.10.1 |
| 42 ~ 59 | 00 00 ⋯ 00 00 |
Padding | 최소 60 Bytes를 채우는 0 |
ARP 패킷 구조#
ARP 요청 프레임은 42bytes로, 이더넷 헤더 14 bytes 뒤에 ARP 메시지 28bytes가 붙는다.

실습 2. ICMP 캡처#
실습 진행#
WireShark에서 필터를 ‘arp || icmp’로 설정한다. 이 때 한 번의 ping에 request와 reply가 한 쌍씩 총 8번의 ICMP 통신이 이루어진다.
ICMP Request 분석#
다음 표를 참고하여 ICMP Request를 분석한다.
aa bb cc dd ee ff 11 22 33 44 55 66 08 00 45 00
00 3c 97 97 00 00 80 01 00 00 c0 a8 0a 01 c0 a8
0a 02
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 0~5 | aa bb cc dd ee ff |
Dst MAC | 라즈베리파이 MAC Address |
| 6~11 | 11 22 33 44 55 66 |
Src MAC | 노트북 MAC Address |
| 12 ~ 13 | 08 00 |
Type | IPv4 |
| 14 | 45 |
Version / IHL | IPv4 · Header 20 Bytes |
| 15 | 00 |
DSCP / ECN | 우선순위 없음 |
| 16~17 | 00 3c |
Total Length | 60 Bytes (IP 20 + ICMP 8 + Data 32) |
| 18 ~ 19 | 97 97 |
Identification | Fragment 식별 번호 |
| 20 ~ 21 | 00 00 |
Flags / Offset | Fragment 없음 |
| 22 | 80 |
TTL | 128 · Windows 기본값 |
| 23 | 01 |
Protocol | ICMP |
| 24 ~ 25 | 00 00 |
Header Checksum | NIC가 계산 · 0으로 표시 |
| 26 ~ 29 | c0 a8 0a 01 |
Src IP | 192.168.10.1 |
| 30 ~ 33 | c0 a8 0a 02 |
Dst IP | 192.168.10.2 |
08 00 4b 87 00 01 01 d4 61 62 63 64 65 66 67 68
69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61
62 63 64 65 66 67 68 69
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 34 | 08 |
Type | Echo Request |
| 35 | 00 |
Code | 0 |
| 36 ~ 37 | 4b 87 |
Checksum | 오류 검출 |
| 38 ~ 39 | 00 01 |
Identifier | ping 프로세스 구분 |
| 40 ~ 41 | 01 d4 |
Sequence Number | 468번째 요청 |
| 42 ~ 73 | 61 62 63 ⋯ 68 69 |
Data | 알파벳 32 Bytes |
ICMP Reply 분석#
다음 표를 참고하여 ICMP Reply를 분석한다.
11 22 33 44 55 66 aa bb cc dd ee ff 08 00 45 00
00 3c c4 95 00 00 40 01 d0 d7 c0 a8 0a 02 c0 a8
0a 01
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 0 ~ 5 | 11 22 33 44 55 66 |
Dst MAC | 노트북 MAC Address |
| 6 ~ 11 | aa bb cc dd ee ff |
Src MAC | 라즈베리파이 MAC Address |
| 12 ~ 13 | 08 00 |
Type | IPv4 |
| 14 | 45 |
Version / IHL | IPv4 · Header 20 Bytes |
| 15 | 00 |
DSCP / ECN | 우선순위 없음 |
| 16 ~ 17 | 00 3c |
Total Length | 60 Bytes (IP 20 + ICMP 8 + Data 32) |
| 18 ~ 19 | c4 95 |
Identification | Fragment 식별 번호 |
| 20 ~ 21 | 00 00 |
Flags / Offset | Fragment 없음 |
| 22 | 40 |
TTL | 64 · Linux 기본값 |
| 23 | 01 |
Protocol | ICMP |
| 24 ~ 25 | d0 d7 |
Header Checksum | 오류 검출 |
| 26 ~ 29 | c0 a8 0a 02 |
Src IP | 192.168.10.2 |
| 30 ~ 33 | c0 a8 0a 01 |
Dst IP | 192.168.10.1 |
00 00 53 87 00 01 01 d4 61 62 63 64 65 66 67 68
69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61
62 63 64 65 66 67 68 69
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 34 | 00 |
Type | Echo Reply |
| 35 | 00 |
Code | 0 |
| 36 ~ 37 | 53 87 |
Checksum | Type이 바뀌어 다시 계산 |
| 38 ~ 39 | 00 01 |
Identifier | Request와 동일 |
| 40 ~ 41 | 01 d4 |
Sequence Number | 468번째 요청 |
| 42 ~ 73 | 61 62 63 ⋯ 68 69 |
Data | 알파벳 32 Bytes |
ICMP 패킷 구조#
ICMP는 IP 위에서 동작하므로 이더넷과 IP 헤더를 거쳐 전달된다. 캡처된 프레임은 총 74bytes이다.

실습 3. UDP 예제 코드 실행#
실습 진행#
라즈베리파이와 노트북에서 각각 아래와 같이 build한다. 라즈베리파이에서 'udp_server'를 먼저 실행하고, 노트북에서 'udp_client'를 실행한다.
make
./udp_server
make
./udp_client
WireShark에서 필터를 'udp.port==9999’로 설정하여 결과를 분석한다.

UDP 패킷 분석#
다음 표를 참고하여 UDP 패킷을 분석한다.
aa bb cc dd ee ff 11 22 33 44 55 66 08 00 45 00
00 31 73 bb 40 00 40 11 e1 ac c0 a8 0a 01 c0 a8
0a 02
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 0 ~ 5 | aa bb cc dd ee ff |
Dst MAC | 라즈베리파이 MAC Address |
| 6 ~ 11 | 11 22 33 44 55 66 |
Src MAC | 노트북 MAC Address |
| 12 ~ 13 | 08 00 |
Type | IPv4 |
| 14 | 45 |
Version / IHL | IPv4 · Header 20 Bytes |
| 15 | 00 |
DSCP / ECN | 우선순위 없음 |
| 16 ~ 17 | 00 31 |
Total Length | 49 Bytes (IP 20 + ICMP 8 + Data 21) |
| 18 ~ 19 | 73 bb |
Identification | Fragment 식별 번호 |
| 20 ~ 21 | 40 00 |
Flags / Offset | Fragment 없음 · DF |
| 22 | 40 |
TTL | 64 · Linux 기본값 |
| 23 | 11 |
Protocol | UDP |
| 24 ~ 25 | e1 ac |
Header Checksum | 오류 검출 |
| 26 ~ 29 | c0 a8 0a 01 |
Src IP | 192.168.10.1 |
| 30 ~ 33 | c0 a8 0a 01 |
Dst IP | 192.168.10.2 |
9b a1 27 0f 00 1d 52 2c 48 65 6c 6c 6f 20 55 44
50 20 66 72 6f 6d 20 6c 61 70 74 6f 70
| 오프셋 | 바이트 | 필드 | 의미 |
|---|---|---|---|
| 34 ~ 35 | 9b a1 |
Src Port | 39841 · OS 임시 할당 |
| 36 ~ 37 | 27 0f |
Dst Port | 9999 |
| 38 ~ 39 | 00 1d |
Length | 29 Bytes (Header 8 + Data 21) |
| 40 ~ 41 | 52 2c |
Checksum | 오류 검출 |
| 42 ~ 62 | 48 65 6c 6c 6f ⋯ 6f 70 |
Data | Hello UDP from laptop |
과제 1. 보내는 데이터 변경#
노트북 udp_client_blank.cpp에서 보내는 데이터를 변경한다. 실습3과 동일한 방식으로 build 후, 라즈베리파이에서 udp_server를 먼저 실행하고, 노트북에서 udp_client_blank를 실행한다.
const char* msg = "Hello UDP from laptop";
g++ -std=c++17 -O2 udp_client_blank.cpp -o udp_client_blank
./udp_client_blank
과제 2. 서버가 응답 보내기#
이번에는 라즈베리파이 udp_server_blank.cpp에서 보내는 데이터를 변경한다. 실습3과 동일하게 build 후, 라즈베리파이에서 udp_server_blank를 먼저 실행하고 노트북에서 udp_client를 실행한다.
const char* reply = "ACK from Pi";
sendto(sock, reply, strlen(reply), 0, (sockaddr*)&cli, clilen);
g++ -std=c++17 -O2 udp_server.cpp -o udp_server
./udp_server