99. 서버 1대의 포트 노출 현황 종합 분석

changseop lee·5일 전

📚 네트워크 · 패킷 분석 › 02. 포트 · 프로토콜 분석 — 99편
이전 글: 98. 포트·프로토콜 보안 점검 체크리스트 · 다음 글: 100. SOC Port 분석
참고(리눅스 시스템 기초): 37. Listening Port 보안 점검 — LISTEN 포트 점검의 기본 명령과 개념

1. 왜 알아야 하는가

  1. 포트 · 프로토콜 분석 시리즈의 마지막 글입니다. 지금까지 포트 체계(01편), 서비스 매핑(02편), 개별 프로토콜(04~19편), 식별과 위장(20·21편), 정책과 체크리스트(22·23편)를 살펴봤습니다. 이번에는 이것을 서버 한 대에 한 번에 적용합니다.

"이 서버의 포트 노출 현황을 정리해 주세요"라는 요청을 받았다고 가정해 봅시다. 결과물은 포트 목록이 아니라 다음 질문에 답하는 보고서여야 합니다.

  • 이 서버에서 어떤 서비스·프로토콜이 어떤 포트로 통신하는가?
  • 그중 누구에게(어느 네트워크에) 열려 있는가?
  • 그것이 정책상 허용된 상태인가?
  • 판단의 근거(명령 출력·설정) 는 무엇인가?

이 글은 실습 VM 한 대(web01, 192.168.10.20)를 예로 이 과정을 끝까지 진행합니다. 여기서 확인한 노출 현황은 다음 03. Wireshark 패킷 분석 시리즈에서 "실제로 어떤 패킷이 오갔는가"를 보는 출발점이 됩니다.


2. 핵심 개념

2-1. 노출 = 세 조건의 교집합

조건확인 대상대표 명령
① 서비스가 LISTEN 중인가소켓ss -tulnp
② 어느 주소에 바인드됐는가로컬 주소(loopback / 특정 IP / 전체)ss 출력의 Local Address
③ 방화벽이 어느 출발지를 허용하는가호스트 방화벽(+ 네트워크 방화벽·보안 그룹)firewall-cmd, ufw, nft

세 조건이 모두 열려 있어야 실제로 접근할 수 있습니다. 그리고 ④ 다른 호스트에서의 도달 확인으로 판단이 맞는지 검증합니다.

2-2. 분석 결과를 담는 노출 매트릭스

열내용
포트/프로토콜예: 443/tcp
프로세스·유닛·패키지예: nginx / nginx.service / nginx 패키지
식별된 프로토콜예: TLS(HTTP/1.1) — 네트워크 응답으로 확인
바인드loopback / 특정 IP / 전체
방화벽 허용 범위any / 관리 대역 / 차단
도달 확인허용 대역 VM, 비허용 VM 각각의 결과
정책 분류외부 공개 / 내부 전용 / 노출 금지 (22편)
판정양호 / 취약 / 주의 / 확인 불가 (23편)

2-3. 이 글에서 쓰는 이전 편 연결

분석 단계참고 글
포트·서비스 매핑 원칙01. 포트 번호 체계, 02. 서비스와 포트 매핑
프로세스 기반 식별20. 비표준 포트에서 동작하는 서비스 식별
TLS 확인06. HTTPS와 TLS Handshake
DB 노출 3층19. DB 포트 노출 점검
이상 연결21. 정상 포트로 위장한 통신
정책·판정 기준22. 노출 정책, 23. 점검 체크리스트

3. 동작 원리

서버 한 대 분석의 전체 흐름입니다.

노출 분석 파이프라인
그림 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]은 외부 관점입니다. 두 관점이 일치하지 않으면(예: 방화벽에서 막았다고 생각했는데 도달됨) 그 차이 자체가 가장 중요한 발견입니다.


4. 실제 명령어 / 실습

실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 분석 대상 web01(192.168.10.20), 허용 대역 확인용 VM(192.168.10.5), 비허용 대역 확인용 VM(192.168.20.50)은 모두 본인 소유 VM이며 IP·인터페이스 ens33은 예시입니다.

4-0. 기본 정보

hostnamectl
ip -br addr
ip route

4-1. LISTEN 인벤토리

sudo ss -tulnp | tee listen-$(hostname)-$(date +%F).txt

4-2. 프로세스·패키지·유닛 식별

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/... 경로로 다시 확인합니다.)

4-3. 방화벽 규칙 확인

# 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편 참고).

4-4. 외부 관점 도달 확인 (확인용 VM에서)

# [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. 네트워크 스캔 · 공격 징후 분석 시리즈에서 본인 실습 환경을 대상으로 다룹니다.

4-5. 프로토콜 확인

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 인증서

4-6. 연결·로그·시간

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의 도달 확인 결과 비교

📷 [실습 화면 삽입] 완성한 노출 매트릭스 표


5. 결과 확인

실습 VM의 노출 매트릭스 형식 예시(값은 환경마다 다름)

포트프로세스/유닛프로토콜 확인바인드방화벽도달(허용/비허용)정책판정
22/tcpsshd / sshd.serviceSSH-2.0-OpenSSH_8.7전체192.168.10.0/24만open / filtered내부 전용(관리)양호
80/tcpnginx / nginx.serviceHTTP 301 → HTTPS전체anyopen / open외부 공개양호
443/tcpnginx / nginx.serviceTLS, 인증서 유효전체anyopen / open외부 공개양호
3306/tcpmariadbd / mariadb.serviceMariaDB greeting전체anyopen / open노출 금지취약
6379/tcpredis-server / redis.service연결 시 응답 없음(클라이언트 선발화)loopback-closed / closed내부 전용양호
8081/tcppython3 / 사용자 세션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, 방화벽 출력, 도달 확인 결과

점검 체크리스트

  • 모든 LISTEN 포트가 노출 매트릭스에 포함되었다
  • 각 포트의 프로세스·유닛·패키지(또는 "패키지 외")를 기록했다
  • 내부 관점(바인드·방화벽)과 외부 관점(도달 확인)의 결과를 비교했다
  • 정책 분류와 판정, 판정 근거를 모두 적었다
  • 분석 범위 밖(네트워크 방화벽 등)은 "확인 불가"로 명시했다

6. 패킷 / 로그 분석

6-1. 내부·외부 관점이 어긋날 때

관찰 내용정상일 수 있는 경우의심해야 하는 경우
방화벽 허용인데 도달 안 됨네트워크 방화벽·보안 그룹에서 추가 차단서비스 다운, 라우팅 문제 (가용성 이슈)
방화벽 차단인데 도달됨다른 프로그램(Docker 등)이 추가한 커널 규칙누군가 규칙을 우회하도록 변경, 포워딩 설정
loopback 바인드인데 외부에서 응답리버스 프록시가 해당 서비스를 중계(설계된 경우)알 수 없는 포워딩·터널 프로세스 존재
프로토콜 확인 결과가 기대와 다름서비스 설정 변경21편의 포트-프로토콜 불일치
알 수 없는 ESTABLISHED 연결업데이트·모니터링 에이전트패키지 외 프로세스의 외부 연결

6-2. 도달 확인이 남긴 흔적 보기

도달 확인 자체도 로그를 남깁니다. 이는 관제에서 보이는 모습을 미리 경험하는 좋은 기회입니다.

# 분석 대상 서버에서: 방화벽 거부 로그 (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 패킷 분석 시리즈에서 패킷 단위로 확인합니다.


7. 보안관제 관점

  • 노출 매트릭스는 관제 기준선입니다. 이 표가 있으면 "web01로 외부 IP의 3306 연결 성립"이라는 이벤트를 곧바로 정책 위반·고위험으로 분류할 수 있습니다.
  • 흔적 위치 정리: 호스트(ss·journal·방화벽 로그), 네트워크(경계 방화벽 세션 로그, IDS/NSM), 자산·변경 관리(서비스 등록 여부).
  • 한계: 호스트 점검은 특정 시점의 스냅샷이고, 네트워크 방화벽·클라우드 보안 그룹·로드밸런서 설정은 서버 안에서 보이지 않습니다. 보고서에 범위와 한계를 반드시 적습니다.
  • 오탐 주의: 도달 확인이 "열림"이어도 인증·애플리케이션 계층에서 막혀 있을 수 있고, "닫힘"이어도 다른 경로(IPv6, 다른 인터페이스)로 열려 있을 수 있습니다. IPv6 주소([::]) 바인드도 함께 봅니다.
  • 이후 연결: 실제 패킷 확인은 03. Wireshark 패킷 분석, 외부 스캔 관점은 05. 네트워크 스캔 · 공격 징후 분석, 방화벽 규칙 심화는 06. 방화벽 · IDS/IPS 분석, 여러 장비 로그를 묶는 분석은 07. 네트워크 보안관제 통합 분석 시리즈에서 다룹니다.

8. 핵심 정리

  • 포트 노출은 LISTEN · 바인드 주소 · 방화벽 허용 범위의 교집합이며, 외부 도달 확인으로 검증합니다.
  • 포트마다 프로세스·유닛·패키지를 확인해 "무엇이 열었는가"를 증거로 남깁니다.
  • 내부 관점과 외부 관점이 어긋나는 지점이 가장 중요한 발견입니다.
  • 결과는 노출 매트릭스 + 정책 분류 + 판정 + 근거 + 한계를 갖춘 보고서로 정리합니다.
  • 이 매트릭스는 관제의 기준선이 되고, 다음 시리즈의 패킷 분석 출발점이 됩니다.

다음 글: 01. 패킷 캡처 원리 — NIC·Promiscuous 모드·미러링

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글