el34는 한 대에 다 넣은 보안 학습 랩이다. kt88 은 그 구성을 여러 대로 확장한다. el34 는 freeze 하고 건드리지 않는다.
표준 망분리 모델 그대로다. 모든 망의 게이트웨이는 보안장비이고, 그래서 망 간 통신은 반드시 보안장비를 지난다. 우회를 막는 별도 장치가 필요 없다 — 구조가 그렇게 되어 있다.
패킷 흐름(불변): 공격자 → fw → ips → waf → 웹앱. el34 의 체인을 그대로 계승한다. fw 가 경계(외부망·인터넷)를, ips 가 내부 구간의 게이트웨이를 맡는 2계층 방화벽 구조다.
┌────────────────── 코어 192.168.0.202 ──────────────────┐
인터넷 ◀ NAT ──┤ [fw] 경계 방화벽 ext 10.30.10.1 / pipe 10.30.1.1 │
│ │ │
│ [ips] Suricata + 내부 구간 통제 pipe 10.30.1.2 │
│ ├ 10.30.20.1 DMZ ├ 10.30.30.1 내부망 │
│ ├ 10.30.40.1 연구망 ├ 10.30.50.1 웹앱 │
│ │ └ 10.30.60.1 관리망 │
│ │ │
│ [waf] Apache + ModSecurity(CRS) │
│ dmz 10.30.20.80 ──프록시──▶ app 10.30.50.80 │
│ 취약앱 juice-shop 10.30.50.11 / DVWA 10.30.50.12 │
│ SIEM indexer .60.10 / manager .60.11 / dashboard .60.12│
└───────────────────────┬───────────────────────────────┘
▲
┌────────────────────────────────┴─────────────────────────┐
worker 192.168.0.203 research 192.168.0.231
내부망 엔드포인트 (리눅스/윈도우) 연구망 엔드포인트
10.30.30.11, .12 … 10.30.40.11 …
| 망 | 대역 | 게이트웨이 | 용도 |
|---|---|---|---|
| ext | 10.30.10.0/24 | 10.30.10.1 | 외부망 — 공격자 |
| dmz | 10.30.20.0/24 | 10.30.20.1 | DMZ — WAF(공개 진입점) |
| int | 10.30.30.0/24 | 10.30.30.1 | 내부망 — 업무 엔드포인트 |
| res | 10.30.40.0/24 | 10.30.40.1 | 연구망 — 분석/샌드박스 |
| app | 10.30.50.0/24 | 10.30.50.1 | 웹앱 — WAF 뒤 (직접 접근 차단) |
| mgmt | 10.30.60.0/24 | 10.30.60.1 | 관리망 — SIEM (에이전트 1514/1515만 허용) |
취약 웹앱은 WAF 를 통해서만 도달할 수 있다. 공격자가 앱에 직접 가려 하면 fw 가 막고, 내부망에서 가려 하면 ips 가 막는다. WAF 만 app 세그먼트에 다리를 걸치고 있다.
컨테이너를 macvlan으로 붙인다. macvlan 은 컨테이너에 물리 네트워크의 IP 를 직접 주는 표준 Docker 네트워크 드라이버다(bridge / host / macvlan / overlay / none). 컨테이너가 물리 회선에 자기 IP 와 자기 MAC 으로 붙으므로, 다른 호스트에 있어도 같은 망의 구성원이 된다.
그래서 엔드포인트 호스트에는 설정할 것이 없다. 커널 파라미터, 라우팅, 방화벽 룰
전부 손대지 않는다. docker-compose.yaml 에 macvlan 네트워크 하나를 정의하는 것이
전부다. 라우팅과 필터링은 코어의 보안장비(fw / ips)가 전담한다.
정직하게 짚어둘 점. 네 망이 하나의 물리 스위치(=하나의 L2)를 공유한다. IP 주소로는 나뉘어 있지만 회선은 같다. 그래서 내부망 장비가 정적 라우트를 직접 박으면 보안장비를 건너뛸 수 있다. 이건 결함이 아니라 왜 VLAN 이 필요한가를 보여주는 실습 소재다. 물리적으로 망을 나누려면 관리형 스위치와 VLAN 이 필요하고, 지금 강의실 스위치는 비관리형이라 불가능하다(아래 참조).
이 한계는 추상론이 아니다. 실제로 두 번 드러났다. ① 윈도우 VM 에 DHCP 를 주려 했더니 강의실 라우터가 먼저 응답해 VM 이 192.168.0.105 를 받아갔다(그래서 랩 주소는 전부 고정으로 바꿨다). ② 내부망 장비의 MAC 이 IPS 의 모든 세그먼트 인터페이스 ARP 테이블에 보인다. 왜 VLAN 이 필요한가를 이보다 잘 보여주는 교보재가 없다.
| 항목 | 결과 |
|---|---|
| duplex | 100Mbps full-duplex → 허브 아님 |
| STP BPDU / LLDP / CDP / EAPOL (80초) | 0개 → 관리형 아님 |
| Netgear NSDP 디스커버리 | 무응답 → 웹 스마트스위치도 아님 |
| 관리 IP | LAN 스윕에서 미발견 |
비관리형 스위치로 확정. VLAN·포트미러링 불가.
⚠ 호스트 3대 모두 기가비트 NIC(RTL8111/8168)인데 링크가 전부 100M 로 협상된다. 케이블 문제가 아니라 스위치가 패스트이더넷 제품이라는 뜻이다. 엔드포인트를 늘릴수록 이미지 배포·로그 수집이 이 100M 를 공유하므로 기가비트 스위치 교체를 선행 과제로 둔다.
| 호스트 | 역할 | 사양 |
|---|---|---|
| 192.168.0.202 | core — 방화벽/IPS/WAF/SIEM | Intel N150 4C / 15GB / 423GB |
| 192.168.0.203 | worker — 내부망 엔드포인트 | 〃 |
| 192.168.0.231 | research — 연구망 엔드포인트 | 〃 |
# 호스트마다 1회 (docker 설치가 전부)
scp -r kt88 ccc@<host>:/tmp/
ssh ccc@<host> 'sudo /tmp/kt88/bootstrap/bootstrap-host.sh'
# 코어 — 준비(커널 파라미터 + Wazuh 인증서) 후 기동
ssh ccc@192.168.0.202 'sudo /tmp/kt88/hosts/core/prepare-core.sh'
ssh ccc@192.168.0.202 'cd /tmp/kt88/hosts/core && docker compose up -d --build'
# 엔드포인트
ssh ccc@192.168.0.203 'cd /tmp/kt88/hosts/worker && docker compose up -d'
ssh ccc@192.168.0.231 'cd /tmp/kt88/hosts/research && docker compose up -d'해당 호스트의 docker-compose.yaml 에 서비스 한 항목을 추가하고 IP 를 지정한다.
호스트를 새로 늘릴 때도 bootstrap 후 compose 를 놓으면 끝이다 — 다른 호스트는 건드리지
않는다.
ep-linux-03:
image: ubuntu:22.04
command: sleep infinity
networks:
int: { ipv4_address: 10.30.30.13 }3대 실기기에서 확인한 결과:
| 항목 | 결과 |
|---|---|
| 체인 성립 | 내부망 → 인터넷 traceroute 가 10.30.30.1(ips) → 10.30.1.1(fw) → WAN |
| 내부망 → 같은 내부망 | 통신 OK, 0.1ms (장비를 안 지남) |
| 내부망 → 연구망 | 차단 — ips 드롭 카운터 3 packets / 252 bytes 증가로 확인 |
| 연구망 → 내부망 | 차단 — 드롭 카운터 3 packets, 그리고 Suricata 탐지 |
| Suricata 탐지 | ["10.30.40.11","10.30.30.11","KT88 연구망->내부망 접근 시도"] |
| 내부망 → 인터넷 | OK (fw NAT 경유) — DNS·apt 설치 정상 |
| 망 간 통신 시 출발지 IP | 보존 (10.30.30.11 그대로 도착, NAT 없음) |
| 엔드포인트 호스트 커널 설정 | 0건 |
| 공격자 → WAF | landing 200 / juice 200 / DVWA 302 |
| 공격자 → 웹앱 직접 (WAF 우회) | 차단 — fw 카운터 3 packets / 180 bytes |
| SQLi / XSS / sqlmap | 403 — CRS 942100(SQLi), 941100(XSS), 913(스캐너) |
| WAF 감사로그가 본 출발지 | 10.30.10.5 — 진짜 공격자 IP (NAT 없음) |
| Suricata 가 본 출발지 | 10.30.10.5 — SQLi·XSS·sqlmap 전부 탐지 |
| ET Open 룰셋 | 52,069개 로딩(실패 0) — Shellshock(CVE-2014-6271) 등 실제 탐지 |
| 에이전트 등록 | 다른 호스트의 엔드포인트 3대 모두 Active (ep-linux-01/02, res-01) |
| 로그 파이프라인 | 엔드포인트 → 매니저 → 인덱서, wazuh-alerts 인덱스에 적재 확인 |
| FIM 탐지 | res-01(.231)에서 useradd → /etc/group·/etc/gshadow 변경 알림 |
| 대시보드 | https://192.168.0.202:5601 접근 가능 |
| 윈도우 엔드포인트 | ep-win-01 10.30.30.21 — Windows 11 Pro, 에이전트 Active, 알림 521건 |
| 윈도우 공격면 | RDP 3389 / SMB 445 / RPC 135 개방 — 랩 안에서 공격 대상 |
| 윈도우 콘솔 | http://192.168.0.203:8006 접근 가능 |
세 계층이 각각 다른 근거로 같은 공격을 잡는다는 점이 그대로 드러난다 — fw 는 경로를 막고(카운터), ips 는 패킷을 탐지하고(Suricata alert), waf 는 요청을 차단한다(CRS 룰 + 403). 실습에서 셋을 각각 확인시킬 수 있다.
Host 헤더를 IP 로 보내면 CRS 920(“Host 가 IP”) 룰이 먼저 걸려 403 이 난다. SQLi/XSS 룰이 걸린 것을 보려면
-H "Host: dvwa.kt88.lab"처럼 이름으로 요청해야 한다.
IPS 는 기동에 약 2분 걸린다. 5만 개 룰로 탐지 엔진을 빌드하는 시간이고, N150 4코어에서는 그 정도가 정상이다. 이 동안 CPU 한 코어가 100% 로 붙는다. 기동 후에는 메모리 약 780MB, 유휴 CPU 8% 수준.
net/segments.env 망 정의 — 단일 진실원천
bootstrap/ 갓 설치한 우분투 → kt88 호스트 (docker 설치만)
hosts/core/ fw + ips + waf + SIEM(Wazuh) + 취약앱 + 공격자
hosts/core/prepare-core.sh 코어 전용 준비 — 커널 파라미터 + Wazuh 인증서
endpoint/ 엔드포인트 공용 이미지 (Wazuh 에이전트 내장)
hosts/worker/ 내부망 엔드포인트
hosts/research/ 연구망 엔드포인트
hosts/worker/windows/ 윈도우 엔드포인트 (QEMU/KVM, 최초 부팅 시 에이전트 자동 설치)
- 물리 네트워크 실측 / 설계 확정
- fw(경계) + ips(내부 구간) 2계층 방화벽, 정책 시행 검증
- 엔드포인트 확장 패턴 (3대 실기기 검증)
- IPS(Suricata) — 별도 컨테이너, fw→ips 체인 (실기기 검증)
- WAF(Apache+ModSecurity CRS) + 취약 웹앱 — fw→ips→waf→app 체인 완성
- SIEM(Wazuh) + 엔드포인트 에이전트 등록 — 원격 호스트 3대 Active, FIM 탐지 확인
- 윈도우 엔드포인트 — 내부망 10.30.30.21, 에이전트 Active, RDP/SMB 개방
- pjt 베어메탈 — 보류