📚 네트워크 · 패킷 분석 › 06. 방화벽 · IDS 기초 — 282편
이전 글: 281. Anomaly Detection · 다음 글: 283. IDS Alert
Signature Rule(시그니처 규칙) 은 시그니처 탐지에서 "어떤 트래픽이면 어떤 Alert를 만들지"를 한 줄로 적은 명세입니다. Snort가 만든 규칙 문법이 사실상 표준이 되어 Suricata도 대부분 같은 형식을 씁니다. 규칙 파일 위치, 로컬 규칙 추가, sid 범위 관리는 04 영역 192. IDS Rule에서 다뤘습니다.
이 글은 규칙 한 줄을 읽고 해석하는 법, 즉 규칙의 해부(anatomy)를 다룹니다. 관제자가 Alert를 판단하려면 먼저 그 Alert를 만든 규칙이 무엇을 보려 했는지 알아야 합니다.
alert tcp $EXTERNAL_NET any -> $HOME_NET 22 (msg:"LOCAL SSH banner from external"; flow:established,to_server; content:"SSH-"; depth:4; classtype:misc-activity; sid:1000501; rev:1;)
└조치┘└프로토콜┘└─출발지─┘└포트┘└방향┘└─목적지─┘└포트┘ └──────────────────── 옵션(괄호 안, 세미콜론 구분) ────────────────────┘
괄호 앞이 헤더(Header), 괄호 안이 옵션(Options) 입니다. 헤더는 "어떤 연결을 볼지", 옵션은 "그 안에서 무엇을 찾고, 찾으면 어떻게 표시할지"를 정합니다.
규칙은 다음 순서로 읽으면 의도가 빨리 파악됩니다.
[1] 조치(action) → 탐지만(alert)인가, 차단(drop)인가
↓
[2] 헤더 → 누가(출발지) 누구에게(목적지), 어떤 프로토콜·포트, 어느 방향
↓
[3] msg → 규칙 작성자가 붙인 이름 (Alert 제목)
↓
[4] flow → 연결 상태와 방향 (요청인가 응답인가)
↓
[5] 탐지 조건 → content·pcre·크기·플래그 등 실제 비교 조건
↓
[6] 식별·분류 정보 → sid, rev, classtype, reference, metadata
헤더의 구성 요소입니다.
| 요소 | 예 | 의미 |
|---|---|---|
| 조치 | alert, drop, pass | 일치 시 동작 (엔진별 목록은 276. IPS란 무엇인가 참고) |
| 프로토콜 | tcp, udp, icmp, ip, http 등 | 검사 대상 프로토콜. 응용 계층 이름은 Suricata와 Snort 3에서 지원 |
| 주소 | $HOME_NET, 192.168.10.0/24, !10.0.0.5, any | 변수·CIDR·부정·목록 사용 가능 |
| 포트 | 22, [80,443], 1024:, any | 범위는 콜론, 목록은 대괄호 |
| 방향 | ->, <> | 단방향 / 양방향 |
자주 보는 옵션을 역할별로 나누면 다음과 같습니다.
| 옵션 | 역할 | 해석 포인트 |
|---|---|---|
msg | Alert 제목 | 작성자의 의도 요약, 판단 근거로는 부족 |
flow | 연결 상태·방향 | established,to_server면 연결 성립 후 요청 방향 |
content | 문자열·바이트 비교 | 따옴표 안 값, 바이트는 파이프 기호로 감싼 16진수 표기 |
nocase, depth, offset, distance, within | content 위치·대소문자 조건 | 위치를 제한할수록 정확 |
pcre | 정규표현식 | 유연하지만 성능 부담 |
sid, rev | 규칙 번호와 개정 번호 | 로컬 규칙은 관례상 1000000 이상 |
gid | 생성기 ID | 텍스트 규칙은 보통 1, 전처리기·inspector 이벤트는 다른 값 |
classtype | 분류 | classification 설정을 거쳐 Alert의 분류·기본 우선순위가 됨 |
priority | 우선순위 직접 지정 | classtype의 기본값을 덮어씀 |
reference | 참고 자료 | CVE, URL 등 탐지 근거 |
metadata | 부가 정보 | 작성일, 영향 제품, 배포 정책 등 |
content 뒤에 붙는 수정자(http_uri) 방식, Suricata 5 이후와 Snort 3는 필드를 먼저 지정하는 sticky buffer(http.uri / http_uri) 방식을 씁니다. 세부는 288. Snort Rule 기초, 290. Suricata Rule 기초에서 다룹니다.로컬 규칙 한 줄을 요소별로 해석한 형식 예시입니다(Suricata·Snort 2 공통으로 동작하도록 단순화, 값은 환경마다 다름).
# 형식 예시
alert tcp $HOME_NET any -> $EXTERNAL_NET 21 (msg:"LOCAL FTP login from internal host to external"; flow:established,to_server; content:"USER "; depth:5; nocase; classtype:policy-violation; reference:url,example.com/policy/ftp; sid:1000502; rev:2; metadata:created_at 2026_09_30;)
| 부분 | 해석 |
|---|---|
alert tcp $HOME_NET any -> $EXTERNAL_NET 21 | 내부에서 외부 21번 포트로 가는 TCP만 검사, 탐지만 함 |
flow:established,to_server | 연결이 성립된 뒤 클라이언트→서버 방향 데이터만 |
content:"USER "; depth:5; nocase; | 데이터 앞 5바이트 안에 대소문자 무관 "USER " |
classtype:policy-violation | 공격이 아닌 정책 위반 분류 |
sid:1000502; rev:2; | 로컬 규칙 1000502의 두 번째 개정판 |
분석 방법 — 이 규칙의 Alert는 "외부 FTP 서버에 로그인 명령을 보냈다"는 정책 위반 신호이지, 공격을 받았다는 뜻이 아닙니다. classtype과 방향을 읽지 않고 msg만 보면 의미를 잘못 판단할 수 있습니다.
$HOME_NET, $EXTERNAL_NET 같은 변수 값이 잘못되면 규칙 전체가 의도와 다르게 동작합니다. 방향 조건이 있는 규칙은 특히 영향을 받습니다.any any <> any any처럼 헤더가 넓고 content 하나뿐인 규칙은 오탐과 성능 부담을 동시에 만듭니다.pass 규칙은 이후 검사를 건너뛰므로 넓게 쓰면 탐지 공백이 생깁니다.관제자가 Alert의 규칙을 확인할 때 질문
flow 조건상 요청에서 일치했는가, 응답에서 일치했는가?Alert의 sid:rev 확인
↓ 규칙 원문 조회 (규칙 파일 / SIEM 규칙 정보)
↓ 조치·헤더 → 방향과 범위 파악
↓ flow·content → 무엇을 어디서 찾았는지 파악
↓ classtype·reference → 위협 성격과 근거 파악
Alert 해석 시작 (IDS Alert 분석 절차)
오탐 주의: msg는 사람이 붙인 이름일 뿐입니다. 판단은 반드시 규칙 원문의 조건을 기준으로 합니다. 규칙과 Alert를 연결해 읽는 방법은 283. IDS Alert에서 이어집니다.