리눅스 네트워크 진단 · 소켓과 포트 · 실습
소켓과 포트 진단
목표
리스닝 소켓의 바인딩 범위를 구분하고, ss 와 /proc/net/tcp 두 경로로 같은 사실을 확인합니다.
왜 중요한가
"서버 안에서 curl 은 되는데 밖에서는 안 된다"는 신고의 대부분은 방화벽이 아니라 바인딩 문제입니다. 127.0.0.1:8080 에 묶인 소켓은 같은 호스트에서 온 연결만 받고, 외부 패킷은 커널이 아예 전달하지 않습니다. 이 구분은 보안 설계이기도 합니다 - 관리용 포트를 일부러 루프백에만 묶는 것이 표준 관행입니다. 그리고 리스닝 소켓의 Send-Q 는 백로그 최대치, Recv-Q 는 accept 대기 큐의 현재 길이입니다. 확립된 연결에서의 뜻과 다르기 때문에 자주 오독됩니다.
단계
/root/net 디렉터리에서 작업합니다.
1. python3 -m http.server 8080 --bind 127.0.0.1 을 백그라운드로 띄우고 PID 를 /root/net/http_pid.txt 에 적으세요.
2. python3 -m http.server 8081 --bind 0.0.0.0 을 백그라운드로 띄우고 PID 를 /root/net/all_pid.txt 에 적으세요. 8080 은 그대로 루프백 전용이어야 합니다.
3. 두 포트의 바인딩 범위를 /root/net/binding.txt 에 다음 두 줄로 적으세요. 값은 loopback 또는 all 입니다.
8080=<값>8081=<값>
4. 8081 로 연결을 하나 열어 닫지 않고 유지하는 프로세스를 띄우고 PID 를 /root/net/client_pid.txt 에 적으세요.
5. 10진수 8080 을 16진수 4자리 대문자로 바꿔 /root/net/hexport.txt 에 적으세요.
6. 8080 리스닝 소켓의 백로그 최대치를 /root/net/backlog.txt 에 숫자만 적으세요.
7. 8080 을 잡고 있는 프로세스의 PID 를 ss 로 확인해 /root/net/owner.txt 에 적으세요.
8. /root/net/portcheck.sh <포트> 를 만드세요. 그 포트에서 듣고 있으면 port=<포트> state=listen pid=<PID> 를 출력하고 종료 코드 0, 아무도 안 들으면 port=<포트> state=free 를 출력하고 종료 코드 1. 인자가 없으면 0이 아닌 코드입니다.
참고
ss -ltnH는 헤더 없이 리스닝 TCP 소켓만 보여 줍니다. 열 순서는Recv-Q Send-Q Local Peer입니다./proc/net/tcp의local_address는IP:PORT가 모두 16진수이고 상태0A가 LISTEN 입니다.python3 -c "import socket,time; s=socket.create_connection(('127.0.0.1',8081)); time.sleep(9999)" &로 연결을 붙잡을 수 있습니다.- 흔한 실수 1: 4번에서 연결을 열자마자 닫으면 ESTABLISHED 가 사라집니다.
- 흔한 실수 2: 7번에서
-p없이ss -ltn만 쓰면 프로세스 정보가 안 나옵니다.
단계 8개
- 루프백에만 묶어 서버 띄우기
- 모든 주소에 묶어 띄우기
- 바인딩 범위 기록하기
- 연결 붙잡아 두기
- /proc/net/tcp 직접 읽기
- 백로그 최대치 읽기
- 포트의 주인 찾기
- 포트 점유 확인 스크립트