네트워크 기초 — 리눅스 VM 에서 손으로 · TCP·UDP·ICMP · 실습
TCP 핸드셰이크를 세 줄로 잡는다
이 실습은 VM 에서 돕니다
루프백(lo) 위에서 nc 로 서버와 클라이언트를 만들고 tcpdump 로 그 사이를
잡습니다. 바깥 네트워크가 필요 없어서 잡히는 패킷이 전부 내 것입니다.
목표
연결이 열리고 닫히는 과정을 SYN·SYN-ACK·ACK·FIN 플래그로 읽고, 닫힌 포트와
열린 포트의 차이, TIME-WAIT, 임시 포트, 그리고 포트를 잡은 프로세스를 찾는 법을 익힙니다.
왜 중요한가
"연결이 안 된다" 는 한 문장에 서로 다른 세 가지가 섞여 있습니다. SYN 을 보냈는데
RST 가 오면 상대는 살아 있고 포트만 닫힌 것이고, 아무것도 안 오면 방화벽이
버리거나 경로가 없는 것이고, SYN-ACK 까지 왔는데 데이터가 안 오면 애플리케이션
문제입니다. 이 셋은 사용자에게 똑같이 "안 됨" 으로 보이지만 고치는 사람은 완전히
다릅니다. 플래그를 읽을 줄 알면 첫 30초에 그 셋이 갈립니다.
단계
1. nc -lk 127.0.0.1 9000 서버를 백그라운드로 띄우고(받은 데이터는 /root/tcp/recv.txt 로) ss -ltn 출력을 /root/tcp/listen.txt 에 저장하세요.
2. lo 의 9000 포트를 tcpdump 로 잡으면서 hello 한 줄을 보내, 핸드셰이크와 종료가 담긴 캡처를 /root/tcp/handshake.txt 에 저장하세요.
3. 아무도 듣지 않는 9001 포트로 접속을 시도해 오류 메시지와 그때의 캡처(RST 가 보이는)를 /root/tcp/refused.txt 에 함께 저장하세요.
4. 9000 으로 한 번 더 접속하고 닫은 직후 ss -tan 에서 TIME-WAIT 줄을 /root/tcp/timewait.txt 에 저장하세요.
5. 임시 포트 범위와 2단계 캡처에서 클라이언트가 쓴 포트를 /root/tcp/ports.txt 에 range=·client_port= 두 줄로 저장하세요.
6. 파이썬으로 127.0.0.1:9000 에 한 번 더 bind 를 시도해 그 오류를 /root/tcp/inuse.txt 에 저장하세요.
7. ss -ltnp 로 9000 을 잡은 프로세스를 찾아 그 줄을 /root/tcp/owner.txt 에 저장하세요.
8. /root/tcp/report.md 에 client_port=·server_port= 두 줄과 함께 세 단계 핸드셰이크와 TIME-WAIT 가 왜 있는지를 적으세요.
참고
- 서버는
setsid nc -lk 127.0.0.1 9000 > /root/tcp/recv.txt 2>&1 < /dev/null &처럼 띄우세요.-k는 연결이 끝나도 계속 듣는 옵션입니다. - 캡처:
timeout 6 tcpdump -i lo -nn -l 'tcp port 9000' > 파일 2>&1 &를 먼저 걸고,echo hello | nc -q 1 127.0.0.1 9000. - 플래그:
[S]SYN,[S.]SYN+ACK,[.]ACK,[P.]데이터,[F.]FIN,[R.]RST. - 임시 포트 범위:
sysctl net.ipv4.ip_local_port_range. - 흔한 실수: 서버를 띄우고 표준 출력을 터미널에 물려 두는 것. 다른 명령이 섞여 파일이 엉킵니다 — 반드시 파일로 보내세요.
단계 8개
- 듣는 소켓
- 세 줄의 핸드셰이크
- 닫힌 포트는 RST 로 답한다
- TIME-WAIT
- 임시 포트
- 포트는 하나가 잡는다
- 누가 잡았나
- 무엇을 배웠나