ping が実際に送るものと MTU
한국어 원문으로 표시합니다.
이 실습은 VM 에서 돕니다
네임스페이스 둘(pa·pb)을 veth 로 잇고 그 위에서 ICMP 와 UDP 를 봅니다.
2번째 실습과 같은 모양이지만 이번엔 프레임이 아니라 패킷 크기와 오류 메시지가 주인공입니다.
목표
ping 이 보내는 ICMP echo 를 잡고, MTU 를 넘는 패킷이 조각나거나 거부되는 것을 보고, UDP 가 닫힌 포트를 어떻게 알려 주는지(ICMP port unreachable) 확인합니다.
왜 중요한가
"ping 은 되는데 큰 파일만 멈춘다", "SSH 는 되는데 웹 페이지가 반쯤 뜨다 만다" — 거의 언제나 MTU 입니다. 작은 패킷은 통과하고 큰 패킷만 어딘가에서 버려지는데, DF 비트 때문에 조각도 못 내고, 그 사실을 알려 줄 ICMP 는 방화벽이 막고 있는 것이 흔한 사고 형태입니다. VPN·오버레이 네트워크·터널이 헤더를 덧붙일 때마다 이 문제가 되살아나므로, 1500 과 1472 가 어디서 오는 숫자인지 손으로 세어 봅니다.
단계
- 네임스페이스
pa·pb와 vethpa0↔pb0를 만들어10.60.0.1/24·10.60.0.2/24를 붙이고 서로 ping 이 되게 하세요. pa에서pb로ping -c 3한 결과를/root/icmp/ping.txt에 저장하세요.pa0에서 ICMP 를 캡처하며 ping 한 번을 보내, echo request 와 echo reply 가 담긴 출력을/root/icmp/echo.txt에 저장하세요.ping -M do로 조각을 금지한 채 크기를 바꿔 가며 통과하는 최대 페이로드를 찾아/root/icmp/mtu.txt에mtu=·max_payload=두 줄과 실패 메시지를 저장하세요.- 조각을 허용한 채 페이로드 3000 바이트 ping 을 캡처해 조각난 패킷이 보이는 출력을
/root/icmp/frag.txt에 저장하세요. pb에 UDP 9001 을 듣는nc -lu를 띄우고(받은 것은/root/icmp/udp.txt로)pa에서hello-udp를 보내세요.pa에서pb의 닫힌 UDP 포트 9999 로 데이터그램을 보내며 캡처해,udp port 9999 unreachable이 보이는 출력을/root/icmp/unreach.txt에 저장하세요.pa0의 MTU 를 1400 으로 낮추고/root/icmp/report.md에mtu=1400·max_payload=두 줄과 함께 그 수가 왜 그렇게 나오는지, 그리고 조각화가 왜 문제가 되는지를 적으세요.
참고
ping -M do -s <바이트>: DF 를 켜고 페이로드 크기를 정합니다. MTU 1500 = IP 헤더 20 + ICMP 헤더 8 + 페이로드.- 캡처는
ip netns exec pa timeout 5 tcpdump -i pa0 -nn -l icmp > 파일 2>&1 &처럼 걸어 두고 보냅니다. - UDP 서버:
ip netns exec pb setsid timeout 20 nc -lu 10.60.0.2 9001 > /root/icmp/udp.txt 2>&1 < /dev/null &. 클라이언트:echo hello-udp | ip netns exec pa nc -u -q 1 -w 1 10.60.0.2 9001. - MTU 바꾸기:
ip -n pa link set pa0 mtu 1400. - 흔한 실수:
-s 1500을 넣고 왜 안 되는지 갸웃하는 것. 헤더 28 바이트를 빼야 합니다.
두 대를 잇는다
네임스페이스 pa·pb 와 veth pa0↔pb0 를 만들어 10.60.0.1/24·10.60.0.2/24 를 붙이고 서로 ping 이 되게 하세요.
2번 실습과 같은 순서입니다: netns add → link add veth → link set netns → addr add → link set up(lo 포함). ip netns exec pa ping -c 1 10.60.0.2 로 확인.
ping 세 번
pa 에서 pb 로 ping -c 3 한 결과를 /root/icmp/ping.txt 에 저장하세요.
ip netns exec pa ping -c 3 10.60.0.2 > /root/icmp/ping.txt. 통계 줄에 3 received 가 있어야 합니다. time= 이 왕복 시간(RTT)입니다.
echo 를 잡는다
pa0 에서 ICMP 를 캡처하며 ping 한 번을 보내, echo request 와 echo reply 가 담긴 출력을 /root/icmp/echo.txt 에 저장하세요.
ip netns exec pa timeout 5 tcpdump -i pa0 -nn -l icmp > /root/icmp/echo.txt 2>&1 & 뒤 1초 쉬고 ip netns exec pa ping -c 1 10.60.0.2. 파일에 ICMP echo request 와 ICMP echo reply 가 한 줄씩 있어야 합니다.
조각 금지
ping -M do 로 조각을 금지한 채 크기를 바꿔 가며 통과하는 최대 페이로드를 찾아 /root/icmp/mtu.txt 에 mtu=·max_payload= 두 줄과 실패 메시지를 저장하세요.
ip -n pa link show pa0 의 mtu 는 1500. ping -M do -s 1472 는 되고 -s 1473 은 message too long, mtu=1500 으로 실패합니다. 실패한 ping 의 출력(2>&1)을 두 줄 아래 붙이세요.
조각내기
조각을 허용한 채 페이로드 3000 바이트 ping 을 캡처해 조각난 패킷이 보이는 출력을 /root/icmp/frag.txt 에 저장하세요.
캡처를 걸고 ip netns exec pa ping -c 1 -s 3000 10.60.0.2. 3028 바이트 패킷이 1500 짜리 조각들로 나뉘어 첫 조각만 ICMP echo request, 나머지는 ip-proto-1 로 보입니다(ICMP 헤더가 첫 조각에만 있어서).
UDP 는 핸드셰이크가 없다
pb 에 UDP 9001 을 듣는 nc -lu 를 띄우고(받은 것은 /root/icmp/udp.txt 로) pa 에서 hello-udp 를 보내세요.
서버: ip netns exec pb setsid timeout 20 nc -lu 10.60.0.2 9001 > /root/icmp/udp.txt 2>&1 < /dev/null &. 클라이언트: echo hello-udp | ip netns exec pa nc -u -q 1 -w 1 10.60.0.2 9001. 파일에 hello-udp 가 들어 있으면 됩니다.
닫힌 UDP 포트는 ICMP 로 답한다
pa 에서 pb 의 닫힌 UDP 포트 9999 로 데이터그램을 보내며 캡처해, udp port 9999 unreachable 이 보이는 출력을 /root/icmp/unreach.txt 에 저장하세요.
캡처 필터를 'icmp or udp' 로 걸고 echo x | ip netns exec pa nc -u -q 1 -w 1 10.60.0.2 9999. UDP 데이터그램 한 줄 뒤에 ICMP 10.60.0.2 udp port 9999 unreachable 이 따라옵니다.
MTU 를 낮추고 정리
pa0 의 MTU 를 1400 으로 낮추고 /root/icmp/report.md 에 mtu=1400·max_payload= 두 줄과 함께 그 수가 왜 그렇게 나오는지, 그리고 조각화가 왜 문제가 되는지를 적으세요.
ip -n pa link set pa0 mtu 1400 뒤 ping -M do -s 1372 는 되고 -s 1373 은 안 됩니다. max_payload 는 1400 - 28. 설명에 MTU 와 조각(또는 fragment)이라는 말이 들어가야 합니다.