DB 접속 실패 로그가 쏟아지는데 애플리케이션 설정이 틀린 건지 포트가 막힌 건지 알 수 없습니다. ping은 성공하지만 TCP 3306 연결은 별개의 문제입니다.
L4 포트 점검을 빠르게 끝내야 앱, 방화벽, 서비스 중 어디를 볼지 결정할 수 있습니다.
L4 포트 통신 점검: telnet과 nc
서비스가 갑자기 안 된다는 신고를 받았을 때, 가장 먼저 해야 할 일은 네트워크 레이어를 단계적으로 좁혀 나가는 것입니다. L3(IP)까지는 ping으로 확인했다면, 다음은 L4(TCP/UDP 포트)가 열려 있는지 확인해야 합니다.
이 챕터에서는 현장에서 가장 많이 사용하는 두 도구 — telnet과 nc(netcat) — 를 사용하여 포트 통신을 점검하는 방법을 익힙니다.
오전 9시, 개발팀에서 "새로 배포한 API 서버에 연결이 안 된다"는 티켓이 들어옵니다. 애플리케이션 로그에는 아무것도 없습니다. 이 상황에서 인프라 엔지니어가 가장 먼저 하는 것은 포트 레벨에서 통신이 되는지 확인하는 것입니다.
telnet api-server 8080 하나로 문제가 방화벽인지, 데몬인지, 아니면 네트워크 경로인지를
30초 안에 구분할 수 있습니다. 이 판단이 빠를수록 장애 복구 시간(MTTR)이 줄어듭니다.
telnet으로 포트 연결 확인
telnet은 원래 원격 터미널 접속 프로토콜이지만, 오늘날 인프라 엔지니어들은 포트 연결 테스트 도구로 주로 사용합니다.
- 1telnet을 포트 연결 테스트 도구로 활용할 수 있다
- 2TCP 3-Way Handshake의 성공·실패 유형별 결과를 해석할 수 있다
- 3Connection Refused와 Connection Timeout의 근본적 차이를 구분할 수 있다
- 4nc(netcat)의 -z/-v/-u/-l 옵션과 포트 스캔 패턴을 활용할 수 있다
- 5iptables DROP과 REJECT의 차이를 이해하고 방화벽 동작을 시뮬레이션할 수 있다
- 6포트 점검 표준 절차(SOP) 스크립트를 작성할 수 있다
which telnet || apt-get install -y telnetnc -h 2>&1 | head -3ss -tlnpiptables 규칙 추가/삭제 실습에는 root(sudo) 권한이 필요
telnet의 포트 연결 테스트 원리
서비스가 올라가 있는데 외부에서 접속이 안 됩니다. curl도 타임아웃, 브라우저도 응답 없음입니다. 방화벽인지, 프로세스가 안 떴는지, 바인딩 주소가 잘못됐는지 짐작만 됩니다. telnet <host> <port> 한 줄이면 포트까지 TCP 연결이 되는지 여부를 즉시 확인할 수 있습니다.
확대
telnet은 지정한 호스트와 포트로 TCP 3-way handshake를 시도합니다.
클라이언트 → SYN → 서버:포트
클라이언트 ← SYN-ACK ← 서버:포트 (포트가 열려있으면)
클라이언트 → ACK → 서버:포트
handshake가 성공하면 포트가 열려 있는 것입니다. 실패하는 방식에 따라 원인이 달라집니다:
- 즉시 "Connection refused" → TCP RST 패킷 수신 → 서버에 도달했으나 해당 포트에 LISTEN 프로세스 없음
- 일정 시간 후 Timeout → 패킷이 응답 없이 사라짐 → 방화벽(ACL, Security Group, iptables)이 DROP
- 연결 성공 후 빈 화면 → TCP 연결 수립됨 → 포트 정상 오픈
telnet은 TCP 전용입니다. UDP 포트 확인에는 nc를 사용해야 합니다.
포트를 두드리면 실제로 오가는 것 — SYN 한 발의 4단계
telnet·nc 한 줄이 포트 여닫힘을 알아내는 실제 과정 — SYN 한 발의 4단계
telnet db 3306이나 nc -zv db 3306 한 줄이면 "포트가 열렸나"를 즉시 알 수 있습니다. 이 도구들이 하는 일은 단 하나 — 대상 IP:포트로 TCP SYN 한 발을 쏘고 무엇이 돌아오는지 보는 것입니다. 돌아오는 응답이 SYN-ACK냐, RST냐, 아무것도 아니냐 — 이 세 갈래가 각각 다른 원인을 가리키므로, 그 분기를 단계로 알면 방화벽·서비스·경로 중 어디가 문제인지 30초 안에 좁힙니다.
[내 PC] nc -zv 10.0.0.5 3306
│
① 라우팅·ARP로 next-hop 결정 후 SYN 발사 (목적지 IP:3306으로 연결 요청)
│
② 목적지(또는 경로)가 응답을 결정
│
├─► SYN-ACK 회신 → ③a 내 커널이 ACK로 연결 완성 → "succeeded / Connected" = 열림
│
├─► RST 회신 → ③b 즉시 "Connection refused" = 닫힘/거부
│
└─► (무응답) → ③c SYN 재전송하다 "Connection timed out" = 드롭
▼
Connection to 10.0.0.5 3306 port [tcp/mysql] succeeded!
각 갈래가 하는 일과, 그 뜻(다음 확인):
| 단계 | 하는 일 | 무슨 뜻(다음 확인) |
|---|---|---|
| ① SYN 발사 | 라우팅으로 next-hop을 정하고 그 MAC을 ARP로 해석한 뒤 대상 IP:포트로 TCP SYN 전송 | 라우팅·ARP 실패면 No route to host = L3부터 어긋남(포트 문제 아님) |
| ②→③a SYN-ACK | 그 포트에 LISTEN 프로세스가 있어 커널이 SYN-ACK로 수락 → 내 커널이 ACK로 3-way 완성 | succeeded·Connected = L4 정상. 그 위 계층(앱·인증)으로 조사 이동 |
| ②→③b RST | 도달은 했으나 그 포트에 LISTEN이 없어 커널이 RST 회신 → 즉시 refused | 서비스 미기동·다른 포트 LISTEN. 단 방화벽 REJECT도 RST를 위장하니 ss -tlnp로 실제 LISTEN 대조 |
| ②→③c 무응답 | 경로·목적지 방화벽이 SYN을 조용히 DROP → 응답이 없어 재전송만 반복 | 몇 초 뒤 timeout = 방화벽·보안그룹 차단 또는 호스트 다운. traceroute·인바운드 규칙 확인 |
| 구분 포인트 | refused는 즉시·timeout은 지연 — 응답 속도가 두 원인을 가르는 1차 단서 | UDP는 무응답이 정상일 수 있어 이 판정이 부정확 → 실제 프로토콜로 확인(dig·ntpdate -q) |
즉 포트 점검은 SYN 한 발에 돌아온 세 가지 응답을 읽는 일입니다 — SYN-ACK(열림)·RST(닫힘/거부)·무응답(드롭). 여기서 핵심은 refused와 timed out을 응답 속도로 가르는 것입니다: 즉시 거부면 패킷이 목적지까지 갔다는 뜻이라 "네트워크는 살아있고 서비스가 없다"로 좁혀 ss -tlnp로 LISTEN을 보고, 지연 후 timeout이면 "경계에서 삼켜졌다"로 보고 traceroute와 방화벽·보안그룹 인바운드 규칙부터 확인합니다. 다만 refused가 늘 서비스 부재는 아니라 방화벽 REJECT가 RST를 위장할 수 있고, UDP는 무응답이 정상일 수 있어 nc -zv -u의 '열림' 판정을 그대로 믿지 말고 실제 프로토콜 질의로 확인해야 합니다.
기본 사용법
# 실습 디렉토리 준비
mkdir -p /tmp/networking/part3/exam_12 && cd /tmp/networking/part3/exam_12
# 기본 형식
telnet [호스트] [포트]
# 예시: 웹 서버 80 포트 확인
telnet 192.168.1.100 80
# 예시: HTTPS 443 포트 확인
telnet google.com 443
# 예시: MySQL 3306 포트 확인
telnet db-server 3306
- 응답 메시지 먼저 확인—"Connection succeeded" 또는 "Connected to" 가 나오면 포트 열림 — "Connection refused"면 서비스 미기동, 타임아웃이면 방화벽 차단
- 응답 속도로 차단 여부 구분—즉시 Connection refused는 서버가 거절, 3~5초 후 타임아웃은 방화벽이 패킷을 조용히 버리는 것(DROP 정책)
- nc exit code 조합—nc -zv 성공 시 exit 0, 실패 시 exit 1 — 스크립트 자동화에서 $?로 분기할 때 기준값
결과 해석
Case 1 - 포트 열림 (연결 성공)
Trying 192.168.1.100...
Connected to 192.168.1.100.
Escape character is '^]'.
이 상태에서 빈 화면이 나타나면 TCP 연결이 수립된 것입니다. Ctrl+] 후 quit으로 종료합니다.
Case 2 - Connection Refused (서비스 없음)
Trying 192.168.1.100...
telnet: Unable to connect to remote host: Connection refused
호스트에는 도달했지만 해당 포트에서 수신 대기 중인 프로세스가 없습니다.
Case 3 - Connection Timeout (방화벽 차단)
Trying 192.168.1.100...
(응답 없음... 시간 경과 후)
telnet: Unable to connect to remote host: Connection timed out
패킷이 방화벽에서 DROP되고 있습니다.
실제 공개 서버로 telnet 테스트를 연습합니다.
1단계: HTTP 포트 확인
telnet google.com 80
연결되면 아래처럼 HTTP 요청을 직접 입력해볼 수 있습니다:
GET / HTTP/1.0
Host: google.com
(빈 줄 두 번 입력)
HTML 응답이 반환되면 telnet으로 HTTP 통신이 가능함을 확인한 것입니다.
2단계: 존재하지 않는 포트로 Refused 확인
# 로컬에서 열려있지 않은 포트로 테스트
telnet localhost 9999
예상 결과:
Trying ::1...
telnet: connect to address ::1: Connection refused
3단계: 방화벽 테스트용 Timeout 시뮬레이션
iptables로 임시 DROP 규칙을 추가한 후 테스트합니다 (root 필요):
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
# DROP 규칙 추가
sudo iptables -I INPUT -p tcp --dport 8888 -j DROP
# 다른 터미널에서 nc로 8888 포트 열기
nc -l 8888 &
# telnet으로 접속 시도 (Timeout 발생)
timeout 10 telnet localhost 8888
# 규칙 제거
sudo iptables -D INPUT -p tcp --dport 8888 -j DROP
nc(netcat)로 포트 스캔
nc(netcat)는 "네트워크의 스위스 아미 나이프"라 불리는 도구입니다. TCP/UDP 포트 스캔, 간이 서버, 파일 전송 등 다양한 용도로 활용됩니다.
nc -zv 옵션 이해
nc의 포트 스캔에 사용하는 핵심 옵션:
확대
| 옵션 | 의미 | 설명 |
|---|---|---|
-z | Zero I/O mode | 연결만 확인하고 데이터 전송 없음 |
-v | Verbose | 상세 결과 출력 |
-u | UDP | UDP 프로토콜 사용 (기본값은 TCP) |
-w N | Timeout | N초 후 연결 시도 중단 |
-l | Listen | 서버 모드, 해당 포트에서 수신 대기 |
포트 범위 스캔:
nc -zv 192.168.1.1 20-25
20번부터 25번까지 순서대로 스캔합니다.
nc는 TCP와 UDP를 모두 지원하므로 DNS(53/UDP), NTP(123/UDP) 등 UDP 서비스 점검에도 활용됩니다.
nc 주요 사용 패턴
# TCP 포트 단일 스캔
nc -zv 192.168.1.10 80
# UDP 포트 스캔
nc -zv -u 8.8.8.8 53
# 포트 범위 스캔 (20-80번)
nc -zv 10.0.0.1 20-80
# 타임아웃 3초로 빠른 확인
nc -zv -w 3 192.168.1.10 443
# 여러 포트를 한 번에 확인
for port in 22 80 443 3306 6379; do
nc -zv -w 2 192.168.1.10 $port 2>&1
done
nc 연결 결과 해석
# 성공
$ nc -zv 192.168.1.10 80
Connection to 192.168.1.10 80 port [tcp/http] succeeded!
# 실패 (Refused)
$ nc -zv 192.168.1.10 9999
nc: connect to 192.168.1.10 port 9999 (tcp) failed: Connection refused
# 실패 (Timeout)
$ nc -zv -w 5 10.0.0.1 8080
nc: connect to 10.0.0.1 port 8080 (tcp) failed: Connection timed out
nc의 핵심 기능을 실습합니다.
1단계: 로컬 포트 스캔
# SSH 포트 확인
nc -zv localhost 22
# 흔한 서비스 포트들을 한 번에 확인
for port in 22 80 443 3306 5432 6379 8080; do
result=$(nc -zv -w 2 localhost $port 2>&1)
echo "Port $port: $result"
done
2단계: nc로 임시 TCP 서버 열기
터미널 A (서버 역할):
nc -l 9000
터미널 B (클라이언트 역할):
nc localhost 9000
이후 어느 쪽에서든 텍스트를 입력하면 반대편으로 전송됩니다. 가장 단순한 양방향 채팅입니다.
3단계: nc로 파일 전송 테스트
터미널 A (수신측):
nc -l 9001 > received_file.txt
터미널 B (송신측):
echo "Hello from nc file transfer" | nc -w 3 localhost 9001
터미널 A에서 received_file.txt 내용 확인:
cat received_file.txt
4단계: UDP 포트 확인
# DNS 서버 UDP 53 포트 확인
nc -zv -u 8.8.8.8 53
# NTP 서버 UDP 123 포트 확인
nc -zv -u pool.ntp.org 123
Connection Refused vs Connection Timeout 심층 분석
이 두 오류를 정확히 구분하는 것이 빠른 장애 원인 파악의 핵심입니다.
두 오류의 원인과 해결 방향
Connection Refused 발생 흐름:
클라이언트 → SYN → 방화벽(허용) → 서버 OS
서버 OS: "이 포트에 LISTEN 중인 소켓이 없다"
서버 OS → RST → 클라이언트
결과: 즉시 "Connection refused"
확대
원인: 데몬(서비스)이 실행 중이지 않거나, 잘못된 포트로 LISTEN 중이거나, 서비스가 크래시됨
해결 방향:
# 서비스 상태 확인
systemctl status nginx
# 또는
ps aux | grep nginx
# 실제로 어느 포트에서 LISTEN 중인지 확인
ss -tlnp | grep nginx
Connection Timeout 발생 흐름:
클라이언트 → SYN → 방화벽(DROP) → 패킷 소멸
클라이언트: "응답이 없다... 기다린다..."
일정 시간 후: "Connection timed out"
원인: iptables DROP 규칙, AWS Security Group 미허용, 하드웨어 방화벽 ACL, 라우팅 경로 없음
해결 방향:
# iptables 규칙 확인
sudo iptables -L -n -v | grep DROP
# 클라우드 환경이면 Security Group / 방화벽 정책 확인
# traceroute로 어느 구간에서 패킷이 막히는지 확인
traceroute 목적지IP
REJECT vs DROP 차이: 방화벽 정책이 DROP이면 Timeout, REJECT이면 즉시 "Connection refused" 또는 "No route to host"가 반환됩니다. REJECT는 거부 패킷을 돌려보내고, DROP은 무응답으로 패킷을 버립니다.
실제 방화벽 동작을 재현하여 두 오류의 차이를 체감합니다.
사전 준비: 테스트용 서비스 실행
# Python으로 8080 포트에 임시 서버 실행
python3 -m http.server 8080 &
SERVER_PID=$!
echo "서버 PID: $SERVER_PID"
시나리오 1: 정상 연결
nc -zv localhost 8080
# 예상: Connection succeeded
시나리오 2: 서비스 중지 → Connection Refused
이 명령은 프로세스를 종료해 연결 중인 사용자나 배치 작업을 중단시킬 수 있습니다. PID와 프로세스 이름이 목표 서비스인지 확인한 뒤 실행하세요.
kill $SERVER_PID
nc -zv localhost 8080
# 예상: Connection refused (서비스 없음)
시나리오 3: iptables DROP → Connection Timeout
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
# 서비스 재시작
python3 -m http.server 8080 &
SERVER_PID=$!
# DROP 규칙 추가
sudo iptables -I INPUT -p tcp --dport 8080 -j DROP
# Timeout 확인 (3초 타임아웃으로 빠르게)
nc -zv -w 3 localhost 8080
# 예상: Connection timed out
# DROP 규칙 제거
sudo iptables -D INPUT -p tcp --dport 8080 -j DROP
# 정리
kill $SERVER_PID
시나리오 4: iptables REJECT → 즉시 거부
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
python3 -m http.server 8080 &
SERVER_PID=$!
# REJECT 규칙 추가
sudo iptables -I INPUT -p tcp --dport 8080 -j REJECT
# 즉시 거부 확인
nc -zv localhost 8080
# 예상: Connection refused (REJECT이므로 즉시 응답)
sudo iptables -D INPUT -p tcp --dport 8080 -j REJECT
kill $SERVER_PID
실전 트러블슈팅 시나리오
상황: 개발팀이 신규 Node.js 앱을 서버에 배포했지만 외부에서 http://서버IP:3000으로 접속이 안 됩니다.
1단계: 서버 내부에서 포트 확인
# 서버 내부에서 로컬호스트로 접속 테스트
nc -zv localhost 3000
결과: Connection succeeded → 앱은 실행 중
2단계: 외부에서 접속 테스트
# 다른 서버나 PC에서 실행
nc -zv 서버IP 3000
결과: Connection timed out → 방화벽 문제
3단계: iptables 확인
sudo iptables -L INPUT -n -v
# 3000번 포트 허용 규칙이 없음을 확인
4단계: 방화벽 규칙 추가
이 명령은 방화벽 정책을 변경해 현재 접속 중인 세션이나 운영 트래픽에 즉시 영향을 줄 수 있습니다. 적용 전 허용 대상 IP·포트와 롤백 명령을 확인하세요.
sudo iptables -A INPUT -p tcp --dport 3000 -j ACCEPT
# 또는 firewalld 사용 환경이라면:
sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --reload
5단계: 재확인
nc -zv 서버IP 3000
# 예상: Connection succeeded
핵심 교훈: 내부에서는 되는데 외부에서 안 된다면, 먼저 방화벽(iptables, firewalld, Security Group)을 의심하세요.
상황: 애플리케이션 로그에 ECONNREFUSED 10.0.1.5:5432 에러가 반복됩니다.
1단계: 포트 연결 테스트
nc -zv 10.0.1.5 5432
결과: Connection refused
2단계: DB 서버에서 PostgreSQL 상태 확인
# DB 서버에 SSH 접속 후
systemctl status postgresql
결과: Active: failed → PostgreSQL이 죽어있음!
3단계: 로그 확인
journalctl -u postgresql -n 50
# 또는
tail -50 /var/log/postgresql/postgresql-14-main.log
4단계: PostgreSQL 재시작
이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.
systemctl start postgresql
systemctl status postgresql
5단계: 포트 재확인
nc -zv 10.0.1.5 5432
# 예상: Connection succeeded
추가 확인: PostgreSQL이 올바른 주소에서 LISTEN 중인지 확인
# postgresql.conf에서 listen_addresses 확인
grep listen_addresses /etc/postgresql/14/main/postgresql.conf
# 'localhost'만 있다면 외부 연결 불가 → '*' 또는 특정 IP로 변경 필요
핵심 교훈: Connection Refused는 "서비스가 없다"는 뜻입니다. 서비스 상태와 LISTEN 주소/포트 설정을 함께 확인하세요.
심화 — 거부(refused)의 출처를 의심하라
심화: RST를 만드는 세 출처 — refused가 늘 '서비스 없음'은 아니다
이 모듈은 'refused=서비스 없음, timeout=차단'으로 가르치지만, 실무에는 그 경계를 흐리는 경우가 있습니다. refused를 만드는 RST 패킷은 죽은 서비스만 보내는 게 아니라 방화벽·프록시도 흉내 낼 수 있어서, 단순 규칙을 그대로 믿으면 멀쩡한 서비스를 붙잡고 시간을 버립니다.
- 정상 닫힘: 포트에 LISTEN 프로세스가 없으면 커널이 RST를 돌려보내 즉시 refused (교과서 케이스).
- 방화벽 REJECT:
-j REJECT --reject-with tcp-reset규칙은 방화벽이 대신 RST를 만들어 보냅니다. 서비스가 멀쩡히 떠 있어도 refused처럼 보입니다 — DROP(무응답=timeout)과 달리 REJECT는 refused로 위장합니다. - 프록시·LB가 handshake를 대신 받음: L4 로드밸런서·포트포워더는 앞단에서 TCP 3-way handshake를 자기가 완료합니다. 그래서 백엔드가 죽어도
nc -z는 성공(열림)으로 뜨고, 실제 데이터를 보내야 뒤늦게 RST나 무응답이 드러납니다. - 그래서 판정을 한 겹 더: refused여도 그 RST가 서비스에서 온 건지 방화벽에서 온 건지, 열림이어도 진짜 백엔드인지 앞단 프록시인지 구분해야 합니다.
nc -v의 타이밍, 다른 위치에서의 재현, 실제 프로토콜 요청으로 교차 검증합니다.
즉 nc의 열림/거부 판정은 시작점일 뿐, '그 신호를 누가 보냈나'까지 물어야 오진을 피합니다.
상황: 앱 로그에 connection refused가 찍혀 DB가 죽은 줄 알았는데, DB 서버에 들어가 보니 서비스는 멀쩡히 떠서 5432를 LISTEN하고 로컬에서는 접속도 됩니다. 그런데 앱 서버에서 nc -zv DB 5432는 여전히 refused입니다.
원인: 경로의 방화벽에 -j REJECT --reject-with tcp-reset 규칙이 있어, 방화벽이 서비스 대신 RST를 돌려보낸 것입니다. 죽은 서비스가 보내는 RST와 방화벽이 만든 RST는 클라이언트 눈에 똑같이 refused로 보여, 'refused=서비스 없음'이라는 단순 규칙이 오진을 부릅니다.
진단: 먼저 DB 서버 로컬에서 실제 LISTEN을 확인해 서비스가 살아 있음을 못박고, 앱 서버에서 거부가 즉시 오는지(REJECT/죽은 서비스) 오래 걸린 뒤 timeout인지(DROP)를 구분합니다.
# DB 서버 로컬 — 서비스는 살아 있는가
ss -tlnp | grep 5432
# 경로 방화벽 — REJECT 규칙이 있는가
sudo iptables -L -n | grep -i reject
# RST가 DB 서버가 아니라 중간 장비에서 돌아오는지 대조
sudo tcpdump -ni any 'tcp port 5432 and tcp[tcpflags] & tcp-rst != 0'
해결: 방화벽에서 해당 출발지·포트를 ACCEPT로 허용(또는 REJECT 규칙 정정)합니다. '거부'의 출처를 서비스인지 방화벽인지 먼저 가르는 습관이, 멀쩡한 서비스를 재시작하며 시간을 버리는 일을 막습니다.
포트 점검 체크리스트
장애 발생 시 포트 레이어를 체계적으로 점검하는 표준 절차입니다.
#!/bin/bash
# port-check.sh - 포트 통신 종합 점검 스크립트
TARGET_HOST="${1:-localhost}"
TARGET_PORT="${2:-80}"
TIMEOUT=5
echo "===== 포트 통신 점검 시작 ====="
echo "대상: ${TARGET_HOST}:${TARGET_PORT}"
echo ""
# 1. DNS 해석 확인
echo "[1] DNS 해석 확인"
if host "${TARGET_HOST}" > /dev/null 2>&1; then
RESOLVED_IP=$(host "${TARGET_HOST}" | awk '/has address/ {print $4}' | head -1)
echo " 성공: ${TARGET_HOST} → ${RESOLVED_IP}"
else
echo " 실패: DNS 해석 불가"
fi
echo ""
# 2. L3 ping 확인
echo "[2] L3 ping 확인 (ICMP)"
if ping -c 3 -W 2 "${TARGET_HOST}" > /dev/null 2>&1; then
echo " 성공: ICMP 응답 있음"
else
echo " 실패 또는 ICMP 차단됨 (ping 차단은 정상일 수 있음)"
fi
echo ""
# 3. L4 TCP 포트 확인
echo "[3] L4 TCP 포트 확인 (nc)"
NC_RESULT=$(nc -zv -w "${TIMEOUT}" "${TARGET_HOST}" "${TARGET_PORT}" 2>&1)
if echo "${NC_RESULT}" | grep -q "succeeded"; then
echo " 성공: 포트 ${TARGET_PORT} OPEN"
elif echo "${NC_RESULT}" | grep -q "refused"; then
echo " 실패: Connection Refused (서비스 미실행 또는 잘못된 포트)"
else
echo " 실패: Connection Timeout (방화벽 DROP 의심)"
fi
echo ""
echo "===== 점검 완료 ====="
사용법:
chmod +x port-check.sh
./port-check.sh google.com 443
./port-check.sh 192.168.1.10 3306
핵심 정리
| 도구 | 주용도 | 프로토콜 | 특징 |
|---|---|---|---|
telnet | 포트 연결 확인, HTTP 수동 테스트 | TCP만 | 대부분의 시스템에 기본 설치 |
nc -zv | 포트 스캔, 범위 스캔 | TCP + UDP | 더 유연하고 스크립트에 적합 |
nc -l | 임시 서버, 연결 수신 대기 | TCP + UDP | 반대편 연결 테스트에 유용 |
오류 메시지 요약:
Connection refused= 패킷 도달 O, 서비스 없음 → 데몬 상태 확인Connection timed out= 패킷 도달 X → 방화벽/라우팅 확인Connection succeeded= L4 통신 정상 → 그 위 계층(앱, 인증) 확인
명령어·단축키 빠른 참조
이 모듈에서 다룬 L4 포트 점검 명령을 실전 옵션과 함께 모았습니다. "예" 열의 조합을 그대로 써도 됩니다.
| 명령어/옵션 | 용도 | 자주 쓰는 예 |
|---|---|---|
telnet <host> <port> | 단발 TCP 포트 연결 확인(수동) | telnet db-server 3306 |
nc -zv <host> <port> | 데이터 없이 열림/거부 판정 | nc -zv 192.168.1.10 443 |
nc -zv <host> <범위> | 여러 포트 한 번에 스캔 | nc -zv 10.0.0.1 20-100 |
nc -zv -u <host> <port> | UDP 포트 점검(무응답 주의) | nc -zv -u 8.8.8.8 53 |
nc -w <초> | 응답 없는 포트에서 무한 대기 방지 | nc -zv -w 3 10.0.0.1 8080 |
nc -l <port> | 임시 리스닝 서버(반대편 테스트) | nc -l 9000 |
ss -tlnp | 로컬 LISTEN 포트·프로세스 확인 | ss -tlnp | grep 5432 |
iptables -I INPUT … -j DROP/REJECT | Refused·Timeout 재현·차단 | sudo iptables -I INPUT -p tcp --dport 8080 -j DROP |
iptables -L -n | REJECT/DROP 규칙 확인(거부 출처 판별) | sudo iptables -L -n | grep -i reject |
traceroute <IP> | timeout 시 어느 구간에서 막히는지 | traceroute 10.0.0.1 |
관련 모듈로 더 깊이:
- netstat과 ss 명령어로 커넥션 상태(ESTABLISHED 등) 분석 — 포트가 열려 있는지 반대편에서
ss로 LISTEN 상태를 확인하는 법 - 3-Way Handshake 원리와 신뢰성 높은 포트 체계 — telnet은 TCP만, nc는 UDP까지 — 프로토콜별 포트 점검의 차이
- 웹 서버에서 DB 접속 실패 시 원인 격리 프로세스 — Refused/Timeout 오류를 L3/L4/L7로 격리하는 전체 흐름
다음 모듈에서는 ss와 lsof로 포트를 점유한 프로세스를 찾고 안전하게 종료하는 방법을 다룹니다.