정보보안핵심 · 19분 읽기

Suricata와 EVE JSON 이벤트

Suricata의 경보·흐름·프로토콜 기록을 함께 보면 탐지의 앞뒤 상황을 이해할 수 있다. EVE JSON은 중앙 분석으로 넘기는 공통 출발점이다.

개념부터 찾아보기

정의·역할·동작 원리를 독립 페이지에서 확인하세요. 본문의 밑줄 용어에도 설명이 있습니다.

이 노트에서 설명할 수 있게 되는 것

  1. EVE 이벤트의 공통 필드와 유형별 필드를 구분한다.
  2. flow_id·tx_id·센서 식별자의 범위 안에서 이벤트를 연결한다.
  3. 경보와 흐름·프로토콜 증거의 관계 및 지연을 설명한다.

01개념과 구성 요소

  • 는 패킷 탐지·차단과 flow·HTTP·· 같은 메타데이터 기록을 수행한다.
  • 캡처 기능··worker·상태 한도·룰·출력 유형의 구성이 처리 결과를 정한다.
  • 공통 필드와 event_type별 필드를 가진 JSON 이벤트로 탐지·거래·흐름을 연결한다.

02수신 패킷이 EVE 이벤트로 바뀌는 순서

  1. NIC와 지원 캡처 기능이 패킷을 사용자 공간 엔진으로 전달한다. Ring·큐·CPU 병목은 이 단계에서 손실을 만들 수 있다.
  2. 헤더와 캡슐화를 읽고 필요한 IP 단편을 재조립한다. IP fragment 처리와 stream 처리는 다르다.
  3. 양방향 흐름과 상태·순서·재전송을 관리해 응용 파서에 필요한 바이트를 구성한다.
  4. HTTP method·URI·status 같은 의미 있는 필드와 검사 버퍼를 만든다.
  5. Prefilter와 규칙 평가가 조건을 검사한다. ·depth·누락 패킷은 검사 가능한 범위를 제한한다.
  6. 활성화한 유형에 따라 alert·http·flow 등을 기록한다. 와 필요한 로 같은 통신의 다른 관찰을 연결한다.

03Suricata의 기능과 실행 조건

  • 수업 원문은 7.0.11을 쪽 환경과 맞추어 설치하고 과 로그를 비교한 자료다. 캡처·재조립·탐지·로그는 서로 다른 처리 단계다.
  • 는 / 엔진이면서 HTTP···flow 메타데이터를 남길 수 있다. EVE에 모든 종류가 항상 기록되는 것은 아니며 켠 출력 유형과 파서가 실제 관찰한 내용에 따라 달라진다.
  • 는 단일 스레드 제품으로 일반화할 수 없다. 제품 세대·입력 방식·구성에 따라 처리 구조를 비교해야 한다.

04빌드 기능이 사용 가능한 캡처 경로를 결정한다

  • 소스 빌드에서 configure는 설치 prefix와 라이브러리를 조사하고 make는 컴파일·링크, install은 산출물과 설정을 배치한다. Rust/C 도구 체인, libpcap, YAML·JSON· 라이브러리는 각각 파서·캡처·설정·출력·탐지 기능과 관련된다.
  • 패키지가 설치되어 있어도 실행 중인 바이너리가 해당 기능을 포함해 빌드되었는지는 별도 문제다.
  • 수업 환경의 --build-info에서는 AF_PACKET은 yes, NFQueue·DPDK·Netmap 등은 no로 표시되었다. 이것은 그 실습 바이너리의 능력이며 제품 전체가 그 기능을 지원하지 않는다는 뜻이 아니다.
  • YAML에 캡처 옵션을 적는 것만으로 빌드에서 빠진 기능이 생기지 않는다. 배포판 패키지와 수동 빌드가 함께 있으면 가 어떤 실행 파일을 호출하는지도 실행 결과를 바꾼다.
text
suricata --build-info
suricata --list-runmodes
suricata -T -c /etc/suricata/suricata.yaml
systemctl cat suricata

기능·실행 경로·설정 문법을 읽는 검사 예입니다. 패키지 설치나 방화벽 해제는 수행하지 않습니다.

05NIC RX Ring·DMA·RSS의 역할

  • NIC는 수신 프레임을 DMA로 메모리 버퍼에 놓고 descriptor로 그 위치와 상태를 관리한다. RX ring은 descriptor를 순환하며 재사용하는 구조이고 무한 대기열이 아니다.
  • 소비보다 유입이 빠르면 빈 버퍼 부족 등으로 패킷이 유실될 수 있다. Ring 1024·최대 4096이라는 값은 해당 NIC의 설정 예이며 모든 장치의 고정값이 아니다.
  • 는 패킷 흐름의 주소·포트 등에 대한 해시로 여러 수신 큐에 분산한다. 같은 flow를 일관된 처리 경로에 두는 것이 재조립 상태 관리에 유리하다.
  • 양방향 대칭 분산과 큐·스레드 배치는 NIC와 캡처 구성에 맞아야 한다. 버퍼를 늘리면 순간 폭주를 견딜 여유는 늘지만 지속적인 CPU 처리량 부족을 해결하지 못하며 지연이 늘 수 있다.
LEARN THROUGH PRACTICE

Suricata 실행 전에 NIC의 큐·링·드라이버 읽기

채널 수와 수신 링 용량을 구분하고 패킷 손실 진단의 기준선을 만든다.

실습 구성과 전제

  • 센서용 격리 의 데이터 NIC를 확인한다.
  • 조회 명령만 사용하며 운영 NIC의 채널 수·링 크기를 임의로 변경하지 않는다.
  1. 드라이버가 제공하는 기능을 확인한다

    • ethtool -i는 드라이버와 기능 정보를 보여 준다. 게스트에서 보이는 가상 NIC의 기능과 물리 호스트 NIC의 기능을 혼동하지 않는다.
    • 기능 지원은 실제 활성화 상태나 사용 상태와 별개다.
    shell
    ethtool -i ens160
    suricata --build-info

    NIC와 빌드 기능을 조회한다. 인터페이스 이름은 자신의 센서에 맞춘다.

    suricata · 실습·개념 참고 화면 2원본 크기로 보기 ↗
    • driver는 vmxnet3이며 version·bus-info가 표시된다.
    • supports-statistics는 yes지만 EEPROM 접근은 no다. 모든 ethtool 기능이 동일하게 지원되는 것은 아니다.
    확인 기준

    센서 인터페이스 이름과 드라이버를 운영 기록에 남긴다.

  2. 채널 수와 링 크기를 나누어 읽는다

    • ethtool -l의 Combined는 채널 수이며 ethtool -g의 RX는 링 파라미터다. 숫자 4와 1024를 같은 단위의 처리량으로 비교하지 않는다.
    • 여러 큐가 있어도 양방향 연결이 같은 처리 맥락에 배치되는지, 캡처 모드의 분배 방식이 맞는지를 확인해야 한다.
    shell
    ethtool -l ens160
    ethtool -g ens160
    ethtool -S ens160

    채널·링·통계를 각각 조회한다. 드라이버마다 통계 이름과 지원 항목이 다르다.

    suricata · 실습·개념 참고 화면 1원본 크기로 보기 ↗
    • Combined의 최대값과 현재값이 모두 4로 표시된다.
    • RX·TX가 n/a인 것은 분리 채널 항목이 지원되지 않는다는 표시이며 패킷을 수신하지 못한다는 뜻이 아니다.
    suricata · 실습·개념 참고 화면 3원본 크기로 보기 ↗
    • RX의 최대값은 4096, 현재값은 1024로 표시된다.
    • TX와 RX Jumbo도 별도의 현재값을 가진다. 최대 가능 값과 현재 설정을 구분해야 한다.
    확인 기준

    변경 전에는 인터페이스 통계·캡처 손실·CPU 병목을 먼저 기록한다.

  3. 손실 지점을 센서 파이프라인과 연결한다

    • NIC 드롭이 늘면 캡처 이전 손실을 의심하고, 캡처·해석 통계와 함께 비교한다. EVE 경보 수가 적다는 것만으로 트래픽이 적거나 안전하다고 판단하지 않는다.
    • ··AF_PACKET 등 실제 실행 조건을 적고 같은 부하에서 한 설정씩 비교한다.
    확인 기준

    한 가지 튜닝 값보다 입력 패킷·수신 손실·처리 지연의 전후 수치를 비교한다.

실습에서 확인한 동작 원리

  • 채널 수·링 용량·스레드 수는 다른 값이다.
  • 경보 품질을 보기 전에 캡처 가시성과 손실부터 확인한다.
동작·명령 참고 문서

06일반 소켓과 패킷 캡처 경로는 같지 않다

  • 일반 애플리케이션은 커널이 처리한 바이트 스트림을 소켓에서 읽는다. AF_PACKET 같은 캡처 경로는 링크 계층 패킷을 사용자 공간 엔진으로 넘겨 가 자체 flow·stream·응용 파싱을 수행하게 한다.
  • 패킷 캡처 경로를 일반 애플리케이션의 소켓 경로와 동일하게 해석해서는 안 된다.
  • NAPI는 인터럽트와 polling을 조합하는 커널 수신 처리와 관련되고, sk_buff는 커널의 패킷 표현이다. DPDK·AF_XDP·Netmap 등은 다른 입출력 경로와 전제 조건을 가진다.
  • 단순히 이름에 “고속”이 있다는 이유만으로 현재 에서 더 빠르다고 결론 내릴 수 없으며 장치·드라이버·메모리·코어 배치가 함께 작동해야 한다.

07Decode→Defrag→Flow→Stream

  • Decode는 //IP// 등의 헤더와 캡슐화를 해석한다. Defrag는 IP fragment를 묶는 단계이고 stream reassembly는 순서 번호에 따른 바이트를 묶는 단계다.
  • 둘은 계층과 상태가 다르다. 에서도 IP 단편화가 가능하므로 “는 fragment가 없다”로 외우면 안 된다.
  • Flow tracking은 대개 양방향 5튜플과 구성된 ·장치 구분을 이용해 상태를 유지한다. Stream tracking은 handshake·순서·재전송·종료를 관찰하고 재조립 버퍼를 만든다.
  • 문자열이 UNI / ON SEL / ECT 세 조각에 나뉘어 있으면 단일 payload 검색에는 없던 문자열이 재조립 후 나타날 수 있다. 누락·겹침·중간부터 시작한 캡처는 해석의 불확실성을 만든다.

08App-layer parser와 검사 버퍼

  • 응용 파서는 HTTP 요청·응답에서 method·URI·host·status 같은 의미 있는 필드를 만든다. 탐지 엔진은 raw packet, 재조립 stream, 응용 계층 버퍼 중 규칙이 지정한 곳을 평가한다.
  • URI에서 찾으려는 문자열을 전체 payload와 같은 것으로 다루면 정규화나 분할 조건에서 결과가 달라질 수 있다.
  • 여러 패턴을 빠르게 찾는 MPM·prefilter는 후보를 줄여 정밀 규칙 평가의 비용을 낮추는 구조다. Hyperscan 등 사용 가능 엔진은 빌드 조건에 영향을 받는다.
  • prefilter가 있다는 사실은 모든 규칙을 동일한 방식으로 평가한다는 뜻이 아니며, 규칙 추가 후 CPU·drop·검사 범위도 함께 달라질 수 있다.

09workers·autofp와 실제 스레드 상태

  • 는 각 패킷 처리 스레드가 전체 처리 파이프라인을 가지는 방식이고 는 수신·디코딩 뒤 flow worker로 전달하는 구조다. single은 하나의 패킷 처리 스레드로 수행하는 방식이다.
  • 캡처 방식에 따라 사용 가능한 와 적합성이 달라진다.
  • 실습의 ps -Lf 출력에는 하나의 PID 아래 여러 LWP와 NLWP=10이 표시되었다. PID가 같고 LWP가 다른 것은 동일 안의 여러 스레드라는 뜻이다.
  • ps -lf의 소문자 l은 긴 형식이고 스레드 표시의 대문자 L과 구분한다. 스레드 수 10과 vCPU 4만으로 10개가 동시에 계산 중이라고 말할 수는 없다.
  • 관리 스레드·대기 스레드와 실제 worker의 CPU 사용을 구분한다.

10HOME_NET·룰 파일·정책의 연결

  • HOME_NET은 보호 대상 주소 범위이며 캡처 위치에서 보이는 전후 주소와 일치해야 한다. af-packet 인터페이스는 실제 패킷이 들어오는 지점이고 default-rule-path와 rule-files는 읽을 규칙을 결정한다.
  • local.rules 파일을 만들었어도 로드 목록에 없으면 탐지는 일어나지 않는다. YAML 들여쓰기는 탭 대신 공백으로 구성한다.
  • host-os-policy는 겹친 데이터 등의 해석을 보호 대상에 맞추는 정책이다. 모든 주소를 무조건 로 바꾸는 것이 보편적인 정답은 아니다.
  • 설정 파일의 줄 번호는 버전마다 달라지므로 이름과 구조를 확인하지 않은 줄 단위 일괄 편집은 적절하지 않다.

11memcap·depth·checksum은 가시성 조건이다

  • defrag·flow·stream·reassembly의 은 각 상태 영역의 메모리 상한이다. timeout은 상태를 얼마나 유지할지, reassembly depth는 어느 범위까지 바이트를 재조립할지에 관여한다.
  • 상한 초과 때 동작은 기능·모드·정책별로 달라질 수 있다. depth 너머에서 재조립이 중단되면 해당 바이트가 필요한 탐지에 한계가 생긴다.
  • checksum validation은 잘못된 체크섬을 다루는 조건이다. 송신 호스트에서 캡처한 패킷은 NIC offload 전에 보이는 체크섬 때문에 실제 회선 패킷과 다르게 표시될 수 있다.
  • 이 경우 검증을 무조건 끄는 대신 캡처 위치와 offload 영향을 분리한다. stats 출력까지 모두 끄면 drop과 메모리 한도를 추적할 근거가 사라진다.

12EVE의 공통 필드와 유형별 필드

  • 은 timestamp·event_type··주소·포트 등의 공통 정보와 alert/http/flow 같은 유형별 내용을 한 줄 이벤트로 기록한다. alert.signature_id는 규칙, http.url은 요청 경로, http.status는 응답 상태를 설명한다.
  • 는 같은 엔진 흐름의 이벤트를 연결하지만 여러 센서에서 통용되는 전역 고유 ID로 간주하지 않는다. 한 연결의 여러 HTTP 거래는 등 거래 정보를 더해 구분한다.
  • 아래 세 줄은 실제 환경의 주소를 제거한 학습 예다. alert가 있었다는 사실과 HTTP 응답이 성공했는지, 센서가 차단했는지는 서로 다른 필드의 질문이다.
  • passive 에서 allowed는 업무적으로 안전하다는 판정이 아니다.
text
{"event_type":"alert","flow_id":42001,"tx_id":0,"alert":{"signature_id":1000001,"action":"allowed"}}
{"event_type":"http","flow_id":42001,"tx_id":0,"http":{"http_method":"GET","url":"/training","status":200}}
{"event_type":"flow","flow_id":42001,"flow":{"pkts_toserver":4,"pkts_toclient":3}}

jq 'select(.flow_id == 42001)' eve.json

원리를 설명하는 가상 학습 예시입니다.

원리 심화

13Flow·Transaction·Community ID의 결합 범위

  • 는 같은 흐름의 EVE 이벤트를 연결하는 핵심 필드다. 독립 센서·실행 시점까지 포함한 전역 영구 식별자로 가정하지 않는다.
  • 한 연결에 여러 HTTP 요청·응답이 존재할 수 있다. 같은 문맥을 더해야 어느 요청에서 탐지가 발생했는지 좁힐 수 있다.
  • 호환 도구가 흐름을 연결하도록 공통 방식으로 계산한 식별자다. 비교 도구들은 같은 seed 등 호환 조건을 사용해야 한다.
  • 앞뒤에서는 관찰 주소·포트가 달라져 같은 실제 통신의 가 달라질 수 있다. 변환 기록과 센서 위치가 필요하다.
  • 같은 주소·포트 조합은 나중에 재사용될 수 있다. 흐름 지문만으로 서로 다른 시간의 사건을 하나로 합치지 않는다.
예제로 추적

14가상 HTTP 연결의 두 요청과 경보 결합

  1. =420인 연결에 =0의 요청 A와 =1의 요청 B가 있다고 가정한다. 경보는 =1에서 발생했다.
  2. 만으로 경보를 요청 목록에 결합하면 A와 B 둘 다 후보가 된다. 연결이 같다는 사실만 얻은 것이다.
  3. 와 를 함께 비교하면 B로 좁힐 수 있다. 필드가 실제로 존재하고 같은 파서 문맥인지 확인한다.
  4. 요청·응답·경보 시각과 방향을 비교하여 재시작·ID 재사용·지연 도착을 구분한다.
  5. 가능하면 해당 패킷·재조립 자료로 돌아가 실제 검사 버퍼를 확인한다. EVE의 요약 필드만으로 모든 본문 바이트를 복원할 수는 없다.
검증·예외

15EVE는 있는데 HTTP·경보 필드가 빠질 때

  • 수신 드롭·디코더 오류·flow/stream 제한·app-layer 파싱 상태를 구분한다. 원인은 모두 같은 종류의 packet loss가 아니다.
  • EVE에서 활성화한 이벤트 유형과 출력 설정을 확인한다. 파싱은 수행됐지만 해당 유형을 기록하지 않을 수도 있다.
  • ··본문 검사 한도에 도달한 자료가 아닌지 통계와 설정을 대조한다. 규칙 불일치와 검사되지 않음을 분리한다.
  • 를 종료하지 않는 센서는 암호화된 HTTP 본문을 그대로 읽지 못한다. 메타데이터와 평문 HTTP 가시성을 같은 수준으로 해석하지 않는다.

16Snort 규칙 이식과 결과 비교

  • ·전체 ·80번 목적지 규칙을 두 엔진에 적용하면 fast/JSON 출력 경로를 비교할 수 있다. 이러한 규칙은 파이프라인이 입력을 받아 경보를 출력하는지 확인하는 넓은 시험 규칙이며 그 자체로 공격 탐지를 뜻하지 않는다.
  • HTTP 프로토콜 검사가 없는 any→80 규칙은 포트 조건만 만족한 패킷에도 반응할 수 있다.
  • 두 엔진이 공통 문법을 갖더라도 옵션·버퍼·버전 차이 때문에 모든 규칙이 그대로 호환되는 것은 아니다. 문법 검사와 같은 양성·음성 PCAP의 결과를 각각 비교해야 한다.
  • JSON 필드와 기본값은 버전·설정의 영향을 받으며 단일 실습을 제품 간 보편적인 우열로 확대하지 않는다.

17경보가 없을 때 처리 단계별로 원인을 찾는다

  • 경보가 없는 원인은 패킷 미도착, 캡처 손실, 잘못된 HOME_NET, 응용 파서 미연결, 재조립 한도, 규칙 미로드, 조건 불일치, 출력 미활성화 중 어느 곳에도 있을 수 있다. 한 번에 규칙을 바꾸기보다 패킷 입력 수→flow·protocol 식별→규칙 수→EVE 출력의 연결을 따라가면 실패 지점을 좁힐 수 있다.
  • 같은 의 alert·HTTP·flow를 연결하면 탐지와 응용 거래·전체 흐름을 함께 읽을 수 있다. 그것이 전 구간 무손실이나 모든 공격 탐지를 보증하지는 않는다.
  • 캡처 손실 지표, 로그 처리 지연, 정상 트래픽 오탐을 함께 해석해야 센서가 보고 있지 않은 영역도 설명할 수 있다.

설명과 함께 보는 보조 도식

처리 과정

모식도 · EVE 유형별 사건 연결

서로 다른 EVE 이벤트를 원본을 유지한 채 연결한다.

전체 단계를 한 번에 읽기
  1. 01

    출력

    설정된 유형별로 이벤트를 생성한다.

  2. 02

    흐름 요약

    흐름의 종료·만료 등 출력 조건을 고려한다.

    발생 순서
    경보와 같지 않을 수 있음
  3. 03

    연결

    flow_id와 필요한 경우 tx_id를 문맥 안에서 사용한다.

  4. 04

    확인

    원본과 PCAP로 실제 요청·응답 관계를 검증한다.

    주의
    경보 = 성공 확정 아님
구성요소와 데이터 이동을 단순화한 학습용 모식도입니다. 실제 제품의 모든 내부 모듈을 나타내지는 않습니다.
READ · OBSERVE · CONNECT

함께 보는 학습 자료

아래 공식 자료를 본문의 개념·예제와 함께 읽어 보세요. 자료별로 확인할 위치와 관찰할 내용을 적었습니다.

공식 가이드

Suricata 8: EVE 이벤트별 JSON 예제

alert·http·anomaly·flow 예제를 나란히 읽어 연결 전체와 개별 응용 을 구분한다.

읽으면서 확인할 것
  • event_type마다 다른 필드 구조
  • 와 존재하는 의 결합
  • alert.action과 흐름 종료·상태 정보의 차이
학습 확인

이해했는지 확인하기

  • event_type별 파서와 필수 필드를 확인한다.
  • flow_id를 센서·시간 범위와 함께 사용한다.
  • EVE 출력량·지연·패킷 드롭과 정상 트래픽의 결과를 확인한다.

함께 확인할 공식 자료