📚 네트워크 · 패킷 분석 › 02. 포트 · 프로토콜 분석 — 99편
이전 글: 98. 포트·프로토콜 보안 점검 체크리스트 · 다음 글: 100. SOC Port 분석
참고(리눅스 시스템 기초): 37. Listening Port 보안 점검 — LISTEN 포트 점검의 기본 명령과 개념
"이 서버의 포트 노출 현황을 정리해 주세요"라는 요청을 받았다고 가정해 봅시다. 결과물은 포트 목록이 아니라 다음 질문에 답하는 보고서여야 합니다.
이 글은 실습 VM 한 대(web01, 192.168.10.20)를 예로 이 과정을 끝까지 진행합니다. 여기서 확인한 노출 현황은 다음 03. Wireshark 패킷 분석 시리즈에서 "실제로 어떤 패킷이 오갔는가"를 보는 출발점이 됩니다.
| 조건 | 확인 대상 | 대표 명령 |
|---|---|---|
| ① 서비스가 LISTEN 중인가 | 소켓 | ss -tulnp |
| ② 어느 주소에 바인드됐는가 | 로컬 주소(loopback / 특정 IP / 전체) | ss 출력의 Local Address |
| ③ 방화벽이 어느 출발지를 허용하는가 | 호스트 방화벽(+ 네트워크 방화벽·보안 그룹) | firewall-cmd, ufw, nft |
세 조건이 모두 열려 있어야 실제로 접근할 수 있습니다. 그리고 ④ 다른 호스트에서의 도달 확인으로 판단이 맞는지 검증합니다.
| 열 | 내용 |
|---|---|
| 포트/프로토콜 | 예: 443/tcp |
| 프로세스·유닛·패키지 | 예: nginx / nginx.service / nginx 패키지 |
| 식별된 프로토콜 | 예: TLS(HTTP/1.1) — 네트워크 응답으로 확인 |
| 바인드 | loopback / 특정 IP / 전체 |
| 방화벽 허용 범위 | any / 관리 대역 / 차단 |
| 도달 확인 | 허용 대역 VM, 비허용 VM 각각의 결과 |
| 정책 분류 | 외부 공개 / 내부 전용 / 노출 금지 (22편) |
| 판정 | 양호 / 취약 / 주의 / 확인 불가 (23편) |
| 분석 단계 | 참고 글 |
|---|---|
| 포트·서비스 매핑 원칙 | 01. 포트 번호 체계, 02. 서비스와 포트 매핑 |
| 프로세스 기반 식별 | 20. 비표준 포트에서 동작하는 서비스 식별 |
| TLS 확인 | 06. HTTPS와 TLS Handshake |
| DB 노출 3층 | 19. DB 포트 노출 점검 |
| 이상 연결 | 21. 정상 포트로 위장한 통신 |
| 정책·판정 기준 | 22. 노출 정책, 23. 점검 체크리스트 |
서버 한 대 분석의 전체 흐름입니다.

그림 1. 서버 1대의 포트 노출을 분석하는 5단계
[0] 기본 정보: 호스트명·IP·인터페이스·라우팅 (분석 대상 확정)
↓
[1] LISTEN 인벤토리: ss -tulnp → 포트 목록
↓
[2] 식별: PID → 실행 파일 → 패키지 → 서비스 유닛 → "무엇이" 열었는가
↓
[3] 바인드 분류: loopback / 특정 IP / 전체 → "어느 주소로" 열었는가
↓
[4] 방화벽: zone·규칙·기본 정책 → "누구에게" 허용하는가
↓
[5] 도달 확인: 허용 대역 VM / 비허용 VM 에서 연결 시도 → 판단 검증
↓
[6] 프로토콜 확인: 배너·HTTP·TLS 응답 → 포트와 프로토콜 일치 여부
↓
[7] 연결·로그: ESTABLISHED 연결, 인증 실패 로그, 시간 동기화
↓
[8] 노출 매트릭스 작성 → 정책 대조 → 판정 → 조치 권고 → 보고서
[1]~[4]는 서버 내부 관점, [5]~[6]은 외부 관점입니다. 두 관점이 일치하지 않으면(예: 방화벽에서 막았다고 생각했는데 도달됨) 그 차이 자체가 가장 중요한 발견입니다.
실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 분석 대상 web01(192.168.10.20), 허용 대역 확인용 VM(192.168.10.5), 비허용 대역 확인용 VM(192.168.20.50)은 모두 본인 소유 VM이며 IP·인터페이스 ens33은 예시입니다.
hostnamectl
ip -br addr
ip route
sudo ss -tulnp | tee listen-$(hostname)-$(date +%F).txt
for pid in $(sudo ss -tulnpH | grep -oP 'pid=\K[0-9]+' | sort -u); do
exe=$(sudo readlink -f /proc/$pid/exe)
unit=$(systemctl status "$pid" --no-pager 2>/dev/null | head -n1)
if command -v rpm >/dev/null && rpm -qf "$exe" >/dev/null 2>&1; then
pkg=$(rpm -qf "$exe")
elif command -v dpkg >/dev/null && dpkg -S "$exe" >/dev/null 2>&1; then
pkg=$(dpkg -S "$exe" | cut -d: -f1)
else
pkg="패키지 외"
fi
printf "%s | %s | %s | %s\n" "$pid" "$exe" "$pkg" "$unit"
done
Rocky에서는 rpm -qf, Ubuntu에서는 dpkg -S가 결과를 냅니다. 둘 다 실패하면 "패키지 외"로 표시되며 20편 절차로 추가 확인합니다. (Ubuntu는 /bin이 /usr/bin으로 연결된 구조라, 일부 파일은 패키지에 /bin/...·/sbin/... 경로로 등록되어 /usr/bin/... 경로로는 dpkg -S가 찾지 못할 수 있습니다. 그때는 /bin/... 경로로 다시 확인합니다.)
# Rocky (firewalld)
sudo firewall-cmd --get-active-zones
for z in $(sudo firewall-cmd --get-active-zones | awk '!/^ /{print $1}'); do sudo firewall-cmd --zone="$z" --list-all; done
# Ubuntu (ufw)
sudo ufw status verbose
# 공통: 실제 적용된 커널 규칙 (읽기 전용)
sudo nft list ruleset | less
firewall-cmd·ufw 결과는 "설정한 정책", nft list ruleset은 "커널에 실제 적용된 규칙"입니다. Docker 등 다른 프로그램이 추가한 규칙은 후자에서만 보입니다(22편 참고).
# [1]에서 찾은 포트만 대상으로, 허용 대역 VM과 비허용 대역 VM에서 각각 실행
for p in 22 80 443 3306 6379 8081; do
if timeout 2 bash -c "</dev/tcp/192.168.10.20/$p" 2>/dev/null; then
echo "$p/tcp open"
else
echo "$p/tcp closed/filtered"
fi
done
이미 알고 있는 포트의 도달 여부만 확인하는 것입니다. 포트 범위를 훑는 스캔과 그 탐지는 05. 네트워크 스캔 · 공격 징후 분석 시리즈에서 본인 실습 환경을 대상으로 다룹니다.
timeout 3 nc 192.168.10.20 22 # SSH 배너
curl -sI --max-time 3 http://192.168.10.20/ # HTTP 응답 헤더
openssl s_client -connect 192.168.10.20:443 </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates # TLS 인증서
sudo ss -tnp state established
timedatectl | grep -E "synchronized|Time zone"
sudo journalctl -u sshd --since "7 days ago" | grep -c "Failed password" # Ubuntu는 -u ssh
📷 [실습 화면 삽입] [1]~[3] 단계:
ss -tulnp와 PID·패키지·유닛 식별 결과
📷 [실습 화면 삽입] [5] 단계: 허용 대역 VM과 비허용 대역 VM의 도달 확인 결과 비교
📷 [실습 화면 삽입] 완성한 노출 매트릭스 표
실습 VM의 노출 매트릭스 형식 예시(값은 환경마다 다름)
| 포트 | 프로세스/유닛 | 프로토콜 확인 | 바인드 | 방화벽 | 도달(허용/비허용) | 정책 | 판정 |
|---|---|---|---|---|---|---|---|
| 22/tcp | sshd / sshd.service | SSH-2.0-OpenSSH_8.7 | 전체 | 192.168.10.0/24만 | open / filtered | 내부 전용(관리) | 양호 |
| 80/tcp | nginx / nginx.service | HTTP 301 → HTTPS | 전체 | any | open / open | 외부 공개 | 양호 |
| 443/tcp | nginx / nginx.service | TLS, 인증서 유효 | 전체 | any | open / open | 외부 공개 | 양호 |
| 3306/tcp | mariadbd / mariadb.service | MariaDB greeting | 전체 | any | open / open | 노출 금지 | 취약 |
| 6379/tcp | redis-server / redis.service | 연결 시 응답 없음(클라이언트 선발화) | loopback | - | closed / closed | 내부 전용 | 양호 |
| 8081/tcp | python3 / 사용자 세션 | HTTP (SimpleHTTP) | 192.168.10.20 | 차단 | filtered / filtered | 미등록 | 주의 |
이 표에서 3306은 바인드·방화벽·계정 세 층 중 앞의 두 층이 모두 열려 있어 비허용 대역에서도 도달합니다. 8081은 방화벽에 막혀 있지만 등록되지 않은 임시 서비스이므로 제거를 권고합니다.
# 서버 포트 노출 분석 보고서
## 1. 개요
- 대상: web01 (192.168.10.20, Rocky Linux 9) / 역할: 대외 웹 서버
- 분석 일시·시간대: 2026-09-26 14:00 KST / 분석자: (이름)
- 범위: 호스트 내부 점검 + 내부 2개 대역에서의 도달 확인 (네트워크 방화벽 규칙은 미열람 → 확인 불가)
## 2. 요약
- LISTEN 6개 중 취약 1건(3306 외부 도달), 주의 1건(8081 미등록 서비스)
## 3. 노출 매트릭스
(5절 표)
## 4. 주요 발견과 근거
- [취약] 3306/tcp: bind 전체(ss 출력), 방화벽 any(firewall-cmd 출력), 비허용 대역 도달(도달 확인 결과)
## 5. 조치 권고
- 3306: bind-address를 내부 IP로 제한, 방화벽을 앱 서버 출발지로 한정, host='%' 계정 점검
- 8081: 서비스 종료 및 실행 주체 확인
## 6. 한계
- 점검 시점의 상태이며, 네트워크 방화벽·보안 그룹 규칙은 확인하지 못함
## 7. 첨부
- listen-web01-2026-09-26.txt, 방화벽 출력, 도달 확인 결과
점검 체크리스트
| 관찰 내용 | 정상일 수 있는 경우 | 의심해야 하는 경우 |
|---|---|---|
| 방화벽 허용인데 도달 안 됨 | 네트워크 방화벽·보안 그룹에서 추가 차단 | 서비스 다운, 라우팅 문제 (가용성 이슈) |
| 방화벽 차단인데 도달됨 | 다른 프로그램(Docker 등)이 추가한 커널 규칙 | 누군가 규칙을 우회하도록 변경, 포워딩 설정 |
| loopback 바인드인데 외부에서 응답 | 리버스 프록시가 해당 서비스를 중계(설계된 경우) | 알 수 없는 포워딩·터널 프로세스 존재 |
| 프로토콜 확인 결과가 기대와 다름 | 서비스 설정 변경 | 21편의 포트-프로토콜 불일치 |
| 알 수 없는 ESTABLISHED 연결 | 업데이트·모니터링 에이전트 | 패키지 외 프로세스의 외부 연결 |
도달 확인 자체도 로그를 남깁니다. 이는 관제에서 보이는 모습을 미리 경험하는 좋은 기회입니다.
# 분석 대상 서버에서: 방화벽 거부 로그 (22편에서 로깅을 켠 경우)
sudo journalctl -k --since "10 min ago" | grep -iE "REJECT|DROP" # Rocky
sudo grep "UFW BLOCK" /var/log/ufw.log | tail # Ubuntu
방화벽 거부 로그 형식 예시(값은 환경마다 다름)
kernel: filter_IN_public_REJECT: IN=ens33 OUT= SRC=192.168.20.50 DST=192.168.10.20 PROTO=TCP SPT=40122 DPT=8081 SYN
비허용 대역 VM(192.168.20.50)의 시도가 8081에서 거부된 기록이 남습니다. 어떤 패킷이 오갔는지(SYN에 대한 응답이 RST인지, ICMP인지, 무응답인지)는 03. Wireshark 패킷 분석 시리즈에서 패킷 단위로 확인합니다.
ss·journal·방화벽 로그), 네트워크(경계 방화벽 세션 로그, IDS/NSM), 자산·변경 관리(서비스 등록 여부).[::]) 바인드도 함께 봅니다.