개요 — 무엇을 하나
IP 평판 조회는 보안 화면 어디서든 의심 출발지 IP(src_ip)를 클릭하면 서버가 AbuseIPDB 위협 인텔을 대신 조회해 인앱 팝업으로 보여 주는 공용 기능입니다. 브라우저에서 외부 사이트로 나가지 않고, 콘솔 안에서 곧바로 "이 IP가 얼마나 악명 높은가"를 판정합니다.
핵심 특성:
- 순수 조회(read-only). 이 기능은 AbuseIPDB
/api/v2/check만 호출합니다. IP를 외부로 신고·publish 하지 않습니다 — 국제공조(신고 제출)는 별개의 후속 대응 단계입니다. - 악용 신뢰도(Abuse Confidence Score) 0–100 게이지 + 신고 수·신고자 수·용도·ISP·국가·도메인·Tor/화이트리스트 플래그·최근 신고 내역을 정규화해 표시합니다.
- 다중 키 라운드로빈. 평판 API에 등록한 AbuseIPDB 키 풀을 순서대로 소비하고, 429(쿼터 초과)·401/403(키 문제) 응답이면 자동으로 다음 키로 대체합니다(쿼터 풀링).
- IP당 1시간 캐시. 무료 티어 1000회/일 쿼터를 보호하기 위해 같은 IP를 1시간 안에 반복 조회하면 캐시된 결과를 돌려줍니다.
- 공용 믹스인. Threats·Detections·Security Overview·Blocklist 등 여러 화면이 같은 팝업 컴포넌트를 공유합니다.
이 문서의 라이브 버튼은 Security 영역(
/security)으로 이동합니다. 평판 조회는 독립 페이지가 아니라, 보안 화면의 IP 옆에 붙는 심볼 아이콘(.infr-ipsym)이나 [평판 조회] 버튼을 눌렀을 때 뜨는 공용 팝업입니다.
언제 쓰나
- Threats에서 심각도 상위 공격 IP를 트리아지할 때 — 정말 악성인지, 알려진 스캐너/봇넷인지 즉시 확인.
- Detections의 JA3 오펜더나 Kitsune 이상 IP가 "진짜 위협인지" 근거가 필요할 때.
- Blocklist & Reputation에서 차단/해제 결정 전, 대상 IP의 외부 평판을 대조할 때.
- Security Overview의 상위 위협 IP·JA3 오펜더 패널에서 빠르게 IP 평판을 훑을 때.
화면 구성
팝업(security/partials/abuse-modal.blade.php)은 조회 결과에 따라 세 가지 상태로 렌더됩니다.
성공 — 평판 카드
| 영역 | 표시 내용 |
|---|---|
| 신뢰도 게이지 | 0–100 conic 도넛 + 중앙 score%. 톤은 점수에 따라 색이 바뀝니다(아래 판정 표). |
| 판정 라벨 | 신고 없음 / 낮은 위험 / 주의 / 높은 위험 |
| 플래그 | Tor 노드(is_tor) · 화이트리스트(is_whitelisted) 배지 |
| 큰 지표 2개 | 총 신고 수(reports) · 신고자 수(distinct_users) |
| 메타 | 국가 · 용도(usageType) · ISP · 도메인 · 최근 신고 시각(lastReportedAt) |
| 최근 신고 내역 | 최대 6건 — 카테고리 칩 + 신고국 + 시각 + 코멘트(최대 200자) |
| 조회 스탬프 | 서버가 조회를 수행한 시각(checked_at) |
신뢰도 점수 → 판정 톤
| 점수 | 판정(verdict) | 톤 | 의미 |
|---|---|---|---|
| 0 | 신고 없음(clean) | good | 이 창에서 접수된 악용 신고 없음 |
| 1–24 | 낮은 위험(low) | info | 소수 신고 — 참고 |
| 25–74 | 주의(elevated) | warn | 유의미한 악용 이력 |
| 75–100 | 높은 위험(high) | crit | 강한 악성 신호 |
미설정 / 실패 상태
- 키 미설정:
열쇠 경고아이콘 + 안내문. 하단 [AbuseIPDB 열기] 버튼으로 외부 사이트에서 직접 확인. - 조회 실패: 쿼터 초과·네트워크 오류 등. 잠시 후 재시도하거나 외부 사이트 링크로 폴백.
하단 액션 버튼
| 버튼 | 동작 |
|---|---|
| IP 복사 | 클립보드에 IP 복사(비보안 컨텍스트면 execCommand 폴백) |
| IP 조회 | IP Connections 페이지로 이동(/infra/traffic/ips?src_ip=…) |
| AbuseIPDB 열기 | 외부 abuseipdb.com/check/{ip} 새 탭 |
| 차단 등록 | Blocklist에 프리필 딥링크(/security/blocklist?add={ip}) |
사용법
- 보안 화면(Threats·Detections·Overview·Blocklist)에서 IP 옆의 방패-검색 심볼 아이콘 또는 [평판 조회] 버튼을 클릭합니다.
- 팝업이 열리며 로딩 스피너가 표시되고, 프런트가 서버에 조회를 요청합니다:
GET /security/ip-reputation?ip=203.0.113.10
- 서버는 IP를 엄격히 검증(
filter_var FILTER_VALIDATE_IP)한 뒤 AbuseIpdbService로 조회하고 정규화된 JSON을 반환합니다. - 게이지·지표·최근 신고를 검토합니다. 필요하면 하단 버튼으로 복사/추적/차단으로 이어갑니다.
응답 스키마(정규화)
성공 시 서버가 돌려주는 JSON(팝업이 소비):
{
"ok": true,
"configured": true,
"ip": "203.0.113.10",
"score": 84,
"reports": 128,
"distinct_users": 41,
"country": "CN",
"usage": "Data Center/Web Hosting/Transit",
"isp": "Example Hosting Ltd",
"domain": "example-host.net",
"is_tor": false,
"is_whitelisted": false,
"last_reported": "2026-08-12T22:14:07+00:00",
"recent": [
{ "at": "2026-08-12T22:14:07+00:00", "country": "US", "categories": [18, 22], "comment": "SSH brute-force" }
],
"checked_at": "2026-08-13 09:31:20",
"external_url": "https://www.abuseipdb.com/check/203.0.113.10"
}
graceful 실패 시:
{ "ok": false, "configured": false, "external_url": "https://www.abuseipdb.com/check/203.0.113.10" }
| 필드 | 원본(AbuseIPDB) | 의미 |
|---|---|---|
score |
abuseConfidenceScore | 악용 신뢰도 0–100 |
reports |
totalReports | 총 신고 수 |
distinct_users |
numDistinctUsers | 서로 다른 신고자 수 |
country |
countryCode | 국가 코드 |
usage |
usageType | 용도(데이터센터/ISP/…) |
isp / domain |
isp / domain | ISP·도메인 |
is_tor |
isTor | Tor 출구 노드 여부 |
is_whitelisted |
isWhitelisted | AbuseIPDB 화이트리스트 |
last_reported |
lastReportedAt | 최근 신고 시각 |
recent[] |
reports[] | 최근 신고(최대 6건, 코멘트 200자 컷) |
신고 카테고리(1–23)
recent[].categories는 숫자 ID 배열입니다. 팝업은 security.abuse.cat lang 맵으로 라벨을 렌더합니다.
| ID | 라벨 | ID | 라벨 | ID | 라벨 |
|---|---|---|---|---|---|
| 1 | DNS 침해 | 9 | 오픈 프록시 | 17 | 스푸핑 |
| 2 | DNS 포이즈닝 | 10 | 웹 스팸 | 18 | 무차별 대입 |
| 3 | 사기 주문 | 11 | 이메일 스팸 | 19 | 악성 웹봇 |
| 4 | DDoS 공격 | 12 | 블로그 스팸 | 20 | 침해 호스트 |
| 5 | FTP 무차별 대입 | 13 | VPN IP | 21 | 웹앱 공격 |
| 6 | Ping of Death | 14 | 포트 스캔 | 22 | SSH |
| 7 | 피싱 | 15 | 해킹 | 23 | IoT 표적 |
| 8 | VoIP 사기 | 16 | SQL 인젝션 |
데이터 소스
이 기능은 신규 테이블을 만들지 않습니다. 외부 API 호출 + 키 레지스트리 + 캐시로만 동작합니다.
| 구성요소 | 설명 |
|---|---|
| AbuseIPDB API | https://api.abuseipdb.com/api/v2/check (verbose=1, maxAgeInDays=제공자값·기본 90). 타임아웃 8초. |
AbuseIpdbService |
조회·정규화·캐시·키 회전 소비. check($ip)(캐시) · checkWithKey()(관리자 단일 키 테스트, 캐시 없음). |
ReputationProviderService |
키 풀 SOT. 활성 infr_reputation_provider를 priority·id 순으로 30초 캐시 제공, rotated()로 라운드로빈, 등록 없으면 .env ABUSEIPDB_KEY 폴백. |
infr_reputation_provider |
AbuseIPDB 키 다중 등록 테이블(마이그레이션 000733). 키는 secret_enc(Crypt, write-only)로 저장 — 브라우저로 다시 노출되지 않습니다. 평판 API에서 관리. |
| 캐시 | Cache 키 infr:sec:abuse:{ip}, TTL 3600초(1시간). 라운드로빈 카운터는 infr:reputation:rr. |
config/services.php |
abuseipdb.key(=.env ABUSEIPDB_KEY) · abuseipdb.max_age_days(기본 90). 등록 키가 하나도 없을 때만 폴백. |
키 회전·장애 대체 흐름
check(ip)
└ 캐시 히트? → 반환
└ 미스 → providers.rotated() 순회
키#1 → 200? → normalize·캐시·반환
→ 429/401/403 → 다음 키로 대체(비밀 미출력)
키#2 → …
모두 실패 → { ok:false, error:"http_429"|"unreachable" }
무료 티어를 여러 개 등록하면 쿼터가 합산 풀링됩니다. 한 키가 그날 쿼터를 소진해 429를 반환하면 다음 키로 자동 넘어가므로, 조사량이 많은 팀은 평판 API에 키를 2–3개 등록하는 것을 권장합니다.
권한
- 조회 엔드포인트
GET /security/ip-reputation: 순수 조회라 step-up 재확인·감사 로그가 없습니다. Security 메뉴 영역(min_req 2) 뒤에 있으므로 보안 담당(staff=5) 이상이 실질 접근합니다. 외부로 아무것도 게시하지 않으므로 파괴적 작업이 아닙니다. - 잘못된 IP:
filter_var검증 실패 시 HTTP 422{"ok":false,"message":"invalid_ip"}. - 키 관리 평판 API:
infr_reputation_providerCRUD·실측 테스트·우선순위 드래그는 관리자(admin=10, level≥5) 전용 + 감사. 키는 암호화 저장되어 편집 시 교체/제거만 가능합니다. - 비밀 미노출: API 키·오류 응답 본문에 키가 새어 나가지 않습니다(오류는
http_상태코드문자열로만 기록).
문제해결 · FAQ
팝업에 "API 키가 설정되지 않았습니다"가 뜹니다
등록된 infr_reputation_provider 키가 없고 .env ABUSEIPDB_KEY도 비어 있는 상태입니다. 평판 API에서 AbuseIPDB 키를 추가하거나 .env에 ABUSEIPDB_KEY=YOUR_KEY를 채우세요. 그동안은 [AbuseIPDB 열기] 버튼으로 외부 사이트에서 확인할 수 있습니다.
"조회에 실패했습니다"가 반복됩니다
- 429(쿼터 초과): 무료 티어 1000회/일을 소진했을 수 있습니다. 키를 추가 등록해 쿼터를 풀링하거나 다음 날 재시도.
- 401/403(키 문제): 키가 만료·오타·비활성입니다. 평판 API에서 [실측 테스트]로 키를 검증하세요.
- 네트워크(unreachable): 콘솔 호스트에서
api.abuseipdb.com(443) 아웃바운드가 막혔는지 확인.
방금 차단한 IP가 여전히 낮은 점수로 보입니다
결과는 IP당 1시간 캐시됩니다(infr:sec:abuse:{ip}). 최신 값이 필요하면 최대 1시간 뒤 다시 조회하면 갱신됩니다. 캐시는 무료 쿼터 보호가 목적입니다.
여기서 IP를 AbuseIPDB에 신고할 수 있나요?
아니요. 이 기능은 조회 전용입니다. 신고 제출(국제공조)은 별도의 후속 대응 단계이며, 여기서는 외부로 어떤 데이터도 게시하지 않습니다.
최근 신고가 6건만 보입니다
정규화 단계에서 MAX_REPORTS=6으로 최신 6건만 유지합니다. 전체 이력은 [AbuseIPDB 열기]로 외부 사이트에서 확인하세요.
화이트리스트/내부 IP인데 조회 버튼이 안 보입니다
보안 화면은 등록 인스턴스 IP(자기망)를 내부 배지로 표기하고 평판 조회 버튼을 숨깁니다(SecurityScope). 우리 서버가 Suricata 방향 라벨상 "출발지"로 잡히는 오해를 막기 위함입니다. 내부망 정의는 운영 정책에서 관리합니다.
관련 항목
- 평판 API 관리 — AbuseIPDB 키 다중 등록·라운드로빈·실측 테스트
- Threats — IDS 위협 엔티티 트리아지에서 IP 평판 조회
- Detections · JA3 — JA3 오펜더·이상 IP 평판 확인
- Blocklist & Reputation — 차단 목록 + 평판 대조·차단 딥링크
- Security Overview — 방어 퍼널·상위 위협 IP
- Whitelist — 차단 면책·srct 무죄 자동 화이트리스트
