89. 비표준 포트에서 동작하는 서비스 식별

changseop lee·5일 전

📚 네트워크 · 패킷 분석 › 02. 포트 · 프로토콜 분석 — 89편
이전 글: 88. 위험 Port · 다음 글: 90. 정상 포트로 위장한 통신 — 443을 쓰는 비정상 트래픽
참고(리눅스 시스템 기초): 16. 프로세스와 네트워크 소켓 (ss -p) — 소켓과 프로세스를 연결해 보는 기본 방법

1. 왜 알아야 하는가

02편에서 "포트 번호만으로 서비스를 단정하면 안 된다"고 정리했습니다. 이번 글은 그 다음 단계, 그렇다면 실제로 무엇이 동작하는지 어떻게 확인하는가를 다룹니다.

비표준 포트는 크게 두 가지 이유로 등장합니다.

구분예
정상적인 이유같은 서버에 웹 서비스 여러 개(8080, 8443), 관리 콘솔, 개발용 서버, SSH 포트 변경(2222), 애플리케이션 고유 포트
의심해야 할 이유허가되지 않은 원격 접속 도구, 백도어 리스너, 탐지를 피하려는 목적의 포트 변경, 임시로 띄워 둔 파일 공유 서버

관제 이벤트나 점검 결과에 "알 수 없는 포트 45123 LISTEN" 같은 항목이 나왔을 때, 포트 번호를 검색해서 나온 서비스 이름을 그대로 적으면 틀릴 수 있습니다. 이 글의 목표는 증거에 기반해 서비스를 식별하는 절차를 갖추는 것입니다.


2. 핵심 개념

2-1. 식별의 두 방향

방향방법신뢰도조건
호스트 내부소켓 → 프로세스 → 실행 파일 → 패키지 → 서비스 유닛높음해당 서버 접근 권한 필요
네트워크접속 시 응답 형태(배너), 트래픽 첫 바이트 패턴, 프로토콜 파서 판정중간서버 접근 권한이 없어도 가능

가능하면 호스트 내부 확인이 우선이고, 네트워크 확인은 이를 보완하거나 서버 접근이 어려울 때 사용합니다.

2-2. 프로토콜별 "첫 신호"

많은 프로토콜은 연결 직후 누가 먼저 말하는지, 첫 바이트가 무엇인지로 구분할 수 있습니다.

프로토콜먼저 말하는 쪽첫 신호 특징
SSH서버(그리고 클라이언트도 버전 문자열 전송)SSH-2.0-... 형태의 텍스트 한 줄
FTP / SMTP서버220 ... 응답 코드로 시작하는 텍스트
HTTP클라이언트GET / HTTP/1.1 같은 요청 줄, 응답은 HTTP/1.1 200 OK
TLS (HTTPS 등)클라이언트첫 바이트 0x16(Handshake 레코드), 이어서 버전 0x03 0x0?
MySQL/MariaDB서버버전 문자열을 포함한 greeting 패킷
Redis클라이언트*1\r\n$4\r\nPING\r\n 같은 RESP 형식 텍스트

"서버가 먼저 말하는 프로토콜"은 연결만 해도 정체가 드러나고, "클라이언트가 먼저 말하는 프로토콜"은 적절한 요청을 보내야 응답을 볼 수 있습니다.

2-3. 자동 프로토콜 식별

IDS·NSM 도구는 포트 번호와 관계없이 페이로드를 보고 프로토콜을 판정하는 기능을 가지고 있습니다.

  • Suricata: 애플리케이션 계층 프로토콜 탐지 결과를 이벤트의 app_proto 필드로 기록
  • Zeek: 동적 프로토콜 탐지(DPD)로 비표준 포트의 HTTP·SSH 등을 식별해 conn.log의 service 필드에 기록
  • Wireshark: 알려진 포트 기반 해석 + 휴리스틱, 수동으로는 "Decode As" 기능

이 도구들의 상세 사용법은 03. Wireshark 패킷 분석, 06. 방화벽 · IDS/IPS 분석 시리즈에서 다룹니다.


3. 동작 원리

"알 수 없는 포트"를 발견했을 때의 식별 흐름입니다.

비표준 포트 식별
그림 1. 포트 번호가 아니라 '누가 · 무엇을 · 왜' 열었는지로 판정합니다

 알 수 없는 포트 발견 (예: TCP 8081 LISTEN)
          ↓
 [호스트 접근 가능?] ── 예 ──→ ss -tlnp  → PID·프로세스 이름
          │                         ↓
          │                  /proc/<PID>/exe → 실제 실행 파일 경로
          │                         ↓
          │                  rpm -qf / dpkg -S → 어느 패키지 소속인가 (없으면 수동 설치 파일)
          │                         ↓
          │                  systemctl status <PID> → 어떤 서비스 유닛이 띄웠는가
          │                         ↓
          │                  실행 인자·작업 디렉터리·실행 계정 확인
          ↓ 아니오
 [네트워크 확인] 연결 후 대기 → 서버가 먼저 말하는가? (SSH/FTP/SMTP/DB 배너)
          ↓ 응답 없음
 HTTP 요청 시도 → HTTP 응답인가?
          ↓ 아니오
 TLS 연결 시도 → 인증서·프로토콜 협상 결과 확인
          ↓
 IDS/NSM의 app_proto·service 판정과 대조
          ↓
 결론: "포트 8081 = python3 http.server (사용자 계정 실행, 패키지 외 스크립트)"

핵심은 결론에 포트 번호가 아니라 프로세스·실행 파일·실행 주체가 들어가야 한다는 점입니다.


4. 실제 명령어 / 실습

실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 인터페이스 ens33은 예시이며, 서버 VM 192.168.10.20과 확인용 VM 모두 본인 소유입니다.

4-1. 필요한 도구 설치

# Rocky Linux
sudo dnf install -y nmap-ncat curl openssl lsof

# Ubuntu
sudo apt update && sudo apt install -y netcat-openbsd curl openssl lsof

4-2. 실습용 비표준 포트 서비스 띄우기

# 터미널 1: 8081 포트에 간단한 HTTP 서버 (실습 후 Ctrl+C로 종료)
mkdir -p ~/lab-web && cd ~/lab-web && echo "lab" > index.html
python3 -m http.server 8081 --bind 192.168.10.20

4-3. 호스트 내부에서 식별

sudo ss -tlnp | grep ':8081'
PID=$(sudo ss -tlnpH 'sport = :8081' | grep -oP 'pid=\K[0-9]+' | head -n1)
echo "$PID"
sudo readlink -f /proc/$PID/exe          # 실제 실행 파일
sudo cat /proc/$PID/cmdline | tr '\0' ' '; echo   # 실행 인자
sudo readlink -f /proc/$PID/cwd          # 작업 디렉터리
ps -o user=,pid=,ppid=,lstart=,cmd= -p "$PID"   # 실행 계정·시작 시각·부모 프로세스
systemctl status "$PID" --no-pager       # 서비스 유닛 소속 여부
sudo lsof -i :8081 -P -n

실행 파일이 어느 패키지에 속하는지 확인합니다.

# Rocky Linux
rpm -qf "$(sudo readlink -f /proc/$PID/exe)"
# Ubuntu
dpkg -S "$(sudo readlink -f /proc/$PID/exe)"

4-4. 네트워크에서 식별 (다른 본인 VM에서)

# 서버가 먼저 말하는지 확인 (SSH 포트 예시, 3초 후 종료)
timeout 3 nc 192.168.10.20 22

# HTTP 응답 여부 확인
curl -sv --max-time 3 http://192.168.10.20:8081/ -o /dev/null

# TLS 서비스인지 확인 (8443 등에서)
openssl s_client -connect 192.168.10.20:8443 </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates

nmap의 서비스 버전 탐지(-sV)도 같은 원리를 자동화한 것이지만, 스캔은 05. 네트워크 스캔 · 공격 징후 분석 시리즈에서 본인 실습 환경을 대상으로만 다룹니다.

📷 [실습 화면 삽입] ss -tlnp와 /proc/<PID>/exe, cmdline 확인 결과

📷 [실습 화면 삽입] 다른 VM에서 nc(SSH 배너)와 curl -v(HTTP 응답 헤더) 결과


5. 결과 확인

SSH 배너 형식 예시(값은 환경마다 다름)

SSH-2.0-OpenSSH_8.7

curl -sv 응답 헤더 일부 형식 예시(값은 환경마다 다름)

< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.9.18
< Content-type: text/html

호스트 내부 확인 결과를 정리하면 다음과 같습니다. 형식 예시(값은 환경마다 다름)

항목결과
포트 / 바인드TCP 8081 / 192.168.10.20
프로세스 / PIDpython3 / 2417
실행 파일/usr/bin/python3.9 (패키지 소속)
실행 인자python3 -m http.server 8081 --bind 192.168.10.20
실행 계정 / 작업 디렉터리일반 사용자 / ~/lab-web
서비스 유닛사용자 세션(scope) 소속, 상시 서비스 아님
판정사용자가 수동으로 띄운 임시 HTTP 파일 서버

점검 체크리스트

  • 알 수 없는 포트마다 PID·실행 파일·실행 계정을 확인했는가
  • 실행 파일이 패키지 소속인지, 패키지 외 파일이라면 경로가 적절한지 확인했는가
  • 서비스 유닛으로 관리되는 상시 서비스인지, 사용자가 임시로 띄운 것인지 구분했는가
  • 네트워크 응답(배너·HTTP·TLS)이 호스트 내부 확인 결과와 일치하는가
  • 실습용으로 띄운 서비스를 종료했는가

6. 패킷 / 로그 분석

6-1. 정상일 수 있는 경우 vs 의심해야 하는 경우

관찰 내용정상일 수 있는 경우의심해야 하는 경우
8080·8443 등 웹 대체 포트WAS, 관리 콘솔, 프록시등록되지 않은 서버에서 새로 열림
SSH가 2222 등에서 동작운영 정책에 따른 포트 변경기존 22와 별도로 추가 SSH 데몬이 존재
높은 번호 포트 LISTEN애플리케이션 고유 포트, RPC 동적 포트/tmp·/dev/shm·홈 디렉터리의 실행 파일이 LISTEN
실행 파일의 패키지 소속공식 패키지 또는 배포 절차로 설치된 파일패키지에 속하지 않고 이름이 시스템 프로세스를 흉내냄
포트와 프로토콜 불일치설정 변경 이력이 있는 서비스80 포트에서 HTTP가 아닌 프로토콜, IDS의 app_proto가 판정 실패

6-2. IDS·NSM 로그에서의 모습

Suricata eve.json flow 이벤트 일부 형식 예시(값은 환경마다 다름)

{"event_type":"flow","src_ip":"192.168.10.50","dest_ip":"192.168.10.20","dest_port":2222,"proto":"TCP","app_proto":"ssh"}

dest_port는 2222인데 app_proto가 ssh라면, 포트는 비표준이지만 프로토콜은 SSH라는 뜻입니다. 반대로 dest_port가 443인데 app_proto가 tls가 아니라면 다음 글(21편)에서 다룰 위장 통신을 의심할 근거가 됩니다.

6-3. 호스트에서 의심 위치 빠르게 보기

# LISTEN 중인 프로세스의 실행 파일 경로를 한 번에 확인
for pid in $(sudo ss -tulnpH | grep -oP 'pid=\K[0-9]+' | sort -u); do
  printf "%s\t%s\n" "$pid" "$(sudo readlink -f /proc/$pid/exe)"
done

실행 파일 경로가 /tmp, /var/tmp, /dev/shm에 있거나 (deleted)로 표시되면(실행 후 파일이 삭제됨) 우선 확인 대상입니다.


7. 보안관제 관점

  • 흔적 위치: 호스트 점검 결과(ss·EDR의 프로세스-네트워크 이벤트), IDS·NSM의 app_proto/service 판정, 방화벽의 허용 포트 목록과 실제 트래픽 비교.
  • 판정 문장 쓰는 법: "8081 포트 = HTTP-alt"가 아니라 "8081 포트에서 사용자 계정으로 실행된 python3 http.server가 HTTP로 응답"처럼 증거를 문장에 포함합니다.
  • 한계: 네트워크 배너는 서버 설정으로 바꾸거나 숨길 수 있어 단독 증거로는 약합니다. TLS로 감싸진 서비스는 인증서와 협상 정보 외에 내용을 알기 어렵습니다.
  • 오탐 주의: 개발 서버·테스트 서버는 비표준 포트가 자주 열리고 닫힙니다. 자산·변경 관리 기록과 먼저 대조합니다.
  • 비표준 포트 대상 스캔 탐지는 05. 네트워크 스캔 · 공격 징후 분석 시리즈, 포트-프로토콜 불일치 탐지 규칙은 06. 방화벽 · IDS/IPS 분석 시리즈에서 다룹니다.

8. 핵심 정리

  • 서비스 식별은 호스트 내부(소켓 → 프로세스 → 실행 파일 → 패키지 → 유닛) 확인이 가장 확실합니다.
  • 네트워크에서는 "누가 먼저 말하는가"와 첫 응답(SSH 배너, 220, HTTP/1.1, TLS 0x16)으로 프로토콜을 추정합니다.
  • IDS·NSM의 app_proto·service 필드는 포트와 무관하게 프로토콜을 판정하므로 포트-프로토콜 불일치 확인에 유용합니다.
  • 패키지에 속하지 않은 실행 파일, 임시 디렉터리의 실행 파일, 삭제된 실행 파일이 LISTEN하면 우선 확인합니다.
  • 판정 결과에는 포트 번호가 아니라 프로세스·실행 주체·근거를 적습니다.

다음 글: 21. 정상 포트로 위장한 통신 — 443을 쓰는 비정상 트래픽

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

0개의 댓글