📚 네트워크 · 패킷 분석 › 02. 포트 · 프로토콜 분석 — 96편
이전 글: 95. Firewall Log의 Port · 다음 글: 97. Port 기반 공격
IDS Alert에도 방화벽 로그처럼 출발지·목적지 포트가 들어 있습니다. 차이는 IDS가 패킷 내용을 검사한 결과라는 점입니다. 그래서 Alert의 포트는 두 가지 역할을 합니다.
이 글은 Alert에서 포트를 찾고 방향을 바르게 읽는 법만 다룹니다. 룰 작성 문법과 Alert 분석 절차는 06. 방화벽 · IDS 기초 영역 288. Snort Rule 기초, 290. Suricata Rule 기초, 295. IDS Alert의 Source/Destination 분석에서 다룹니다.
| 위치 | 포트가 나타나는 모양 | 의미 |
|---|---|---|
| 룰 헤더 | $EXTERNAL_NET any -> $HOME_NET 22 | 검사 대상 조건 |
| 포트 변수 | $HTTP_PORTS, $SSH_PORTS 등 | 설정 파일에 정의한 포트 묶음 |
| fast.log | {TCP} 203.0.113.50:51544 -> 192.168.10.20:22 | Alert를 일으킨 패킷의 포트 |
| eve.json (Suricata) | src_port, dest_port, proto, app_proto | 위와 같음 + 식별된 응용 프로토콜 |
Alert 한 건이 만들어지는 과정에서 포트가 쓰이는 지점입니다.
패킷 수집 → 흐름(Flow) 추적: 5-tuple로 세션 묶음, 먼저 SYN을 보낸 쪽 = 클라이언트
↓
응용 프로토콜 식별: 포트 힌트 + 내용 패턴 → app_proto (http, tls, ssh, dns ...)
↓
룰 매칭:
헤더의 프로토콜·IP·포트 조건 (예: tcp ... -> $HOME_NET 22)
또는 응용 프로토콜 키워드 (예: alert http ... → 포트와 무관하게 HTTP면 검사)
+ flow 방향 조건 (to_server / to_client)
↓
Alert 기록: 트리거 패킷의 src_ip:src_port → dest_ip:dest_port
핵심은 Alert의 src/dest가 "공격자/피해자"가 아니라 "그 패킷의 출발지/목적지" 라는 점입니다. 서버 응답을 검사하는 룰(flow:to_client)이 걸리면 Alert의 출발지는 서버, 출발지 포트는 서비스 포트가 됩니다.
포트 값으로 Alert 방향을 읽는 기준입니다.
| Alert 모양 | 해석 | 예 |
|---|---|---|
| src_port 임시 포트 → dest_port 서비스 포트 | 클라이언트 → 서버 요청에서 탐지 | 웹 공격 시도, 스캔 |
| src_port 서비스 포트 → dest_port 임시 포트 | 서버 → 클라이언트 응답에서 탐지 | 서버가 오류·민감 정보를 응답, 악성 파일 다운로드 |
| src/dest 모두 서비스 포트 | DNS 서버 간, NTP 등 특수 동작 | 53 → 53 |
| 포트 없음 | ICMP 등 | proto: ICMP, icmp_type 필드 |
포트와 app_proto가 어긋날 때는 그 자체가 분석 단서입니다.
| dest_port | app_proto | 해석 |
|---|---|---|
| 80 | http | 일치, 일반적 |
| 8081 | http | 비표준 포트의 HTTP. 운영 서비스인지 확인(89. 비표준 포트에서 동작하는 서비스 식별) |
| 443 | (없음) 또는 failed | 443인데 TLS로 식별되지 않음 → 포트-프로토콜 불일치 |
| 53 | tls·http | DNS 포트로 다른 프로토콜 → 터널링·우회 의심 |
| 2222 | ssh | SSH를 다른 포트로 운영하는 설정인지 확인 |
포트 변수는 설정 파일(Suricata suricata.yaml의 vars: port-groups, Snort 2 snort.conf의 portvar, Snort 3는 Lua 설정 파일의 변수)에 정의됩니다. 예를 들어 웹 서버가 8080에서 동작하는데 HTTP_PORTS에 8080이 없으면, 포트 조건으로 작성된 룰은 그 트래픽을 검사하지 않아 미탐(False Negative) 이 생깁니다(06 영역 286. False Negative).
실습 예시 — 본인 실습망의 Suricata 센서에서 Alert의 포트 필드만 뽑아 봅니다(jq 필요, Rocky: sudo dnf install -y jq / Ubuntu: sudo apt install -y jq). 로그 경로는 패키지 기본값 기준 예시입니다.
# 포트 변수 정의 확인
grep -A 12 'port-groups:' /etc/suricata/suricata.yaml
# Alert의 5-tuple과 app_proto
jq -c 'select(.event_type=="alert")
| {src_ip, src_port, dest_ip, dest_port, proto, app_proto,
sig: .alert.signature, sid: .alert.signature_id}' \
/var/log/suricata/eve.json | tail -5
# 목적지 포트별 Alert 건수
jq -r 'select(.event_type=="alert") | "\(.proto) \(.dest_port)"' \
/var/log/suricata/eve.json | sort | uniq -c | sort -rn | head
eve.json Alert 형식 예시(값은 환경마다 다름, 필드 일부 생략, 로컬 테스트 룰 기준):
{"timestamp":"2026-09-30T10:20:11.123456+0900","flow_id":1234567890123456,
"event_type":"alert","src_ip":"203.0.113.50","src_port":51544,
"dest_ip":"192.168.10.20","dest_port":8080,"proto":"TCP","app_proto":"http",
"alert":{"action":"allowed","signature_id":1000001,"rev":1,
"signature":"LOCAL TEST admin path request","severity":2}}
fast.log 형식 예시(값은 환경마다 다름):
09/30/2026-10:20:11.123456 [**] [1:1000001:1] LOCAL TEST admin path request [**] [Classification: (예시)] [Priority: 2] {TCP} 203.0.113.50:51544 -> 192.168.10.20:8080
| 필드 | 해석 |
|---|---|
src_port 51544 | 임시 포트 → 요청 방향 패킷에서 탐지 |
dest_port 8080 + app_proto http | 비표준 포트의 HTTP. 포트 변수에 8080이 포함되어 있는지 확인 |
flow_id | 같은 세션의 flow·http 이벤트와 연결하는 키 |
action allowed | IDS 모드라 차단하지 않음(IPS 모드면 blocked 가능) |
alert http, alert tls 등)과 프로토콜 식별 결과를 함께 쓰는 이유입니다.| 흔적 위치 | 포트 관련 확인 내용 |
|---|---|
| IDS Alert (fast.log, eve.json) | 트리거 패킷의 5-tuple, app_proto |
| IDS flow·프로토콜 이벤트 | 같은 flow_id의 세션 바이트, HTTP·TLS·DNS 상세 |
| 방화벽 로그 | 같은 5-tuple의 허용·차단 여부(95. Firewall Log의 Port) |
| 서버 로그 | 목적지 포트의 서비스가 요청을 받았는지 |
관제자가 확인할 질문
오탐 주의: 존재하지 않는 서비스 포트를 향한 공격 시도 Alert는 대개 자동화된 무차별 시도이며, 영향 가능성은 낮습니다. 반대로 서비스 포트에서 출발한 응답 방향 Alert는 서버가 실제로 반응했다는 뜻이라 우선순위가 높습니다. Alert와 패킷 연계는 06 영역 297. IDS Alert와 Packet 연계에서 다룹니다.