InfraGuard

방화벽 (공격 표면)

함대가 열어둔 오픈 포트를 인스턴스 방화벽 룰 × 등록 서비스로 교차해 위험도로 채색한 노출 지도입니다.

개요 — 무엇을 하나

Security ▸ Firewall(/security/firewall)는 우리 서버 함대가 열어 둔 포트를 한 장의 노출 지도로 그려 줍니다. 각 오픈 포트를 위험도(치명/주의/표준/미상)로 채색하고, 등록된 서비스인지(관리됨) 아니면 뜻밖의 열림(미등록)인지를 구분해 "무엇이 왜 밖에서 보이는가"를 즉시 파악하게 합니다.

세 원천을 교차(join)합니다:

infr_instance_firewall   (인스턴스별 방화벽 룰 = 오픈 포트/서비스)
        ×  infr_instance  (호스트 메타 — 공인 IP·중요도·환경·상태)
        ×  infr_service   (등록된 논리 서비스 — instance_id·port)
        →  FirewallLore 로 위험 분류 →  노출 지도

역할 경계: 이 화면은 물리 포트의 오픈/노출(공격 표면)을 봅니다. *논리 서비스의 도달성(헬스체크)*은 Service ▸ Catalog 소관입니다. 같은 포트라도 관점이 다릅니다.

언제 쓰나

화면 구성

헤더(HERO)

제목·부제(함대가 열어둔 포트 — 공격 표면 노출 지도), 최종 수집 시각 스탬프, LIVE / PAUSED 토글(30s 폴링 on/off), 전체화면 버튼.

빈 상태(Empty)

방화벽 룰이 하나도 없으면 온보딩 안내가 뜹니다 — Instances 로 이동 버튼이 /asset/instances로 보냅니다. Instances ▸ [fw]에서 firewall-cmd 결과를 import 하거나 원격 에뮬레이트로 오픈 포트를 수집하면 지도가 그려집니다.

KPI 밴드(5종)

KPI 라벨 정의 산출
ports 오픈 포트 전 호스트의 열림 항목 총계 분류된 룰 개수
hosts 노출 호스트 포트를 하나라도 연 머신 수 distinct instance_id
crit 위험 노출 치명 등급으로 분류된 포트 수 risk == 'crit'
unmanaged 미등록 노출 등록 서비스가 아니면서 위험이 ok가 아닌 포트 !managed && risk != 'ok'
public_crit 공인·치명 공인 IP 를 가진 호스트에 열린 치명 포트 crit && public

공인·치명(public_crit)은 의도적인 중복 집계입니다. 공인 IP 위의 치명 포트는 이미 위험 노출에, (등록 서비스가 아니라면) 미등록 노출에도 잡히지만, 이 조합(공인 × 치명)이 함대에서 가장 나쁜 단일 노출이므로 별도 KPI 로 한 번 더 표면화해 놓친 것이 없도록 합니다. 이 타일이 0 이 아니면 최우선으로 손봐야 합니다.

노출 위험 분포 밴드

crit·warn·ok·unknown 4색 스택 바로 위험도 구성비를 보여줍니다. 아래 레전드는 클릭형 필터 — 한 위험 등급을 누르면 그 등급만 남기고(다시 누르면 해제) 뷰가 좁아집니다. 밴드 옆 coverage(예: 7 / 12 호스트 수집됨)는 방화벽 룰이 수집된 호스트 수 대비 전체 인스턴스 수입니다.

툴바 · 필터

포트별 뷰

포트 카드 그리드. 카드마다 포트/프로토콜·서비스 라벨·위험 배지, 이 포트를 여는 호스트 칩(최대 8개 + +N), 하단에 호스트 수·공인 노출 수·분류. 카드 클릭 → 포트 상세 + 위험 해설 모달. 정렬은 위험도 → 호스트 수 → 포트 번호.

호스트별 뷰

호스트 카드 그리드. 카드마다 호스트명·별칭·환경·중요도, 공인 여부 배지, 그 머신이 여는 포트 칩(위험도 채색, 등록 서비스면 check-decagram 표식), 하단에 위험 등급별 카운트·총 포트 수. 포트 칩 클릭 → 같은 상세 모달. 정렬은 crit 수 → warn 수 → 포트 수.

포트 상세 + 위험 해설 모달

포트/프로토콜·서비스명·위험 배지·분류, 그리고 fwlore 해설 3단:

아래에 이 포트를 여는 호스트 목록(환경·중요도·존·공인/내부·등록/미등록 배지)과 Instances ▸ [fw] 에서 관리 링크.

사용법

  1. 상단 LIVE 가 켜져 있으면 30초마다 자동 갱신됩니다. 조사 중 값이 흔들리는 게 싫으면 PAUSED 로 멈춥니다.
  2. 공인·치명 KPI부터 확인합니다 — 0 이 아니면 위험도 레전드에서 치명을 눌러 포트별 뷰로 좁힌 뒤, 공인 칩(지구 아이콘)이 붙은 호스트를 먼저 처리합니다.
  3. 미등록만 체크로 "뜻밖의 열림"을 골라냅니다. 등록 서비스가 아닌 DB(3306/5432/27017)·캐시(6379/11211)·Docker(2375)·원격관리(23/3389/VNC)가 여기 걸리면 즉시 좁혀야 합니다.
  4. 포트 카드를 눌러 해설 모달에서 why/best 를 읽고, Instances ▸ [fw] 에서 관리로 넘어가 룰을 좁히거나 서비스로 등록합니다.
  5. 실제로 포트를 닫거나 룰을 편집하는 것은 이 화면이 아니라 대상 호스트의 방화벽 + Instances ▸ [fw] 에서 합니다. 이 화면은 지도이자 감사 도구입니다.

위험 분류 규약(FirewallLore)

포트 문자열은 단일(8080) 또는 범위(6081-6100)를 받습니다. 범위는 시작 포트 기준으로 well-known 매핑을 찾습니다.

risk 순위 의미 예시
crit 3 외부 노출 시 즉시 위험 — 데이터스토어·원격관리·파일공유·컨테이너 MySQL 3306, Redis 6379, RDP 3389, SMB 445, Docker 2375, k8s-api 6443
warn 2 주의 — 관리·레거시·비표준 SSH 22, SMTP 25, 8080/8443, SNMP 161, Grafana 3000
ok 1 표준 공개 서비스 HTTP 80, HTTPS 443, DNS 53, NTP 123, WireGuard 51820
unknown 0 매핑 없음 — 검토 필요 카탈로그에 없는 포트/대역

관리됨(managed) 판정

등록 서비스 맵은 infr_service.instance_id : port로 만듭니다. 인스턴스에 그 포트의 등록 서비스가 있으면 관리됨(check-decagram 표식, managed_name). 범위 포트는 시작 포트(low) 기준으로 매칭합니다. 등록 서비스가 없으면 미등록 — 위험이 ok가 아니면 미등록 노출 KPI 에 잡힙니다.

데이터 소스

테이블 / 소스 역할 채우는 주체
infr_instance_firewall 인스턴스별 오픈 포트/서비스 룰(원장) Assets ▸ Instances ▸ [fw] — 수동 CRUD / firewall-cmd --list-all 원시 텍스트 import / scripts/infr_firewall_probe.cjs JSON import
infr_instance 호스트 메타 — name·alias·env·criticality·status·ip_public Assets ▸ Instances
infr_service 등록 논리 서비스(instance_id·port·name·kind) → 관리됨 판정 Service ▸ Catalog
App\Support\FirewallLore 포트 → {key,label,category,risk,icon} 분류 SOT(로케일 독립) 코드
resources/lang/{ko,en}/fwlore.php 위험 등급·분류별 what/why/best 해설 lang pack

infr_instance_firewall 룰 형태(UNIQUE instance_id, zone, proto, port):

{
  "zone": "public",
  "ports": [
    { "port": "22",         "proto": "tcp", "service": "ssh" },
    { "port": "443",        "proto": "tcp", "service": "https" },
    { "port": "3306",       "proto": "tcp", "service": "mysql" },
    { "port": "6081-6100",  "proto": "tcp", "service": "" }
  ]
}

원시 firewall-cmd --list-all 텍스트도 [fw] import 가 파싱합니다(존 헤더 → services: 매핑 → ports: 직접):

public (active)
  services: http https ssh
  ports: 8080/tcp 6081-6100/tcp 3306/tcp

빌드된 대시보드는 서버에서 30초 캐시(infr:sec:firewall:dashboard)됩니다. 룰이 하나도 없으면 빈 페이로드(empty=true)로 온보딩 상태를 그립니다.

권한

문제해결 · FAQ

빈 화면(“아직 방화벽 데이터가 없습니다”)만 보여요. infr_instance_firewall에 룰이 없다는 뜻입니다. Assets ▸ Instances ▸ [fw]에서 firewall-cmd --list-all 결과를 붙여넣어 import 하거나, 원격 에뮬레이트로 오픈 포트를 수집하세요.

포트가 미상 서비스로 나와요. FirewallLore 카탈로그에 없는 포트입니다(위험 unknown). 정상 서비스면 Service ▸ Catalog에 서비스로 등록하거나 [fw] 룰의 service·note에 라벨을 달아 두라. 불필요하면 닫습니다.

등록된 서비스인데 미등록으로 표시돼요. 관리됨 판정은 같은 인스턴스에 infr_service가 그 포트로 있어야 성립합니다. 서비스가 다른 호스트에 있거나 포트가 다르면 매칭되지 않습니다. 범위 포트는 시작 포트 기준으로만 매칭합니다.

위험 노출은 있는데 공인·치명은 0 이에요. 치명 포트가 열린 호스트들이 모두 공인 IP(ip_public) 없이 내부 전용이라는 뜻입니다 — 노출 반경이 작아 상대적으로 안전합니다. 그래도 내부 위협·측면 이동을 고려해 좁히는 것이 좋습니다.

값이 실시간이 아니에요. LIVE 가 PAUSED 이거나 탭이 백그라운드일 수 있습니다. 대시보드는 서버에서 30초 캐시되므로 [fw]에서 룰을 바꾼 직후 최대 30초는 이전 값이 보일 수 있습니다.

포트를 여기서 닫을 수 있나요? 아니다. 이 화면은 읽기 전용 지도입니다. 실제 차단은 대상 호스트의 방화벽에서, 룰 원장 갱신은 Instances ▸ [fw]에서 합니다.

관련 항목

방화벽 — 오픈 포트 노출 지도
방화벽 — 오픈 포트 노출 지도