개요 — 무엇을 하나
Security ▸ Threats(/security/threats)는 Suricata IDS 경보 테이블 suricata_alert_ct 를 출발지 IP(src_ip) 엔티티 관점으로 재구성해 트리아지하는 화면입니다. 수천 건의 개별 경보를 그대로 나열하는 대신, "누가(어느 IP가) 우리를 얼마나·어떻게 건드렸는가"로 묶어 심각도 순으로 보여 줍니다.
세 가지를 한 화면에서 연결합니다.
- 위협 엔티티 트리아지 — src_ip 를 경보 수·최고 심각도·distinct 시그니처 수·최종 관측 시각으로 요약한 카드.
- 자동조치(차단) 연결 — 각 위협 IP의 /24 대역이 자동방어 테이블
blacklist_info에 이미 올라가 있는지 매칭해 차단됨/탐지됨 배지를 붙입니다. 탐지와 대응을 한눈에 잇습니다. - 시그니처 해설(Signature Lore) — Suricata 시그니처 문자열 대부분은 사람이 읽기 어려운 엔진 이벤트(stream / decoder / app-layer 이벤트)입니다. 이 화면은 각 시그니처가 실제로 무엇을 암시하는지(무엇을 탐지 · 왜 검출됐나[양성→악성] · 조심할 상황 · 최악의 시나리오)를 해설 패널로 풀어 줍니다.
전부 읽기 전용입니다. 상태를 바꾸는 유일한 행동은 위협 IP를 블록리스트로 보내는 딥링크뿐이며, 실제 차단 쓰기는 그 화면에서 별도 권한으로 수행됩니다.
언제 쓰나
- 아침 점검: 지난 24시간 우리를 가장 많이 건드린 IP와 그 심각도를 훑을 때.
- 특정 IP가 진짜 위협인지 노이즈인지 판정할 때 — 시그니처 해설의 [양성/주의/악성] 톤과 자동차단 여부로 빠르게 분류.
- "이 시그니처가 도대체 무슨 뜻이지?"를 팀원에게 설명해야 할 때 — 해설 패널이 그대로 교재가 됩니다.
- 위협 IP를 조사한 뒤 차단 후보로 올릴 때(→ 블록리스트 딥링크, → IP 평판 팝업).
화면 구성
상단 KPI (창 기준 집계)
| KPI | 의미 | 산출 |
|---|---|---|
| alerts | 창 내 총 IDS 경보 수 | suricata_alert_ct where alert_ts >= since count |
| entities | 위협 IP 엔티티 수 | 상위 src_ip(최대 48개) |
| blocked | 이미 자동차단된 위협 IP 수 | 엔티티 /24 ∈ blacklist_info(is_use=1) |
| critical | 미차단 치명 위협 IP 수(관측 전체는 critical_all) |
max_sev <= 1 이고 아직 차단되지 않은 엔티티 |
위협 엔티티 카드/행
상위 src_ip 를 경보 수 내림차순으로 최대 48개 표시합니다. 각 엔티티가 담는 값:
| 필드 | 설명 |
|---|---|
ip |
출발지 IP(src_ip) |
alerts |
창 내 이 IP의 경보 수 |
sev |
최고 심각도(1=치명 … 3=정보). Suricata는 낮을수록 심각 → MIN(severity) 가 최고치 |
sigs |
distinct 시그니처(sid) 수 — 공격 다양성 |
last_ts |
최종 관측 시각 |
blocked |
이 IP의 /24가 자동차단 목록에 있으면 true |
block_source |
차단 근거 소스태그: kitsune · suricata · manual · other (reason 문자열 파싱) |
country / asn |
지오/ASN 인리치(ip_info_loop 최신 1건) |
자기망은 제외됩니다.
SecurityScope::excludePrefixes()가 등록된 인스턴스 IP의 /24 대역(+ 운영 정책의 내부망 화이트리스트)을NOT LIKE로 걸러, 우리 서버가 출발지로 잡힌 잡음을 위협 목록에서 뺍니다. 그럼에도 내부 IP가 방향 라벨 탓에 보이면 운영 정책의internalMatchers기반내부배지가 붙고 평판 조회 버튼이 숨겨집니다.
severity 분포 · categories · signatures
- severity 분포:
{1: n, 2: n, 3: n}— 치명/경고/정보 경보 수. - categories: 상위 10개 category(카운트 desc) + 각 최소 심각도.
- signatures: 상위 12개 시그니처(카운트 desc). 각 항목은
signature·sid·cnt·sev(min) +explain(SignatureLore 분류 결과)을 포함합니다. 시그니처를 클릭하면 sibling 해설 패널이 열립니다.
시그니처 해설 패널 (Signature Lore)
시그니처 문자열을 App\Support\SignatureLore::classify() 가 유형(family) 과 세부 키(key) 로 분류하고, 실제 해설 텍스트는 resources/lang/{ko,en}/siglore.php 언어 팩이 소유합니다. 프런트가 family + key 를 병합해(세부가 유형을 오버라이드) 4단 서사로 렌더합니다.
| 구성 | 내용 |
|---|---|
| 무엇을 탐지했나 (meaning) | 이 시그니처가 규약상 무엇을 잡았는지 |
| 왜 검출되었나 · 가능성 (why) | 원인 후보를 [양성] → [주의] → [악성] 톤 순으로 나열 |
| 조심해야 할 상황 (caution) | 노이즈와 진짜 신호를 가르는 기준 |
| 최악의 시나리오 (worst) | 방치 시 이어질 수 있는 침해 |
각 유형은 암시 심각도(tone) 를 가집니다 — 정보성 이벤트라도 함의는 다릅니다.
| family | 라벨 | tone | 아이콘 |
|---|---|---|---|
stream |
TCP 스트림 재조립 이상 | warn | mdi-transit-connection-variant |
decoder |
패킷 디코드/무결성 이상 | info | mdi-package-variant-closed |
applayer |
애플리케이션 프로토콜 이상 | warn | mdi-swap-horizontal-bold |
http |
HTTP 파싱 이상 | warn | mdi-web |
tls |
TLS 이상 | warn | mdi-lock-outline |
dns |
DNS 이상 | warn | mdi-dns-outline |
scan |
스캔/정찰 | warn | mdi-radar |
exploit |
익스플로잇 시도 | crit | mdi-bug-outline |
malware |
악성코드/C2 | crit | mdi-virus-outline |
dos |
DoS/플러딩 | crit | mdi-flash-alert-outline |
policy |
정책/정보 | info | mdi-file-document-outline |
generic |
기타 IDS 시그니처 | info | mdi-shield-alert-outline |
세부 키 오버라이드는 14종입니다: invalid_timestamp · checksum · retransmit · handshake · evasion · stateanomaly · host_header · desync · malformed · one_direction · mismatch · starttls · tls_anomaly · unsolicited.
대부분의 stream/decoder 시그니처(예:
SURICATA STREAM Packet with invalid timestamp,SURICATA TCPv4 invalid checksum)는 sev3 정보성이며 비대칭 라우팅·NIC 체크섬 오프로딩 같은 인프라 특성에서 대량 발생하는 양성 노이즈입니다. 시그니처 자체보다 같은 src_ip 가 짧은 시간에 여러 유형(스캔+핸드셰이크 이상 등)을 겹쳐 만드는지를 보세요. 그것이 의도성의 신호입니다.
사용법
1) 조회 범위 선택
기본 창은 24h입니다. 지원 범위와 매핑:
| range | 창(분) |
|---|---|
1h |
60 |
6h |
360 |
24h |
1440 (기본) |
범위 토글은 ?range= 로 전달되며 화이트리스트에 없는 값은 24h 로 강등됩니다.
2) 위협 IP 트리아지
- 심각도(
sev=1치명)와 경보 수가 높은 엔티티부터 확인합니다. - 차단됨 배지가 있으면 이미 자동방어가 대응한 것 —
block_source로 어느 엔진이 막았는지 확인. - 차단 안 됨 + 높은 심각도 + 다수 시그니처면 조사·차단 최우선 후보입니다.
3) IP 드릴다운(보안 특화 팝오버)
IP를 클릭하면 GET /security/threats/ip-detail?ip=<IP>&range=<range> 를 호출합니다. IP는 FILTER_VALIDATE_IP 로 엄격 검증하며, 실패 시 422(invalid_ip)를 반환합니다. 반환 필드:
{
"ok": true,
"detail": {
"ip": "203.0.113.10",
"cidr": "203.0.113.0/24",
"geo": { "country": "US", "city": null, "asn": "ASNNNNN", "isp": "...", "org": "..." },
"signatures": [
{ "signature": "...", "severity": 3, "cnt": 42, "explain": { "family": "stream", "key": "invalid_timestamp", "tone": "warn", "icon": "mdi-...", "svg": "stream" } }
],
"blocked": true,
"block_source": "suricata",
"block_reason": "[Suricata Auto-Block] ...",
"block_at": "2026-08-13 04:12:00",
"abuse_url": "https://www.abuseipdb.com/check/203.0.113.10"
}
}
- geo/ASN:
ip_info_loop인리치. - signatures: 이 IP의 상위 8개 시그니처(카운트 desc) + 각
explain해설. - 차단 상태:
blacklist_info의 /24 매칭(c_class,is_use=1) → 소스태그·원본 reason·차단 시각.
4) 평판 조회 · 차단으로 승격
- IP 옆 심볼(
.infr-ipsym) 클릭 → IP 평판 AbuseIPDB 인앱 팝업(mixins/abuse_check.js+/security/ip-reputation). 악용 신뢰도·신고 수·국가·용도·최근 신고 내역을 조회합니다. - 조사 후 차단 결정 → 블록리스트로
?add=<IP>딥링크(/24 정규화 후 등록, 별도 권한·감사).
데이터 소스
| 테이블 | 용도 | 접근 |
|---|---|---|
suricata_alert_ct |
IDS 경보(src_ip·severity·category·signature·sid·alert_ts) | 읽기 |
blacklist_info |
자동차단 목록(/24 c_class·reason·country·is_use) |
읽기(자동조치 배지) |
ip_info_loop |
지오/ASN/ISP 인리치 | 읽기 |
| 등록 인스턴스 IP + 운영 정책 내부망 | 자기망 제외 · 내부 배지 | SecurityScope |
모든 원천은
legacy_glory커넥션(수집기 함대가 채우는 무접두 레거시 테이블)이며 읽기 전용입니다. 읽기 백본은App\Repositories\SecurityRepository(파라미터 바인딩·좁은 창·LIMIT). 컨트롤러/서비스는 이 테이블을 생성·변경하지 않습니다.
캐시 · 갱신
ThreatService::build()결과는 range별로 30초 캐시(키infr:sec:th:<range>)됩니다.- 화면은 30초 폴링(
/security/threats/live)으로 갱신합니다(Reverb 아님). MIN(severity)로 최고 심각도를 잡으므로,sev값이 낮을수록 위험합니다(1=치명, 3=정보).
권한
| 작업 | 등급 |
|---|---|
| 화면·드릴다운·평판 조회 | ≥ 2 (스탭=5, 관리자=10) |
| 데모(1) 접근 | 불가 |
/security/*전체가infr.level:2미들웨어로 보호됩니다. 데모(1)는 보안 정보 조회가 제한됩니다(등급 재편).- Threats 자체는 모두 GET(읽기 전용) 이라 쓰기 감사 대상이 아닙니다. 차단 쓰기·평판 신고 같은 파괴적/외부 행동은 각각 블록리스트·[국제공조]에서 별도 권한과 감사로 수행됩니다.
문제해결 · FAQ
Q. invalid timestamp·invalid checksum 이 압도적으로 많은데 공격인가요?
대개 아닙니다. invalid checksum 은 자기 서버 트래픽에서 NIC 체크섬 오프로딩 때문에, invalid timestamp 는 비대칭 라우팅·중간장비 때문에 대량 발생하는 sev3 양성 노이즈입니다. 시그니처 해설의 [양성] 항목이 이를 설명합니다. 특정 외부 src_ip 에 편중되고 다른 신호(스캔·핸드셰이크 이상)와 겹칠 때만 의심하세요.
Q. severity가 왜 숫자 1이 가장 심각한가요?
Suricata 규약에서 severity 1=high, 2=medium, 3=informational 입니다. 따라서 엔티티의 최고 위험도는 MIN(severity) 로 계산합니다.
Q. 우리 서버 IP가 위협 목록에 보입니다.
SecurityScope 가 등록 인스턴스 /24 와 내부망 화이트리스트를 제외하지만, 미등록 IP거나 방향 라벨(src/dst) 때문에 보일 수 있습니다. 인스턴스에 IP를 등록하거나 운영 정책 내부망 대역을 추가하세요. 그래도 보이면 내부 배지가 붙습니다.
Q. IP 드릴다운이 422를 반환합니다.
ip 파라미터가 유효한 IP가 아닙니다(invalid_ip). 값이 실제 IPv4/IPv6인지 확인하세요.
Q. 시그니처 해설이 "기타 IDS 시그니처"로만 나옵니다.
SignatureLore::match() 키워드 규칙에 걸리지 않은 시그니처는 generic 유형으로 폴백합니다. category 와 시그니처 이름으로 판단하고, 필요하면 siglore.php 에 세부 키를 추가할 수 있습니다.
Q. 목록이 30초 동안 그대로입니다. 정상입니다. 서비스가 range별 30초 캐시 + 30초 폴링으로 동작합니다. 즉시 최신값이 필요하면 새로고침하세요(캐시 만료 후 재계산).
관련 항목
- Security Overview — 위협→탐지→대응 퍼널 서사(센터피스)
- Detections & JA3 — Kitsune ML·srct 휴리스틱·JA3 시퀀스 이상탐지
- Rulesets — 44 탐지 룰셋 정본 카탈로그
- Blocklist & Reputation — 자동차단 목록 조회·차단/해제(
blacklist_info) - IP Reputation — AbuseIPDB 인앱 평판 팝업
- Whitelist — 차단 면책 IP/CIDR
