Network Fundamentals — Hands-on in a Linux VM
What ping Really Sends, and MTU
This lab runs on a VM
You connect two namespaces (pa·pb) with a veth pair and look at ICMP and UDP on top of it.
It has the same shape as the second lab, but this time the main subject is not frames but packet size and error messages.
Goal
Capture the ICMP echo that ping sends, see a packet larger than the MTU being fragmented or rejected, and confirm how UDP reports a closed port (ICMP port unreachable).
Why it matters
"Ping works but only big files stall", "SSH works but the web page half loads and stops" — it is almost always the MTU. Small packets pass and only large packets are dropped somewhere, and because of the DF bit they cannot even be fragmented, and the ICMP that would report that fact is blocked by a firewall — that is the common shape of the incident. Every time a VPN, overlay network, or tunnel adds headers, this problem comes back to life, so you count by hand where the numbers 1500 and 1472 come from.
Steps
- Create the namespaces
pa·pband the vethpa0↔pb0, attach10.60.0.1/24·10.60.0.2/24, and make ping work in both directions. - Save the result of
ping -c 3frompatopbto/root/icmp/ping.txt. - Send one ping while capturing ICMP on
pa0, and save the output containing the echo request and echo reply to/root/icmp/echo.txt. - Use
ping -M doto forbid fragmentation, vary the size to find the largest payload that gets through, and save two lines,mtu=·max_payload=, plus the failure message to/root/icmp/mtu.txt. - With fragmentation allowed, capture a ping with a 3000-byte payload and save the output showing the fragmented packets to
/root/icmp/frag.txt. - Start an
nc -lulistening on UDP 9001 inpb(send what it receives to/root/icmp/udp.txt) and sendhello-udpfrompa. - Send a datagram from
pato the closed UDP port 9999 onpbwhile capturing, and save the output showingudp port 9999 unreachableto/root/icmp/unreach.txt. - Lower the MTU of
pa0to 1400 and, in/root/icmp/report.md, write two lines,mtu=1400·max_payload=, together with an explanation of why that number comes out the way it does and why fragmentation is a problem.
Notes
ping -M do -s <바이트>: turns DF on and sets the payload size (replace the placeholder with a number of bytes). MTU 1500 = IP header 20 + ICMP header 8 + payload.- Start the capture like
ip netns exec pa timeout 5 tcpdump -i pa0 -nn -l icmp > 파일 2>&1 &(replace the file placeholder with the output file name), and then send. - UDP server:
ip netns exec pb setsid timeout 20 nc -lu 10.60.0.2 9001 > /root/icmp/udp.txt 2>&1 < /dev/null &. Client:echo hello-udp | ip netns exec pa nc -u -q 1 -w 1 10.60.0.2 9001. - Changing the MTU:
ip -n pa link set pa0 mtu 1400. - A common mistake: entering
-s 1500and wondering why it does not work. You have to subtract the 28 bytes of headers.
Connect the two
Create the namespaces pa·pb and the veth pa0↔pb0, attach 10.60.0.1/24·10.60.0.2/24, and make ping work in both directions.
The order is the same as in lab 2: netns add → link add veth → link set netns → addr add → link set up (including lo). Check with ip netns exec pa ping -c 1 10.60.0.2.
Three pings
Save the result of ping -c 3 from pa to pb to /root/icmp/ping.txt.
ip netns exec pa ping -c 3 10.60.0.2 > /root/icmp/ping.txt. The statistics line must have 3 received. time= is the round-trip time (RTT).
Capture the echo
Send one ping while capturing ICMP on pa0, and save the output containing the echo request and echo reply to /root/icmp/echo.txt.
After ip netns exec pa timeout 5 tcpdump -i pa0 -nn -l icmp > /root/icmp/echo.txt 2>&1 &, wait 1 second and run ip netns exec pa ping -c 1 10.60.0.2. The file must have one line each for ICMP echo request and ICMP echo reply.
Forbid fragmentation
Use ping -M do to forbid fragmentation, vary the size to find the largest payload that gets through, and save two lines, mtu=·max_payload=, plus the failure message to /root/icmp/mtu.txt.
The mtu in ip -n pa link show pa0 is 1500. ping -M do -s 1472 works, and -s 1473 fails with message too long, mtu=1500. Append the output of the failed ping (2>&1) two lines below.
Fragmenting
With fragmentation allowed, capture a ping with a 3000-byte payload and save the output showing the fragmented packets to /root/icmp/frag.txt.
Start the capture and run ip netns exec pa ping -c 1 -s 3000 10.60.0.2. The 3028-byte packet is split into fragments of 1500, and only the first fragment shows as ICMP echo request, while the rest show as ip-proto-1 (because the ICMP header is only in the first fragment).
UDP has no handshake
Start an nc -lu listening on UDP 9001 in pb (send what it receives to /root/icmp/udp.txt) and send hello-udp from pa.
Server: ip netns exec pb setsid timeout 20 nc -lu 10.60.0.2 9001 > /root/icmp/udp.txt 2>&1 < /dev/null &. Client: echo hello-udp | ip netns exec pa nc -u -q 1 -w 1 10.60.0.2 9001. It is enough if the file contains hello-udp.
A closed UDP port answers with ICMP
Send a datagram from pa to the closed UDP port 9999 on pb while capturing, and save the output showing udp port 9999 unreachable to /root/icmp/unreach.txt.
Set the capture filter to 'icmp or udp' and run echo x | ip netns exec pa nc -u -q 1 -w 1 10.60.0.2 9999. After one UDP datagram line, ICMP 10.60.0.2 udp port 9999 unreachable follows.
Lower the MTU and wrap up
Lower the MTU of pa0 to 1400 and, in /root/icmp/report.md, write two lines, mtu=1400·max_payload=, together with an explanation of why that number comes out the way it does and why fragmentation is a problem.
After ip -n pa link set pa0 mtu 1400, ping -M do -s 1372 works and -s 1373 does not. max_payload is 1400 - 28. The explanation must include the words MTU and fragment (or fragmentation).