📚 네트워크 · 패킷 분석 › 06. 방화벽 · IDS 기초 — 288편
이전 글: 287. Snort란 무엇인가 · 다음 글: 289. Suricata란 무엇인가
Snort Rule은 Snort 탐지 엔진이 읽는 규칙입니다. 헤더·옵션 구조와 sid·rev·classtype 같은 공통 요소는 282. Signature Rule에서 정리했으므로, 이 글은 Snort 2와 Snort 3에서 규칙이 어떻게 다르게 쓰이는가와 Snort에서 임계치·억제를 표현하는 방법에 집중합니다.
두 버전은 규칙의 큰 틀이 같지만, 운영 중 가장 자주 마주치는 차이는 다음과 같습니다.
| 항목 | Snort 2 | Snort 3 |
|---|---|---|
| content 수정자 | 별도 옵션: content:"abc"; nocase; depth:4; | content 안에 쉼표로: content:"abc",nocase,depth 4; |
| HTTP 필드 지정 | content 뒤 수정자: content:"/a"; http_uri; | 필드를 먼저 지정(sticky buffer): http_uri; content:"/a"; |
| 헤더 프로토콜 | ip, tcp, udp, icmp | 위 4개 + 서비스 이름(alert http 등) |
| 서비스 조건 | metadata:service http; | service:http; 옵션 |
| 규칙 임계치 옵션 | detection_filter, (구) threshold | detection_filter (Alert 수 제한은 설정의 event_filter) |
| 변환 도구 | — | snort2lua가 설정과 함께 규칙 문법 변환 지원 |
Snort 3는 Snort 2 규칙 상당수를 읽을 수 있지만, 수정자 표기 등 일부는 변환이 필요합니다. 운영 중인 버전의 매뉴얼로 확인합니다.
같은 탐지 목적의 규칙을 두 버전으로 쓰면 차이가 잘 보입니다. 아래 규칙은 외부에서 내부 웹 서버의 특정 관리 경로로 가는 요청을 탐지합니다(형식 예시, 값은 환경마다 다름).
# Snort 2
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"LOCAL external request to admin console"; flow:to_server,established; content:"/manage/console"; http_uri; nocase; metadata:service http; classtype:web-application-activity; sid:1001201; rev:1;)
# Snort 3
alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"LOCAL external request to admin console"; flow:to_server,established; http_uri; content:"/manage/console",nocase; classtype:web-application-activity; sid:1001201; rev:1;)
엔진이 규칙을 평가하는 흐름입니다.
헤더 일치 (Snort 2: tcp + HTTP 포트 / Snort 3: http 서비스로 식별된 흐름)
↓
flow: 연결 성립 후 클라이언트→서버 방향인가
↓
버퍼 선택: 정규화된 URI (Snort 2는 수정자, Snort 3는 sticky buffer)
↓
content 비교: "/manage/console", 대소문자 무시
↓
Alert: [1:1001201:1] + msg + classtype 우선순위
Snort 3의 서비스 규칙(alert http)은 포트가 아니라 식별된 서비스로 일치하므로, 비표준 포트에서 동작하는 웹 서비스도 검사할 수 있습니다.
반복 행위 탐지와 Alert 양 조절에 쓰는 Snort의 기능입니다.
| 기능 | 위치 | 의미 |
|---|---|---|
detection_filter | 규칙 옵션 (Snort 2·3) | 지정 시간 안에 규칙 일치가 N회를 넘은 뒤부터 Alert |
threshold 규칙 옵션 | Snort 2 규칙 옵션 | limit·threshold·both 방식으로 Alert 수 조절, Snort 2.8.5 이후 event_filter 사용 권장 |
event_filter | 설정 (snort.conf / snort.lua) | 규칙 수정 없이 특정 gid·sid의 Alert 수 조절 |
suppress | 설정 | 특정 gid·sid를 특정 IP에 대해 Alert하지 않음 |
detection_filter는 탐지 조건의 일부(N회 넘어야 탐지)이고, event_filter는 탐지 후 기록량 조절이라는 점이 다릅니다. 반복 로그인 시도 탐지처럼 "횟수 자체가 의심 근거"인 경우에는 detection_filter를 씁니다.
임계치와 억제 설정의 형식 예시입니다(값은 환경마다 다름, sid는 로컬 범위).
# 형식 예시 — 규칙 옵션: 같은 출발지에서 60초 안에 SSH 새 연결 시도가 10회를 넘으면 Alert (Snort 2·3 공통 표기)
alert tcp $EXTERNAL_NET any -> $HOME_NET 22 (msg:"LOCAL SSH connection attempts threshold exceeded"; flow:to_server; flags:S; detection_filter:track by_src, count 10, seconds 60; classtype:attempted-recon; sid:1001202; rev:1;)
# 형식 예시 — Snort 2 snort.conf (또는 threshold.conf)
event_filter gen_id 1, sig_id 1001201, type limit, track by_src, count 1, seconds 300
suppress gen_id 1, sig_id 1001202, track by_src, ip 192.168.10.5
-- 형식 예시 — Snort 3 snort.lua
event_filter = { { gid = 1, sid = 1001201, type = 'limit', track = 'by_src', count = 1, seconds = 300 } }
suppress = { { gid = 1, sid = 1001202, track = 'by_src', ip = '192.168.10.5' } }
분석 방법 — 첫 규칙의 Alert는 "SSH 연결 시도가 60초에 10회를 넘었다"는 뜻입니다. 로그인 실패 여부는 암호화 때문에 네트워크에서는 알 수 없으므로 서버 인증 로그로 확인해야 합니다. event_filter의 type limit, count 1, seconds 300은 같은 출발지에 대해 5분에 1건만 기록하라는 뜻이므로, Alert 건수가 실제 시도 횟수가 아님을 알고 해석합니다.
$HTTP_PORTS 같은 포트 변수에 없는 포트의 웹 서비스는 Snort 2 규칙에서 검사되지 않습니다. Snort 3 서비스 규칙이 이 공백을 줄여 줍니다.관제자가 Snort 규칙을 읽을 때 질문
detection_filter가 있다면 몇 초에 몇 회 조건인가? Alert 1건이 실제 몇 번의 행위를 뜻하는가?Snort Alert의 sid
↓ 규칙 원문: 버전 문법 확인 → 버퍼·content·flow 해석
↓ detection_filter 조건 → 행위 횟수 기준 이해
↓ event_filter·suppress 설정 확인 → 기록량·억제 범위 이해
Alert 건수 = 실제 행위 수? → 원본 로그·흐름 기록으로 보정
오탐 주의: 모니터링 도구의 주기적 SSH 헬스체크, 배포 도구의 대량 연결은 연결 횟수 규칙과 쉽게 일치합니다. 반복 로그인 탐지 기준은 292. Brute Force 탐지에서 다룹니다.
alert http 같은 서비스 규칙으로 포트와 무관하게 서비스를 검사할 수 있습니다.detection_filter는 횟수를 탐지 조건으로 쓰고, event_filter는 탐지 후 기록량을 조절합니다.