Diagnosing Sockets and Ports
한국어 원문으로 표시합니다.
목표
리슨 소켓을 읽고, 바인딩 주소가 원격 접속에 미치는 영향을 직접 재현하고, Connection refused 와 정상 연결의 차이를 확인합니다.
왜 중요한가
127.0.0.1:8080 으로 리슨하는 프로세스는 같은 호스트에서는 완벽히 동작하지만 바깥에서 오는 연결은 커널이 RST 로 거절합니다 — 즉 refused 가 납니다. 그래서 "로컬에서는 되는데 원격만 안 된다" 는 신고를 받으면 ss -ltnp 의 Local Address 열 한 칸만 보면 절반이 끝납니다. 반대로 그 주소가 0.0.0.0 인데도 바깥에서 timeout 이면 그때부터 방화벽과 네트워크 정책을 봅니다. 이 갈림이 조사 범위를 절반으로 줄입니다.
단계
/root/sock디렉터리를 만들고, 현재 리슨 중인 TCP 소켓 목록을/root/sock/listen.txt로 저장하세요.:2222가 포함돼야 합니다.0.0.0.0:8080에서 듣는 HTTP 서버를 백그라운드로 띄우세요. 채점 시점에도 살아 있어야 합니다.127.0.0.1:8081에서만 듣는 두 번째 서버를 띄우고, 두 소켓의Local Address:Port를 각각 한 줄씩/root/sock/bind.txt에 적으세요. (예:0.0.0.0:8080과127.0.0.1:8081)127.0.0.1:8080으로 연결이 되는지 확인한 결과를/root/sock/nc-open.txt로 저장하세요.- 아무도 듣고 있지 않은
127.0.0.1:9999로 연결을 시도한 결과를/root/sock/nc-refused.txt로 저장하세요. 출력에 refused 를 뜻하는 문구가 있어야 합니다. /proc/net/tcp에서 8080 포트의 LISTEN 소켓 줄을 찾아 그대로/root/sock/proctcp.txt에 저장하세요.- 자기 인터페이스 IP(루프백 아님)로 8080 과 8081 을 각각 두드리고, 결과를
/root/sock/scope-test.txt에 두 줄로 적으세요.8080=<open|closed>/8081=<open|closed> /root/sock/report.csv를 만드세요. 첫 줄은port,bind,proto헤더이고, 그 아래에 2222, 8080, 8081 세 포트에 대해 각각 한 줄씩 적으세요.bind는 실제 리슨 주소,proto는tcp입니다.
참고
ss -ltnp,nc -zv -w 2 <ip> <port>,ip -4 -br addr show scope global조합이면 충분합니다.- 서버는
nohup python3 -m http.server 8080 --bind 0.0.0.0 >/dev/null 2>&1 &형태로 띄웁니다. /proc/net/tcp의 포트는 16진수입니다.printf '%04X\n' 8080으로 변환값을 확인하세요.- 흔한 실수 1: 7번에서 루프백 주소로 시험하면 두 포트 모두 열린 것으로 보여 차이가 드러나지 않습니다.
- 흔한 실수 2: 백그라운드 서버가 셸 종료와 함께 죽는 경우.
nohup이나setsid로 분리하세요.
리슨 소켓 확인
/root/sock 디렉터리를 만들고, 현재 리슨 중인 TCP 소켓 목록을 /root/sock/listen.txt 로 저장하세요. :2222 가 포함돼야 합니다.
TCP 리슨 소켓만, 이름 해석 없이, 프로세스까지 보는 옵션 조합입니다. sshd 가 2222 에서 돌고 있습니다.
테스트 서버 띄우기
0.0.0.0:8080 에서 듣는 HTTP 서버를 백그라운드로 띄우세요. 채점 시점에도 살아 있어야 합니다.
python3 의 내장 HTTP 서버를 백그라운드로 띄우세요. 채점 시점에도 살아 있어야 하므로 nohup 이나 setsid 를 함께 쓰는 편이 안전합니다.
바인딩 범위가 다른 두 서버
127.0.0.1:8081 에서만 듣는 두 번째 서버를 띄우고, 두 소켓의 Local Address:Port 를 각각 한 줄씩 /root/sock/bind.txt 에 적으세요. (예: 0.0.0.0:8080 과 127.0.0.1:8081)
python3 -m http.server 에는 바인딩 주소를 지정하는 옵션이 있습니다. 두 서버의 Local Address 열을 비교해 보세요.
열린 포트 확인
127.0.0.1:8080 으로 연결이 되는지 확인한 결과를 /root/sock/nc-open.txt 로 저장하세요.
nc 의 -z 는 데이터를 보내지 않고 연결만 시도합니다. -v 를 붙여야 결과 문장이 나옵니다.
닫힌 포트 확인
아무도 듣고 있지 않은 127.0.0.1:9999 로 연결을 시도한 결과를 /root/sock/nc-refused.txt 로 저장하세요. 출력에 refused 를 뜻하는 문구가 있어야 합니다.
아무도 듣고 있지 않은 포트로 연결하면 커널이 RST 를 돌려줍니다. 그 결과 문구를 그대로 저장하세요.
/proc/net/tcp 직접 읽기
/proc/net/tcp 에서 8080 포트의 LISTEN 소켓 줄을 찾아 그대로 /root/sock/proctcp.txt 에 저장하세요.
포트는 16진수로 적혀 있습니다. 8080 을 16진수로 바꾸면 무엇이 될까요? 상태 컬럼의 0A 는 LISTEN 입니다.
바깥 주소에서 두드려 보기
자기 인터페이스 IP(루프백 아님)로 8080 과 8081 을 각각 두드리고, 결과를 /root/sock/scope-test.txt 에 두 줄로 적으세요.
8080=<open|closed> / 8081=<open|closed>
루프백이 아니라 자기 인터페이스 IP 로 접속해야 차이가 드러납니다. 두 포트의 결과가 달라야 합니다.
리슨 소켓 표 만들기
/root/sock/report.csv 를 만드세요. 첫 줄은 port,bind,proto 헤더이고, 그 아래에 2222, 8080, 8081 세 포트에 대해 각각 한 줄씩 적으세요. bind 는 실제 리슨 주소, proto 는 tcp 입니다.
CSV 는 쉼표로 구분합니다. 헤더 줄을 포함하고, 앞에서 띄운 두 포트가 모두 들어가야 합니다.