NGFW 하드웨어 오프로드

차세대 방화벽(NGFW) 하드웨어 오프로드 아키텍처 3대 유형(CPU중심 Lookaside·SoC중심 Lookaside·Inline SmartNIC/DPU), Fast/Slow/Exception 경로, Stateful 방화벽·NAT·ACL·QoS·터널(Tunnel)·IPSec 오프로드, 상용 NGFW 비교, Linux 커널 기반 NGFW 파이프라인(Pipeline), 세션 오프로드 결정 트리 종합 가이드

전제 조건: Netfilter 프레임워크(훅 시스템, nftables, conntrack 기초), Netfilter Flowtable(SW/HW 오프로드 메커니즘), eSwitch (Embedded Switch)(switchdev, TC flower offload), SmartNIC/DPU(DPU 아키텍처와 오프로드 기초) 문서를 먼저 읽으세요.
일상 비유: NGFW 하드웨어 오프로드는 공항 보안 검색에 비유할 수 있습니다. 첫 방문 승객(첫 패킷)은 신분증 확인, 수하물 X-ray, 금속 탐지기를 모두 거칩니다(Slow Path = 전체 Netfilter + DPI 검사). TSA PreCheck 승객(확립된 세션)은 이미 검증되었으므로 간소화된 경로로 빠르게 통과합니다(Fast Path = flowtable/eSwitch HW 오프로드). 수상한 행동이 감지되면 이미 검증된 승객이라도 다시 전체 검사를 받습니다(Exception Path = TCP RST, 프로토콜 변경, ALG). NGFW의 핵심 과제는 보안 수준을 유지하면서 첫 패킷 검사가 끝난 세션을 얼마나 빠르게 처리할 수 있는가입니다.

핵심 요약

  • 한 줄 정의: NGFW 하드웨어 오프로드란 차세대 방화벽의 패킷 처리 파이프라인 중 검증 완료된 세션을 SmartNIC/DPU 하드웨어에서 직접 전달하여 CPU 부하를 극적으로 줄이는 기술입니다.
  • 핵심 역할: 새 세션의 첫 패킷만 커널(Slow Path)에서 전체 보안 검사(ACL, conntrack, DPI, IPS)를 수행하고, 이후 패킷은 하드웨어 Fast Path로 우회시켜 라인 레이트(Line Rate) 처리를 달성합니다.
  • 사용 이유: DPI·IPS·App-ID·SSL 검사가 추가된 NGFW는 전통 방화벽 대비 패킷당 처리 비용이 수십 배 높으므로, 확립된 세션을 오프로드하지 않으면 처리량(Throughput)이 급감합니다.
  • Linux 구현: nf_flowtable(SW 오프로드) → TC flower + eSwitch FDB(HW 오프로드) → NFQUEUE(DPI 연동)를 조합하여 오픈소스 NGFW 파이프라인을 구성합니다.
  • 3계층 경로: Fast Path(HW/SW 고속 전달), Slow Path(전체 보안 파이프라인), Exception Path(이상 탐지 시 CPU 복귀)로 트래픽을 분류합니다.

단계별 이해

  1. 패킷 수신과 분류
    NIC가 패킷을 수신하면 eSwitch FDB 또는 TC flower 규칙으로 기존 오프로드 세션인지 확인합니다. 매칭되면 Fast Path로 즉시 전달하고, 매칭되지 않으면 커널 네트워크 스택으로 올립니다.
  2. Slow Path 보안 검사
    새 세션의 첫 패킷은 Netfilter 훅 체인을 통과하며 ACL 필터링, conntrack 상태 생성, NAT 변환, NFQUEUE를 통한 DPI/IPS 검사를 순서대로 받습니다.
  3. 오프로드 결정
    conntrack 상태가 ESTABLISHED로 전환되고 보안 정책이 허용(ACCEPT)이면, nf_flowtable이 해당 세션을 오프로드 후보로 등록합니다. ALG, 프래그먼트, 특수 프로토콜 세션은 제외됩니다.
  4. HW 오프로드 설치
    flowtable이 TC flower 규칙을 생성하고, 이를 eSwitch FDB에 설치합니다. 이후 해당 세션의 패킷은 커널을 거치지 않고 NIC 하드웨어에서 직접 NAT 변환과 포워딩을 수행합니다.
  5. Exception 처리와 세션 종료
    오프로드 중 TCP RST/FIN, 프로토콜 변경, 정책 업데이트가 감지되면 HW 규칙을 제거하고 패킷을 다시 Slow Path로 복귀시킵니다. conntrack 타임아웃(Timeout) 시에도 오프로드 엔트리를 정리합니다.

단계별 학습 로드맵

단계학습 내용관련 섹션난이도
1NGFW가 전통 FW와 어떻게 다른지 이해개요입문
1.5CPU중심 Lookaside / SoC중심 Lookaside / Inline 3대 아키텍처오프로드 아키텍처 3대 유형입문
2Fast/Slow/Exception 3계층 경로 구분데이터 플레인 아키텍처입문
3세션이 오프로드되는 조건과 결정 트리세션 오프로드 생명주기중급
4Stateful FW/NAT/ACL 오프로드 메커니즘Stateful 방화벽 오프로드중급
5QoS/터널/IPSec 오프로드 파이프라인QoS/터널/IPSec 오프로드중급
5.5암·복호화 트래픽 HW 오프로드암/복호화 HW 오프로드고급
6상용 NGFW 칩 아키텍처 비교 (암호화 관점)상용 NGFW HW 아키텍처참고
7커널 서브시스템 매핑(Mapping)커널 빌딩 블록중급
8실전 nftables + TC flower 규칙구현 패턴고급
9보안 vs 성능 트레이드오프 분석보안 vs 오프로드 트레이드오프고급
10성능 튜닝과 운영성능 튜닝, 운영 가이드고급
11QUIC/TLS 1.3/ECH의 NGFW 도전과제QUIC/ECH와 NGFW 오프로드고급
12멀티 테넌트 격리(Isolation)와 zone 분리멀티 테넌트 NGFW고급
13eBPF 기반 차세대 NGFW 파이프라인eBPF 기반 차세대 NGFW고급
14흔한 실수와 안티패턴 회피흔한 실수중급
15실습 (flowtable, DPI, XDP)실습 가이드중급

선수 지식 수준 가이드

지식 영역필수/권장수준학습 자료
iptables/nftables 기초필수체인, 테이블, 규칙 작성Netfilter 프레임워크
conntrack 이해필수NEW/EST/REL 상태, conntrack -L 사용conntrack 헬퍼
TC (Traffic Control)권장qdisc, filter, flower classifier 기초TC
NIC 드라이버 기초권장ethtool, ring buffer, offload 개념Network Device 드라이버
Linux 네트워킹 전반권장sk_buff, Netfilter 훅, 포워딩 경로sk_buff 구조

핵심 용어 정리

용어설명
Fast Path이미 검사가 완료된 세션의 후속 패킷을 최소 비용(HW 또는 SW)으로 전달하는 경로
Slow Path새 세션의 패킷이 전체 보안 파이프라인(ACL → conntrack → DPI → IPS)을 통과하는 경로
Exception Path오프로드된 세션이 비정상 상황(FIN/RST, ALG, 정책변경)으로 CPU로 복귀하는 경로
conntrack커널의 연결 추적(Connection Tracking) 시스템. TCP/UDP 세션 상태(NEW, ESTABLISHED, RELATED)를 관리
flowtablenf_flowtable. ESTABLISHED 세션을 Netfilter 훅을 건너뛰고 직접 전달하는 SW 오프로드
eSwitch FDBNIC 내장 하드웨어 스위치의 Forwarding Database. TC flower 규칙을 하드웨어에서 실행
TC flowerTraffic Control의 flower 분류기. L2~L4 필드 매칭으로 패킷을 분류하고 HW offload 가능
ct_stateconntrack 상태 플래그. +est(established), +new(new), +trk(tracked), +inv(invalid) 등
NFQUEUENetfilter Queue. 커널 패킷을 유저스페이스 프로그램(DPI 엔진)에 전달하는 메커니즘
CPSConnections Per Second. 초당 새 연결 수립 수. NGFW Slow Path의 핵심 성능 지표
App-IDApplication Identification. 포트번호가 아닌 실제 L7 프로토콜/애플리케이션을 식별하는 기술
DPIDeep Packet Inspection. 패킷 페이로드(Payload)를 분석하여 프로토콜, 시그니처, 악성 패턴을 탐지
ALGApplication Level Gateway. FTP/SIP 등 동적 포트를 사용하는 프로토콜의 NAT traversal 지원
SmartNIC/DPU프로그래머블 NIC. eSwitch, TC flower offload, IPSec crypto offload 등을 하드웨어에서 실행

NGFW HW 오프로드 개요

NGFW의 정의

차세대 방화벽(Next-Generation Firewall, NGFW)은 전통적인 L3/L4 패킷 필터링 방화벽에 다음 기능을 통합한 보안 장비입니다:

이러한 기능은 패킷당 처리 비용을 크게 증가시키므로, 하드웨어 오프로드를 통해 검증이 완료된 세션의 후속 패킷을 CPU를 거치지 않고 직접 전달하는 것이 성능의 핵심입니다.

NGFW 세대별 진화

세대시기핵심 기술오프로드 방식처리량(Throughput)
1세대 (패킷 필터)1990sL3/L4 ACL (stateless)ASIC 전체 오프로드1~10 Gbps
2세대 (Stateful FW)2000sconntrack + 상태 기반 ACL세션 테이블 ASIC10~40 Gbps
3세대 (UTM)2005~FW + IPS + AV + VPN 통합보안 프로세서(SP) 보조1~10 Gbps
4세대 (NGFW)2010~App-ID + DPI + SSL 검사검증 세션 선택적 오프로드10~100 Gbps
5세대 (SmartNIC NGFW)2020~eBPF/XDP + eSwitch + flowtable프로그래머블 HW offload100~400 Gbps

5세대의 핵심 차이점은 프로그래머블 오프로드입니다. 기존 ASIC은 벤더가 설계한 고정 파이프라인만 지원했지만, SmartNIC/DPU는 TC flower, eBPF, P4 등으로 오프로드 로직을 사용자가 정의할 수 있습니다.

NGFW 배치 모델

NGFW는 네트워크 내 위치와 동작 방식에 따라 여러 배치 모델이 있으며, 각 모델에서 HW offload의 적용 범위가 달라집니다:

배치 모델동작 방식HW 오프로드 적용장점단점
Inline (L3 Routed) 라우터처럼 L3 포워딩 경로에 위치. 패킷이 NGFW를 반드시 통과 flowtable + eSwitch FDB 전체 활용 가능 차단/허용 즉시 적용, NAT 연동 단일 장애점, 지연(Latency) 추가
Inline (L2 Transparent) 브리지(Bridge) 모드로 L2에서 투명하게 검사. IP 주소 불필요 eSwitch bridge offload + TC flower 활용 네트워크 구조 변경 불필요 NAT 불가, 라우팅(Routing) 정책 제한
TAP/SPAN (Passive) 트래픽 사본을 수신하여 탐지만 수행 (IDS 모드) HW offload 불필요 (패킷 전달 없음) 무중단, 성능 영향 없음 차단 불가, 실시간(Real-time) 대응 지연
Proxy (Explicit/Transparent) TCP 연결을 중간에서 종료/재수립 (SSL Proxy) 프록시 세션 간 TCP splice offload 가능 완전한 L7 검사, SSL 복호화 높은 CPU 부하, 세션 오프로드 제한
DPU 기반 (Bump-in-the-Wire) SmartNIC/DPU가 호스트 앞에서 독립적으로 NGFW 실행 DPU 내 eSwitch + flowtable 전용 활용 호스트 CPU 부하 제로, 독립 보안 DPU 비용, 관리 복잡성
배치 모델과 오프로드 효율: Inline L3 Routed 모델이 HW offload를 가장 효과적으로 활용합니다. flowtable의 L3 포워딩 + NAT rewrite가 모두 하드웨어에서 실행되기 때문입니다. L2 Transparent 모드는 bridge offload에 의존하므로 NIC 지원 범위가 더 제한적입니다. 이 문서의 구현 패턴은 주로 Inline L3 모델을 기준으로 설명합니다.

전통 FW vs NGFW 비교

특성전통 방화벽NGFW
검사 계층L3/L4 (IP, Port)L3~L7 (App-ID, DPI)
정책 기준5-tuple (src/dst IP, port, proto)5-tuple + App + User + Content
상태 추적conntrack (선택적)conntrack 필수 + DPI 세션 상태
IPS/IDS별도 장비통합 (inline IPS)
SSL 검사미지원SSL/TLS Proxy 또는 인라인 복호화
처리량 병목(Bottleneck)PPS (초당 패킷)CPS (초당 새 연결) + DPI 처리량
HW 오프로드 대상전체 ACL검증 완료 세션만 (selective offload)
오프로드 비율90%+ (대부분 정적 규칙)40~80% (DPI 결과에 따라 가변)

오프로드 필요성

NGFW에서 모든 패킷을 CPU에서 처리하면 다음과 같은 병목이 발생합니다:

100Gbps 이상 인터페이스에서 NGFW를 운영하려면, ESTABLISHED 세션의 후속 패킷을 하드웨어에서 처리하고 CPU는 NEW 세션과 예외 상황에만 집중해야 합니다.

트래픽 프로파일과 오프로드 효과

실제 네트워크 트래픽에서 세션의 특성을 분석하면 오프로드의 효과를 정량적으로 이해할 수 있습니다:

트래픽 특성일반적 비율패킷 비율바이트 비율오프로드 영향
장수명 대용량 세션 (영상, 다운로드)세션 5%60%80%오프로드 시 가장 큰 효과
중간 세션 (웹 브라우징)세션 20%25%15%DPI 분류 후 오프로드
단수명 세션 (DNS, API)세션 75%15%5%CPS에 영향, 오프로드 효과 적음

핵심 인사이트: 세션 수로는 단수명 세션이 압도적이지만, 실제 트래픽 볼륨(바이트)의 80%는 소수의 장수명 세션이 차지합니다. 이 장수명 세션을 HW offload하면 전체 CPU 부하의 대부분을 해소할 수 있습니다.

Elephant Flow vs Mouse Flow:
  • Elephant Flow: 100KB+ 세션. 비디오 스트리밍, 파일 다운로드, 백업. 오프로드 1순위 대상
  • Mouse Flow: 10KB 미만 세션. DNS 쿼리, API 호출, 헬스체크. 오프로드 효과 미미하지만 CPS에 영향
  • NGFW 오프로드의 목표: Elephant Flow를 모두 Fast Path로 → CPU는 Mouse Flow의 DPI에만 집중

NGFW 핵심 성능 지표

NGFW 성능을 평가할 때 반드시 구분해야 하는 핵심 메트릭입니다. 벤더 데이터시트는 대부분 "방화벽 처리량"만 강조하지만, 실제 NGFW 성능은 모든 보안 기능을 활성화한 상태에서 측정해야 합니다:

메트릭의미측정 단위병목 원인HW 오프로드 효과
FW 처리량 L3/L4 ACL + NAT + conntrack만 적용한 최대 처리량 Gbps 패킷 처리 오버헤드(Overhead), PPS flowtable/eSwitch로 100Gbps+ 가능
NGFW 처리량 App-ID + IPS + DPI를 모두 활성화한 처리량 Gbps DPI 엔진 CPU, 시그니처 DB 크기 EST 세션 오프로드로 DPI 부하 분산(Load Balancing)
Threat Prevention 처리량 IPS + AV + 안티봇 + URL 필터 전체 적용 처리량 Gbps 시그니처 매칭, 파일 검사 제한적 (첫 패킷/새 세션은 항상 검사)
SSL Inspection 처리량 SSL/TLS 복호화 후 전체 검사 처리량 Gbps PKI 연산 (RSA/ECDHE) Crypto offload (QAT, NIC inline crypto)
CPS 초당 새 연결 수립 수 connections/s conntrack NEW + DPI 첫 분류 간접적 (CPU 여유분이 CPS에 할당)
CC 동시 연결 수 (Concurrent Connections) sessions conntrack 테이블 + DPI 세션 메모리 HW flow 테이블 활용으로 메모리 절감
지연 (Latency) 패킷이 NGFW를 통과하는 데 걸리는 시간 μs 파이프라인 단계 수, 큐잉 HW Fast Path: <5μs, SW: 50~200μs
벤더 데이터시트 주의점: 상용 NGFW 벤더의 "최대 처리량"은 대부분 L4 FW만 활성화하고 64-byte UDP 패킷으로 측정한 값입니다. 실제 환경에서 IPS + SSL Inspection을 활성화하면 처리량이 1/5 ~ 1/10 이하로 떨어집니다. RFC 9411은 보안 기능별 처리량을 분리 측정하도록 규정합니다.
Fast Path (HW/SW Offload) eSwitch FDB Rule (HW) / nf_flowtable (SW) ESTABLISHED 세션 → conntrack bypass → L2/L3 forwarding → NAT rewrite → TX 100Gbps+ 처리 CPU 부하 없음 Slow Path (Full Inspection) Netfilter hooks → conntrack NEW → ACL → NFQUEUE → DPI/IPS → App-ID → Verdict 첫 패킷 + 아직 분류되지 않은 세션 → 전체 보안 파이프라인 통과 1~10Gbps 처리 CPU 집약적 Exception Path ALG 프로토콜, IP fragment, TCP RST/FIN, ICMP error, 정책 변경 재분류 오프로드 불가 또는 오프로드 해제가 필요한 패킷 → Slow Path로 복귀 개별 처리 GC / 상태 전이 EST + ALLOW → offload RST/FIN/ALG → teardown 일반적 트래픽 분포: Fast Path 60~80% | Slow Path 15~30% | Exception 5~10%

오프로드 아키텍처 3대 유형

NGFW 하드웨어 오프로드는 패킷이 처리되는 주체와 경로에 따라 크게 세 가지 아키텍처로 분류됩니다. 이 분류는 앞서 소개한 Fast/Slow/Exception 3계층 경로가 어떤 하드웨어에서, 어떤 방식으로 구현되는지를 결정하는 근본적인 설계 선택입니다.

세 아키텍처는 상호 배타적이 아니며, 상용 NGFW는 기능별로 이를 혼합(Hybrid)하여 사용합니다. 예를 들어 Fortinet은 세션 오프로드에 SoC중심(NP7), SSL 복호화에 SoC중심(SP5), DPI에 CPU중심(CP9+CPU)을 동시에 적용합니다. 아래에서는 각 아키텍처의 전체 패킷 처리 관점에서의 동작 원리, 장단점, 적용 사례를 상세히 살펴봅니다.

암호화 오프로드와의 관계: 이 절은 NGFW 전체 패킷 처리 파이프라인(ACL, conntrack, NAT, DPI, 포워딩) 관점의 아키텍처 분류입니다. 암호화(IPSec, TLS, MACsec)에 특화된 3분류 상세는 암호화 오프로드 아키텍처 3분류 절에서 다루며, 커널 crypto API 매핑, 동기/비동기 완료 모델, 하드웨어별 스펙을 포함합니다.

CPU중심 룩어사이드 아키텍처

CPU중심 룩어사이드(CPU-Centric Lookaside) 아키텍처에서 범용 CPU(x86, ARM 서버)가 NGFW 파이프라인의 모든 단계를 직접 실행합니다. Netfilter 훅 체인, conntrack 상태 머신, nftables 규칙 평가, DPI 엔진(Suricata/nDPI) 호출이 모두 CPU에서 수행됩니다. 특정 연산이 CPU에 과도한 부하를 주는 경우에만 해당 작업을 PCIe 버스를 통해 외장 가속기(Lookaside 엔진)에 위임하고, 결과를 돌려받습니다.

동작 원리

  1. 패킷 수신: NIC이 패킷을 수신하여 DMA로 호스트 메모리에 적재 → NAPI/인터럽트로 CPU에 통보
  2. 전체 파이프라인 CPU 실행: Netfilter PREROUTING → conntrack → FORWARD(nftables ACL) → NFQUEUE(DPI) → POSTROUTING(NAT) 전 과정을 CPU가 순차 처리
  3. Lookaside 위임(선택적): 암호화(QAT), 정규식 매칭(HyperScan FPGA), 압축(IAA) 등 CPU 집약적 연산만 가속기에 전송 → 비동기 완료 대기
  4. 오프로드 판정 후 SW Fast Path: ESTABLISHED + ACCEPT 세션은 nf_flowtable에 등록하여 이후 패킷의 Netfilter 훅 체인을 건너뜀 (여전히 CPU에서 실행, 단 경로 단축)
  5. 패킷 송신: CPU가 ip_output()을 호출하여 NIC TX 큐에 패킷 전달

핵심 특성

항목설명
Fast Path 구현nf_flowtable SW 오프로드 (conntrack bypass만, CPU에서 실행)
Slow Path 구현전체 Netfilter 훅 + NFQUEUE + DPI (모두 CPU)
Lookaside 대상암호화(QAT/NITROX), 정규식(FPGA), 압축(IAA/QAT), AV 패턴 매칭
처리량 한계CPU 코어 수 × 코어당 처리량 (DPI 포함 시 코어당 1~5 Gbps)
CPS 한계CPU 기반 conntrack + DPI 초기 분류 (코어당 10K~100K CPS)
대표 구현리눅스 서버 + nftables + Suricata + QAT 카드, Check Point(CoreXL + SecureXL)

CPU중심 Lookaside의 패킷 흐름

아래 다이어그램은 CPU중심 아키텍처에서 새 세션(Slow Path)과 확립된 세션(SW Fast Path)의 처리 흐름을 보여줍니다. Lookaside 가속기는 파이프라인의 특정 단계에서만 호출됩니다.

CPU중심 룩어사이드: NGFW 패킷 처리 전체 흐름 호스트 CPU (x86/ARM 서버) — 전체 파이프라인 실행 NIC RX DMA → 호스트 메모리 flowtable SW Fast Path? conntrack nftables ACL + NAT NFQUEUE → DPI/IPS Verdict SSL 복호화 → DPI → 재암호화 CPU에서 수행 (가속기 위임 가능) SW Fast Path conntrack bypass NIC TX PCIe 가속기 QAT / NITROX 암호화 가속 FPGA / RegEx 패턴 매칭 IAA / 압축 데이터 압축 PCIe DMA 왕복 10-50μs EST match → bypass miss 위임/반환 CPU중심 룩어사이드 특성 요약 SW Fast Path (flowtable, CPU에서 실행) Slow Path (전체 Netfilter + DPI) Lookaside 위임 (PCIe DMA) 장점: ① 범용 CPU로 모든 프로토콜/규칙 유연 처리 ② SW 업데이트로 새 DPI 시그니처 즉시 적용 ③ 가속기 독립 확장 (PCIe 슬롯 추가) 단점: ① Fast Path도 CPU 실행 → 코어 수에 비례하는 처리량 한계 ② 패킷 DMA 복사 2회(NIC→메모리→NIC) ③ DPI 처리량이 전체 병목 대표 구현: 리눅스 서버(nftables + Suricata + QAT), Check Point(CoreXL + SecureXL), 가상 NGFW(VM/컨테이너)

CPU중심 아키텍처의 성능 프로파일

시나리오코어당 처리량16코어 서버 예상병목 원인
L3/L4 ACL만 (FW 모드)10~20 Gbps100~200 GbpsPPS, conntrack 해시
flowtable SW Fast Path10~40 Gbps100~200 Gbps메모리 대역폭, 캐시 미스
DPI + IPS 활성화1~5 Gbps16~80 GbpsDPI 시그니처 매칭
SSL Inspection (CPU AES-NI)2~8 Gbps30~120 GbpsRSA/ECDHE 핸드셰이크
SSL Inspection (QAT 가속)5~15 Gbps80~200 GbpsQAT PCIe 대역폭
CPU중심 아키텍처가 적합한 경우: ① DPI/IPS 시그니처를 자주 업데이트해야 하는 환경 (SW 배포만으로 즉시 적용) ② 다양한 프로토콜과 복잡한 정책 조합이 필요한 엔터프라이즈 경계 ③ 클라우드/가상화 환경에서 VM/컨테이너 기반 NGFW 운영 ④ 초기 투자 비용을 최소화하고 범용 서버로 시작하려는 경우

CPU중심 아키텍처에서의 Crypto Offload

CPU중심 아키텍처의 가장 일반적인 Lookaside 대상은 암호화 연산입니다. SSL Inspection이 활성화된 NGFW에서 CPU의 60~80%가 TLS 핸드셰이크(RSA/ECDHE)와 레코드 암·복호화(AES-GCM)에 소비되므로, 이를 PCIe 가속기(QAT, NITROX)에 위임하면 CPU 코어를 DPI에 집중할 수 있습니다.

Lookaside 대상가속기 예시CPU 절감 효과커널 API
TLS 핸드셰이크 (RSA/ECDHE)Intel QAT 4xxx/8970, NITROX VCPS 10x 향상 (5K→100K ops/s)crypto_akcipher, crypto_kpp
대칭키 벌크 암호화 (AES-GCM)Intel QAT 4xxx/8970코어당 2~8→100+ Gbpscrypto_aead
IPSec ESP (Crypto offload)NIC (ConnectX, E810)AES 연산만 NIC 위임xfrm_offload
정규식 패턴 매칭Intel HyperScan FPGA, Marvell REEDPI 시그니처 매칭 가속벤더 API
데이터 압축Intel IAA, QAT 압축로그 압축, 패킷 캡처 압축crypto_comp

CPU중심 아키텍처에서 QAT 가속기를 활용한 대표적인 NGFW crypto 파이프라인은 다음과 같습니다:

/* CPU중심 Lookaside NGFW crypto 파이프라인 */

[새 TLS 세션 - Slow Path]
패킷 수신 → conntrack NEW → nftables ACL ACCEPT
  → SSL MITM Proxy (nginx/haproxy)
    → TLS ClientHello 수신
    → QAT Lookaside: RSA-2048 서명 / ECDHE P-256 키 교환
      → CPU: -EINPROGRESS → 다른 패킷 처리 → QAT IRQ → 콜백
    → TLS 핸드셰이크 완료 → 대칭키 확보
    → setsockopt(SOL_TLS) → kTLS 활성화 (NIC inline 가능)
  → NFQUEUE → Suricata DPI (평문 검사)
  → Verdict ACCEPT → flowtable 등록

[확립된 TLS 세션 - Fast Path]
패킷 수신 → NIC Inline: kTLS 복호화 (AES-GCM)
  → flowtable bypass → NAT rewrite → NIC Inline: kTLS 재암호화 → TX
  → CPU 부하: 0%

SoC중심 룩어사이드 아키텍처

SoC중심 룩어사이드(SoC-Centric Lookaside) 아키텍처에서는 전용 네트워크 프로세서(NP) 또는 ASIC이 데이터 플레인의 Fast Path를 전담합니다. NP는 패킷 파싱, 세션 테이블 룩업, NAT rewrite, ACL 매칭, QoS 스케줄링을 하드웨어 파이프라인으로 와이어 속도에 가깝게 처리합니다. CPU는 컨트롤 플레인(정책 배포, 로깅, 관리)과 예외 패킷 처리(새 세션의 DPI, ALG, 정책 미매칭 패킷)만 담당합니다.

핵심 설계 원리는 "NP가 처리할 수 있는 패킷은 CPU에 전달하지 않는다"입니다. 새 세션의 첫 패킷만 CPU로 올라가고(Slow Path), CPU가 보안 검사를 완료하면 세션 정보를 NP의 하드웨어 세션 테이블에 프로그래밍합니다. 이후 해당 세션의 모든 패킷은 NP에서 직접 처리됩니다.

동작 원리

  1. 패킷 수신: 물리 포트에서 패킷이 NP ASIC에 직접 도달 (호스트 메모리 DMA 없음)
  2. NP 파이프라인 실행: 패킷 파서 → 세션 테이블 TCAM/Hash 룩업 → 매칭 시 NAT rewrite + ACL + QoS + 포워딩을 하드웨어에서 처리 → 즉시 TX
  3. 세션 미스 → CPU 전달(Lookaside): 세션 테이블에 매칭되지 않는 패킷(새 세션, 예외)은 내부 버스를 통해 CPU로 전달
  4. CPU에서 Slow Path 처리: conntrack NEW, nftables ACL, DPI/IPS 검사 수행
  5. 세션 프로그래밍: CPU가 검사 결과(ACCEPT + 세션 정보)를 NP의 세션 테이블에 기록 → 이후 패킷은 NP에서 직접 처리

핵심 특성

항목설명
Fast Path 구현NP ASIC 하드웨어 세션 테이블 (TCAM/Hash 기반 와이어 속도 처리)
Slow Path 구현CPU에서 Netfilter + DPI (NP→CPU 내부 버스 전달)
Lookaside 방향NP→CPU (예외 패킷), CPU→NP (세션 프로그래밍) — CPU중심과 반대 방향
처리량 한계NP ASIC 설계에 의존 (100~800 Gbps), CPU는 CPS만 제한
세션 테이블 용량NP TCAM/SRAM 크기에 의존 (수백만~수천만 세션)
대표 구현Fortinet(NP7 ASIC + CP9 + CPU), Juniper(Express Path NP + SPC3 + RE), Cisco(QFP)

SoC중심 Lookaside의 패킷 흐름

SoC중심 룩어사이드: NP가 Fast Path를 전담하는 구조 네트워크 프로세서 (NP ASIC) — Fast Path 전담 물리 포트 패킷 파서 세션 테이블 TCAM/Hash 룩업 NAT + ACL + QoS HW 파이프라인 TX 포트 Fast Path: 100~800 Gbps (와이어 속도) CPU 개입 없음, NP ASIC이 전체 처리 내부 인터커넥트 (AXI / Memory-Mapped / Proprietary Bus) CPU — 컨트롤 + 예외 처리 conntrack + ACL 새 세션 정책 평가 DPI / IPS App-ID, 시그니처 세션 프로그래밍 ACCEPT → NP 세션 테이블에 기록 정책 배포 · 로깅 · 관리 · ALG match miss → CPU로 NP에 기록 SoC중심 룩어사이드 특성 요약 장점: ① NP ASIC이 와이어 속도(100~800 Gbps)로 Fast Path 처리 — CPU 부하 거의 제로 ② 세션 테이블 용량이 ASIC 설계로 결정 — 수천만 동시 세션 지원 가능 ③ 패킷 데이터가 호스트 메모리를 거치지 않는 Fast Path → 지연 시간 극소 (<5μs) 단점: ① NP가 지원하지 않는 프로토콜/기능은 CPU로 폴백 → CPS 병목 ② ASIC 설계 변경 불가 → 새 프로토콜(QUIC, WireGuard) 지원에 HW 세대 교체 필요 ③ 벤더 종속 — 자체 ASIC/NP는 오픈소스 드라이버 부재, 벤더 어플라이언스 전용

상용 NGFW의 SoC중심 구현 사례

벤더NP/ASICFast Path 처리량세션 테이블 용량CPU 역할특이사항
Fortinet NP7 (자체 ASIC) 800 Gbps 12M 세션 DPI(CP9 보조), 관리 SP5(암호화), CP9(콘텐츠 검사) 별도 ASIC 추가 — 기능별 전용 칩
Juniper SRX Express Path NP + SPC3 400 Gbps 80M 세션 flowd(DPI), RE(관리) SPC3는 Lookaside 암호화 겸용, Express Path는 세션 오프로드 전용
Cisco Firepower QFP (QuantumFlow) 200 Gbps 30M 세션 Snort DPI, 관리 QFP는 프로그래머블 NP, microcode 업데이트로 제한적 기능 추가 가능
Huawei USG Hi1822 NP 200 Gbps 40M 세션 DPI, SSL, 관리 서버용 SmartNIC으로도 판매, NP + ARM 코어 통합 SoC
SoC중심 아키텍처가 적합한 경우: ① 100Gbps 이상의 라인레이트 처리가 필수인 데이터센터 경계/ISP ② 세션 수가 수천만 이상인 대규모 네트워크 ③ Fast Path 처리량이 최우선이고 DPI는 선택적으로 적용하는 환경 ④ 단일 어플라이언스(Appliance)로 납품하는 상용 NGFW 벤더

SoC중심 아키텍처에서의 Crypto Offload

SoC중심 아키텍처에서 암호화 처리는 두 가지 경로로 나뉩니다. NP ASIC 내장 크립토 엔진이 Fast Path에서 IPSec을 인라인 처리하고, SoC 내부의 별도 크립토 코프로세서(CAAM, OCTEON CPT, SP5 등)가 SSL/TLS 복호화를 Lookaside로 처리합니다.

벤더NP 인라인 크립토별도 크립토 코프로세서CPU 크립토 역할
Fortinet NP7: IPSec AES-GCM 인라인 (800 Gbps) SP5: SSL/TLS 핸드셰이크 + 레코드 가속 CP9 보조: DPI 시 복호화된 평문 처리
Marvell OCTEON CN10K NP: IPSec 인라인 (100 Gbps) CPT 코어: TLS/SSL 룩어사이드 (100 Gbps 대칭키) ARM 코어: DPI, 관리, 예외
NXP Layerscape DPAA2 SEC: IPSec 인라인 (10~40 Gbps) CAAM: Job Ring 기반 비동기 (10~20 Gbps) Cortex-A72: DPI, SSL 프록시
Juniper Express Path NP: 세션 오프로드 SPC3: SSL/IPSec Lookaside 카드 RE/flowd: DPI, 관리

SoC중심 아키텍처의 핵심 장점은 NP와 크립토 엔진이 동일 SoC 다이 내에 있어 내부 버스(AXI/AMBA)로 직접 통신한다는 점입니다. PCIe를 거치지 않으므로 Lookaside 지연이 1~5μs로, CPU중심 아키텍처의 QAT(10~50μs) 대비 5~10배 빠릅니다. 이에 대한 상세 분석은 SoC중심 룩어사이드(암호화) 절을 참조하세요.

인라인(Inline) 오프로드 아키텍처

인라인(Inline) 아키텍처에서는 SmartNIC/DPU가 네트워크 데이터 경로 자체에 위치하여 패킷이 호스트 CPU를 거치지 않고 NIC 하드웨어에서 직접 처리됩니다. SoC중심 아키텍처의 NP와 유사하지만, 핵심 차이점은 표준 Linux 커널 인터페이스(TC flower, eSwitch, flowtable HW offload)를 통해 오프로드 규칙을 프로그래밍한다는 점입니다. 벤더 전용 API가 아닌 오픈 표준을 사용하므로 리눅스 기반 NGFW에서 가장 주목받는 아키텍처입니다.

인라인 아키텍처의 근본적인 설계 원리는 "확립된 세션의 패킷이 호스트 메모리를 전혀 건드리지 않는다"입니다. NIC의 eSwitch FDB에 설치된 TC flower 규칙이 5-tuple + conntrack 상태로 매칭하여, NAT rewrite, 터널 encap/decap, VLAN 처리를 NIC ASIC에서 직접 수행한 뒤 대상 포트로 전달합니다.

동작 원리

  1. 패킷 수신: 이더넷 프레임이 NIC의 물리 포트에 도착
  2. eSwitch FDB 룩업: NIC 내장 eSwitch가 FDB 테이블에서 5-tuple + ct_state 매칭 → HW 규칙 히트(Hit) 시 즉시 처리
  3. HW Fast Path 처리: NAT rewrite, TTL 감소, 터널 encap/decap, VLAN push/pop을 NIC ASIC에서 실행 → 대상 포트 TX 큐로 직접 전달 (DMA-to-DMA, CPU 인터럽트 없음)
  4. FDB 미스 → 호스트 CPU: 매칭되지 않는 패킷은 일반 NIC RX 큐를 통해 호스트 CPU로 DMA 전달 → Slow Path(Netfilter + DPI) 처리
  5. 오프로드 설치: CPU에서 세션이 ESTABLISHED + ACCEPT로 확인되면 nf_flowtable이 TC flower 규칙을 생성하고 ndo_setup_tc()를 통해 NIC 드라이버에 전달 → eSwitch FDB에 HW 규칙 설치

핵심 특성

항목설명
Fast Path 구현eSwitch FDB + TC flower HW offload (NIC ASIC에서 와이어 속도 처리)
Slow Path 구현호스트 CPU에서 Netfilter + DPI (FDB 미스 시에만 진입)
프로그래밍 인터페이스표준 Linux: TC flower, ndo_setup_tc(), nf_flowtable HW offload
처리량 한계NIC 라인레이트 (25/50/100/200/400 Gbps)
FDB 규칙 용량NIC TCAM/EM 크기에 의존 (수만~수백만 엔트리)
대표 구현NVIDIA ConnectX + BlueField DPU, Intel E810, AMD Pensando DSC, nftables + flowtable HW offload

인라인 오프로드의 패킷 흐름

인라인(Inline): SmartNIC/DPU가 Fast Path를 하드웨어 처리 SmartNIC / DPU (eSwitch + Inline Crypto) 포트 RX eSwitch FDB TC flower 규칙 매칭 HW Fast Path 파이프라인 NAT rewrite · 터널 encap/decap · VLAN · TTL 포트 TX Inline Crypto IPSec · MACsec HW Fast Path: NIC 라인레이트 (100~400 Gbps) CPU 인터럽트 0건, 호스트 메모리 접근 0회, 지연 <5μs DMA → 호스트 FDB miss 패킷만 PCIe Bus (호스트 연결) 호스트 CPU — Slow Path만 처리 conntrack + ACL DPI / IPS 새 세션만 검사 flowtable HW offload 설치 nf_flowtable → TC flower → ndo_setup_tc() → eSwitch FDB에 HW 규칙 설치 match miss TC flower HW 규칙 설치 인라인(Inline) 아키텍처 특성 요약 장점: ① 표준 Linux 인터페이스(TC flower, nf_flowtable) — 벤더 비종속, 오픈소스 드라이버 ② HW Fast Path에서 CPU 인터럽트·DMA 완전 제로 → 호스트 CPU를 DPI에 100% 집중 ③ 동일 SmartNIC으로 NGFW + 가상 스위치(OVS) + IPSec VPN 통합 가능 단점: ① FDB 규칙 용량 한계 — NIC TCAM 크기에 따라 수만~수십만 규칙 상한 ② NIC 펌웨어가 지원하는 매칭/액션만 가능 — 복잡한 L7 매칭, ALG는 불가 ③ SmartNIC/DPU 비용 — 고성능 NIC은 일반 NIC 대비 3~10배 가격

인라인 아키텍처의 Linux 커널 연동

인라인 아키텍처의 핵심 장점은 표준 Linux 커널 API를 통한 HW 오프로드입니다. NGFW 관리자는 일반적인 nftables/TC 명령으로 정책을 설정하면, 커널이 자동으로 NIC 하드웨어에 규칙을 설치합니다.

# 1. nftables에서 flowtable HW offload 정의
nft add table inet filter
nft add flowtable inet filter ft {
    hook ingress priority 0 \;
    devices = { enp1s0f0np0, enp1s0f1np0 } \;
    flags offload \;       # ← HW offload 핵심 플래그
}

# 2. ESTABLISHED 세션을 flowtable으로 전달
nft add chain inet filter forward { type filter hook forward priority 0 \; }
nft add rule inet filter forward ct state established,related flow add @ft

# 3. 커널이 자동으로 TC flower 규칙 생성 → NIC eSwitch FDB에 설치
# 확인: HW offload 규칙 조회
tc -s filter show dev enp1s0f0np0 ingress
# filter protocol ip pref 1 flower chain 0
#   ct_state +est+trk   ← HW에서 conntrack 상태 매칭
#   action mirred (Egress Redirect to device enp1s0f1np0)
#   in_hw in_hw_count 1  ← HW offload 확인
인라인 아키텍처가 적합한 경우: ① 리눅스 기반 오픈소스 NGFW를 구축하면서 HW 가속이 필요한 경우 ② 데이터센터에서 SmartNIC/DPU로 호스트 CPU를 완전히 보안 검사에 전담시키려는 경우 ③ OVS(Open vSwitch) + NGFW + IPSec을 단일 SmartNIC에서 통합 운영하려는 경우 ④ 벤더 비종속 아키텍처로 NIC을 교체해도 동일한 nftables/TC 설정을 유지하려는 경우

인라인 아키텍처에서의 Crypto Offload

인라인 아키텍처에서 SmartNIC/DPU는 세션 오프로드(flowtable)뿐 아니라 암호화도 인라인으로 처리합니다. 패킷이 NIC ASIC을 통과하는 과정에서 암·복호화가 와이어 속도로 수행되므로, 호스트 메모리에 암호화된 데이터가 전혀 도달하지 않습니다.

인라인 Crypto 기술NIC 요구프로토콜처리량커널 설정
IPSec Packet offload ConnectX-6 Dx+, E810 ESP (AES-128/256-GCM) NIC 라인레이트 ip xfrm state ... offload dev eth0 dir out
IPSec Full offload ConnectX-7 + eSwitch ESP (AES-GCM) + 포워딩 NIC 라인레이트 eSwitch switchdev + TC flower + xfrm offload
kTLS TX/RX offload ConnectX-6 Dx+, E810 TLS 1.2/1.3 (AES-GCM) NIC 라인레이트 ethtool -K eth0 tls-hw-tx-offload on
MACsec offload ConnectX-6 Dx+, Microchip VSC 802.1AE (AES-128/256-GCM) NIC 라인레이트 ip link add ... type macsec offload mac

인라인 crypto의 핵심 제약은 AES-GCM 외 알고리즘 미지원SA/TLS context 수 제한(NIC 메모리 의존)입니다. 이 제약을 초과하는 세션은 자동으로 SW 폴백됩니다. 상세 알고리즘 매트릭스는 아키텍처별 알고리즘 지원 매트릭스를, NIC 벤더별 지원 현황은 전용 크립토 가속기 절을 참조하세요.

3대 아키텍처 종합 비교

아래 표는 세 아키텍처를 전체 NGFW 파이프라인 관점에서 비교합니다. 암호화에 특화된 비교는 암호화 오프로드 3종 비교를 참조하세요.

항목CPU중심 룩어사이드SoC중심 룩어사이드인라인 (SmartNIC/DPU)
Fast Path 주체CPU (nf_flowtable SW)NP ASIC (HW 세션 테이블)SmartNIC eSwitch (TC flower HW)
Slow Path 주체CPU (Netfilter + DPI)CPU (NP→CPU 전달 후 처리)호스트 CPU (NIC→DMA 후 처리)
Fast Path 처리량코어 수 × 10~40 Gbps100~800 Gbps (ASIC 설계)NIC 라인레이트 (100~400 Gbps)
Fast Path 지연50~200μs (SW 경로)<5μs (NP 파이프라인)<5μs (eSwitch 파이프라인)
Slow Path 처리량코어 수 × 1~5 Gbps (DPI)CPU 코어 수 의존호스트 CPU 코어 수 의존
CPS (새 연결/초)코어 수 × 10K~100KCPU 코어 수 의존호스트 CPU 코어 수 의존
동시 세션 (CC)호스트 메모리 의존NP TCAM/SRAM (수천만)NIC EM/TCAM (수만~수백만)
프로그래밍 인터페이스nftables, Netfilter API벤더 전용 API/CLITC flower, nf_flowtable, switchdev
새 프로토콜 지원SW 업데이트 즉시 가능NP FW/ASIC 세대 교체 필요NIC FW 업데이트 (제한적)
벤더 종속성낮음 (범용 서버)높음 (자체 ASIC 어플라이언스)중간 (표준 API, NIC 선택 가능)
초기 비용낮음 (서버 + SW)높음 (전용 어플라이언스)중간 (서버 + SmartNIC)
대표 구현리눅스 서버 + Suricata + QAT
Check Point (CoreXL)
Fortinet (NP7 + SP5)
Juniper SRX (SPC3)
Cisco (QFP)
NVIDIA BlueField DPU
Intel E810
AMD Pensando DSC
NGFW 오프로드 아키텍처 3대 유형 비교 CPU중심 룩어사이드 CPU = 전체 파이프라인 QAT FPGA ↑ 특정 작업만 위임 ↑ Fast Path: SW (flowtable) 처리량: 코어 비례 유연성: 최고 비용: 낮음 SoC중심 룩어사이드 NP ASIC = Fast Path CPU (예외 + DPI만) ↑ 예외 패킷만 CPU ↑ Fast Path: HW (ASIC) 처리량: 100~800 Gbps 유연성: 낮음 (ASIC 고정) 비용: 높음 (전용 장비) 인라인 (SmartNIC/DPU) NIC eSwitch = Fast Path 호스트 CPU (새 세션 DPI) ↑ FDB miss만 CPU ↑ Fast Path: HW (eSwitch) 처리량: NIC 라인레이트 유연성: 중간 (TC flower) 비용: 중간 (서버+NIC) 적용 영역 스펙트럼 소규모 · 가상화 · 클라우드 ISP · DC 경계 · 통신사 DC 내부 · 마이크로세그멘테이션 ← 유연성 · DPI 커버리지 높음 Fast Path 처리량 높음 →

아키텍처 선택 가이드

요구사항추천 아키텍처이유
DPI/IPS 시그니처를 주 1회 이상 업데이트CPU중심SW 업데이트만으로 즉시 적용, HW 제약 없음
Fast Path 100Gbps+ 필수, DPI는 선택적SoC중심NP ASIC이 와이어 속도 보장
리눅스 오픈소스 NGFW + HW 가속인라인TC flower/nf_flowtable으로 표준 오프로드
클라우드/VM 기반 가상 NGFWCPU중심범용 서버에서 SW만으로 구동
데이터센터 마이크로세그멘테이션인라인SmartNIC이 각 서버 앞단에서 NGFW 실행
ISP/통신사 엣지(Edge) 보안SoC중심수천만 세션 + 라인레이트 필수
SSL Inspection이 전체 트래픽의 80%+CPU중심 + QATLookaside 암호화 가속기로 핸드셰이크 처리
호스트 CPU를 NGFW에 0% 할당인라인 (DPU)BlueField DPU가 독립적으로 NGFW 실행
하이브리드가 현실: 실제 프로덕션 NGFW는 단일 아키텍처로 구성되는 경우가 드뭅니다. 가장 일반적인 조합은 인라인(세션 오프로드) + CPU중심 Lookaside(SSL 가속)입니다. 예를 들어 리눅스 서버에서 SmartNIC eSwitch로 ESTABLISHED 세션을 HW offload하면서, QAT 카드로 SSL Inspection의 RSA/ECDHE를 가속하는 구성입니다. 상용 NGFW HW 아키텍처 절에서 각 벤더의 하이브리드 구성을 상세히 비교합니다.

데이터 플레인 아키텍처

Fast Path (HW + SW)

Fast Path는 이미 보안 검사가 완료된 세션의 후속 패킷을 최소 비용으로 전달하는 경로입니다. 두 가지 수준이 있습니다:

HW Fast Path (eSwitch FDB)

eSwitch의 switchdev 모드에서 TC flower 규칙으로 ct_state +est +trk 매칭 후 FDB(Forwarding Database) 룰을 NIC 하드웨어에 설치합니다. 패킷이 NIC에 도착하면 CPU를 거치지 않고 직접 전달됩니다.

HW Fast Path의 동작을 단계별로 보면:

  1. 패킷 도착: 이더넷 프레임이 NIC의 RX 큐에 도달
  2. eSwitch FDB lookup: NIC 내장 하드웨어가 5-tuple + ct_state로 FDB 테이블을 검색
  3. 매칭 시 HW 처리: NAT rewrite (IP/Port/Checksum), TTL 감소, 터널 encap/decap, VLAN push/pop
  4. 직접 TX: 처리된 패킷이 대상 포트의 TX 큐로 직접 전달 (DMA to DMA, CPU interrupt 없음)

SW Fast Path (nf_flowtable)

nf_flowtable은 커널 소프트웨어에서 conntrack을 bypass하고 직접 L3 forwarding을 수행합니다. HW offload가 불가능한 경우(예: NIC 미지원, 복잡한 NAT, 특정 터널)의 폴백 경로입니다.

SW Fast Path는 커널의 Netfilter ingress 훅(priority -10)에서 동작하여, 일반 Netfilter 체인(PREROUTING → FORWARD → POSTROUTING)을 완전히 건너뜁니다. 이를 통해 nftables 규칙 평가, conntrack 상세 추적, NFQUEUE 전달 등의 오버헤드를 제거합니다.

Fast Path 전환의 커널 내부 흐름

패킷이 Fast Path로 처리되는 과정을 커널 코드 수준에서 살펴보면:

/* net/netfilter/nf_flow_table_ip.c */
/* flowtable ingress 훅에서 호출되는 핵심 함수 */
static unsigned int
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
                        const struct nf_hook_state *state)
{
    struct flow_offload_tuple_rhash *tuplehash;
    struct nf_flowtable *flow_table = priv;
    struct flow_offload_tuple tuple = {};
    enum flow_offload_tuple_dir dir;
    struct flow_offload *flow;

    /* 1. skb에서 5-tuple 추출 */
    if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0)
        return NF_ACCEPT;  /* 추출 실패 → Slow Path */

    /* 2. flowtable에서 lookup */
    tuplehash = flow_offload_lookup(flow_table, &tuple);
    if (!tuplehash)
        return NF_ACCEPT;  /* 미등록 플로우 → Slow Path */

    flow = container_of(tuplehash, struct flow_offload,
                        tuplehash[dir]);

    /* 3. TEARDOWN 상태면 Slow Path로 복귀 */
    if (flow_offload_stale_flow(flow))
        return NF_ACCEPT;

    /* 4. NAT rewrite 적용 */
    if (flow->flags & FLOW_OFFLOAD_SNAT)
        nf_flow_snat_ip(skb, thoff, ...);
    if (flow->flags & FLOW_OFFLOAD_DNAT)
        nf_flow_dnat_ip(skb, thoff, ...);

    /* 5. TTL 감소 + routing 적용 */
    ip_decrease_ttl(iph);
    skb_dst_set_noref(skb, &rt->dst);

    /* 6. 직접 전달 (Netfilter 훅 체인 건너뜀) */
    ip_output(state->net, state->sk, skb);
    return NF_STOLEN;  /* skb 소유권 가져감 → 훅 종료 */
}
코드 설명
  • 8-10행 flow_offload_tuple은 5-tuple(src IP, dst IP, src port, dst port, protocol)을 담는 구조체(Struct)입니다. flowtable의 해시(Hash) 키로 사용됩니다.
  • 13-14행 skb에서 IP/TCP/UDP 헤더를 파싱하여 5-tuple을 추출합니다. 실패하면 일반 Netfilter 경로로 진행합니다.
  • 17-18행 flow_offload_lookup()은 rhashtable 기반 해시 테이블(Hash Table)에서 O(1) 조회합니다. 미스 시 NF_ACCEPT로 Slow Path 진입합니다.
  • 24-25행 TEARDOWN 플래그가 설정된 플로우(TCP FIN/RST 수신)는 GC 대기 중이므로 Slow Path로 보내 정상 종료를 처리합니다.
  • 28-31행 NAT 오프로드: SNAT/DNAT 플래그에 따라 IP/포트를 직접 rewrite합니다. conntrack을 거치지 않으므로 매우 빠릅니다.
  • 34행 라우터 기능: TTL을 1 감소시킵니다. TTL=0이면 ICMP Time Exceeded를 생성하고 패킷을 DROP합니다.
  • 37-38행 NF_STOLEN을 반환하면 Netfilter가 이 패킷의 소유권을 flowtable에 넘깁니다. 이후 FORWARD/POSTROUTING 훅이 호출되지 않습니다.

flow_offload 구조체

/* include/net/netfilter/nf_flow_table.h */
struct flow_offload_tuple {
    union {
        struct in_addr   src_v4;   /* IPv4 소스 주소 */
        struct in6_addr  src_v6;   /* IPv6 소스 주소 */
    };
    union {
        struct in_addr   dst_v4;
        struct in6_addr  dst_v6;
    };
    struct {
        __be16  src;  /* 소스 포트 */
        __be16  dst;  /* 목적지 포트 */
    } port;
    u8      l3proto;    /* AF_INET / AF_INET6 */
    u8      l4proto;    /* IPPROTO_TCP / IPPROTO_UDP */
    struct dst_entry  *dst_cache; /* 라우팅 캐시 */
    int     iifidx;     /* ingress 인터페이스 인덱스 */
    int     oifidx;     /* egress 인터페이스 인덱스 */
};

struct flow_offload {
    struct flow_offload_tuple_rhash tuplehash[2]; /* [ORIGINAL] + [REPLY] */
    struct nf_conn  *ct;         /* 대응하는 conntrack 엔트리 */
    unsigned long    flags;      /* SNAT, DNAT, TEARDOWN 등 */
    u32              timeout;    /* GC 타임아웃 (jiffies) */
};

하나의 flow_offload는 양방향 플로우를 나타냅니다. tuplehash[0]은 ORIGINAL 방향, tuplehash[1]은 REPLY 방향의 5-tuple을 저장합니다. NAT가 적용된 경우 두 방향의 IP/포트가 다릅니다.

Slow Path (전체 검사)

새로운 연결의 첫 패킷(또는 아직 DPI 분류가 완료되지 않은 초기 패킷)은 전체 보안 파이프라인을 통과합니다. Slow Path는 NGFW의 보안 정밀도를 담당하며, 여기서의 결정이 세션의 나머지 수명 동안의 처리 방식을 결정합니다.

Slow Path에서의 패킷 처리 시간은 일반적으로 100us~5ms 범위입니다. DPI 엔진의 시그니처 수, 패킷 페이로드 크기, CPU 캐시(Cache) 히트율에 따라 달라집니다.

처리 순서:

  1. Ingress ACL — nftables/TC filter 기반 정적 규칙 (IP/Port/Protocol 매칭)
  2. conntrack — 연결 추적 테이블에 NEW 엔트리 생성 또는 기존 상태 갱신
  3. NAT — SNAT/DNAT/MASQUERADE 주소 변환(Address Translation)
  4. NFQUEUE — DPI 엔진으로 패킷 전달 (NFQUEUE & DPI 엔진 통합)
  5. DPI / App-ID — 프로토콜 분류, 시그니처 매칭, 애플리케이션 식별
  6. IPS — 시그니처 기반 공격 탐지
  7. Verdict — ACCEPT/DROP/QUEUE 최종 판정

CPS 병목: Slow Path의 처리량은 주로 초당 새 연결(CPS)으로 측정됩니다. DPI 엔진에 따라 코어당 10K~100K CPS 범위이며, 이는 NGFW의 실질적 성능 한계를 결정합니다.

Slow Path 커널 호출 체인

/* Slow Path에서 새 패킷이 거치는 커널 함수 호출 순서 */

/* 1. PREROUTING: conntrack 입구 */
nf_conntrack_in()
  → resolve_normal_ct()
    → nf_conntrack_find_get()    /* 해시 테이블에서 기존 ct 검색 */
    → init_conntrack()            /* 미발견 시 NEW ct 생성 */
      → __nf_conntrack_alloc()   /* slab에서 nf_conn 할당 */
      → nf_ct_helper_find()      /* ALG 헬퍼 자동 할당 (SIP/FTP 등) */

/* 2. FORWARD: nftables 체인 평가 */
nft_do_chain()
  → nft_lookup_eval()            /* set/map 기반 ACL 매칭 */
  → nft_ct_eval()                /* ct state 조건 평가 */
  → nft_queue_eval()             /* NFQUEUE verdict → DPI 전달 */

/* 3. NFQUEUE: 유저스페이스 DPI 전달 */
nf_queue()
  → nf_queue_entry_get_refs()    /* 참조 카운터 증가 */
  → nfnetlink_queue_enqueue()    /* netlink 소켓으로 전달 */
  /* ... Suricata/nDPI가 패킷을 분석 ... */
  → nf_reinject()                /* verdict 반환 후 재주입 */

/* 4. POSTROUTING: NAT 적용 */
nf_nat_ipv4_out()
  → nf_nat_packet()
    → nf_nat_manip_pkt()         /* SNAT/DNAT 주소 변환 */

/* 5. 전송 */
ip_output()
  → ip_finish_output()
    → neigh_output()             /* L2 헤더 추가 후 NIC TX */

CPS 병목 분석

NGFW에서 Slow Path의 CPS가 전체 성능을 제한하는 원인을 세분화하면:

단계CPU 비용 (cycles/pkt)병목 원인최적화 방법
conntrack alloc~500slab 할당 + 해시 삽입conntrack_buckets 증가, NUMA 로컬 할당
nftables 평가~200규칙 수에 비례set/map 기반 매칭 (O(1) lookup)
NFQUEUE 전달~1000netlink 소켓(Socket), 컨텍스트 스위치NFQUEUE batch mode, fanout 분산
DPI 분석~5000~50000패턴 매칭, SSL 파싱멀티코어 분산, 시그니처 최적화
verdict 반환~500재주입 + 훅 체인 재개BPF verdict 캐시
NAT~300conntrack NAT tuple 확인1:1 NAT 단순화

DPI가 전체 Slow Path 비용의 70~90%를 차지합니다. 따라서 DPI 완료 후 세션을 즉시 Fast Path로 전환하는 것이 핵심 최적화입니다.

Exception Path

이미 오프로드된 세션이라도 다음 경우에는 Fast Path에서 CPU로 복귀합니다:

Exception Path 처리의 커널 내부

Exception Path의 핵심은 flow_offload_stale_flow() 검사와 HW trap 메커니즘입니다:

/* net/netfilter/nf_flow_table_core.c */
static bool flow_offload_stale_flow(struct flow_offload *flow)
{
    /* TEARDOWN 플래그: TCP FIN/RST 수신 시 설정 */
    if (flow->flags & FLOW_OFFLOAD_TEARDOWN)
        return true;

    /* DYING 플래그: GC에 의해 만료 대기 중 */
    if (flow->flags & FLOW_OFFLOAD_DYING)
        return true;

    /* conntrack이 삭제된 경우 */
    if (!nf_ct_is_confirmed(flow->ct))
        return true;

    return false;
}

/* GC 워커: 주기적으로 만료된 플로우 정리 */
static void nf_flow_offload_gc_step(struct nf_flowtable *flow_table)
{
    struct flow_offload_tuple_rhash *tuplehash;
    struct rhashtable_iter hti;

    rhashtable_walk_enter(&flow_table->rhashtable, &hti);
    rhashtable_walk_start(&hti);

    while ((tuplehash = rhashtable_walk_next(&hti))) {
        struct flow_offload *flow = ...;
        if (nf_flow_has_expired(flow) ||
            nf_ct_is_dying(flow->ct)) {
            /* HW rule 삭제 → 카운터 동기화 → ct 삭제 */
            flow_offload_teardown(flow);
            nf_flow_offload_del(flow_table, flow);
        }
    }
}

ALG 프로토콜의 Exception 처리

FTP, SIP, H.323 등 ALG(Application Level Gateway) 프로토콜은 제어 채널에서 동적으로 데이터 채널 포트를 협상합니다. 이 과정에서 conntrack helper가 페이로드를 파싱해야 하므로 오프로드가 불가능합니다.

ALG 프로토콜Helper 모듈동적 포트오프로드 불가 이유
FTPnf_conntrack_ftpPORT/PASV 명령으로 데이터 포트 협상제어 채널 파싱 + RELATED 세션 생성
SIPnf_conntrack_sipSDP에서 RTP 포트 협상SDP 메시지 파싱 + NAT 주소 치환
H.323nf_conntrack_h323H.245에서 미디어 포트 협상ASN.1 디코딩 + NAT traversal
TFTPnf_conntrack_tftp서버가 임의 포트에서 응답RELATED expectation 추적
PPTPnf_conntrack_pptpGRE 터널 세션 생성GRE call ID 추적 + NAT
ALG와 NGFW 오프로드의 공존: ALG 제어 채널(예: FTP 21번 포트)은 항상 Slow Path에서 처리하되, ALG에 의해 생성된 데이터 채널(예: FTP PASV 포트)이 ESTABLISHED 상태가 되면 해당 데이터 채널은 flowtable으로 오프로드할 수 있습니다. 다만 이를 위해서는 conntrack helper가 expectation을 확인(confirm)한 이후여야 합니다.
기능HW Fast PathSW Fast PathSlow PathException Path
L3/L4 ACLHW 매칭bypassnftables chainnftables chain
conntrack 상태HW ct_statebypass (aging)전체 추적전체 추적
NAT rewriteHW rewriteSW rewritenf_natnf_nat
DPI / App-ID미수행미수행NFQUEUE → DPI재분류 가능
IPS 시그니처미수행미수행인라인 검사재검사
TCP 윈도우 검증미수행미수행conntrack 수행conntrack 수행
터널 encap/decapVXLAN/GRE/Geneve제한적전체 지원전체 지원
TTL/Hop LimitHW 감소SW 감소SW 감소SW 감소
통계/카운터HW counterSW counterper-chain counterper-chain counter
처리량 (100G NIC)100Gbps10~40Gbps1~10Gbps개별 처리
NIC RX XDP DDoS 사전 필터 eSwitch HW FDB match? HW Fast Path conntrack flowtable SW Fast Path nftables ACL + NAT NFQUEUE DPI / IPS App-ID, 시그니처 Verdict ACCEPT/DROP NIC TX match miss EST NEW ALLOW → offload 등록 Fast Path (HW/SW offload) Slow Path (전체 검사) 오프로드 등록 경로 유저스페이스 DPI 엔진 100Gbps 10~40Gbps 1~5Gbps (DPI) NGFW 전체 데이터 플레인 파이프라인

NIC-Level 오프로드와 NGFW 파이프라인 상호작용

NIC 하드웨어에는 RSS, GRO, TSO, checksum offload 등 다양한 NIC-Level 오프로드 기능이 내장되어 있습니다. 이 기능들은 일반 네트워크 스택에서는 성능을 극대화하지만, NGFW 파이프라인과 결합하면 세션 친화성 깨짐, DPI 시그니처 미탐지, 바이트 카운터 불일치 등의 부작용을 일으킬 수 있습니다. 이 섹션에서는 각 NIC 오프로드 기능이 NGFW 파이프라인의 어느 단계와 상호작용하는지 분석하고, 최적 설정 방법을 제시합니다.

NIC 오프로드 기능과 NGFW 파이프라인 매핑

아래 표는 주요 NIC 오프로드 기능이 NGFW 파이프라인의 어떤 단계에 영향을 미치는지 정리한 것입니다. 영향의 성격은 긍정적(+), 부정적(-), 조건부(±)로 구분합니다.

NIC 오프로드동작 위치영향받는 NGFW 단계영향설명
RSS (Receive Side Scaling)RX 큐 분배conntrack, DPI±해시 불일치 시 동일 세션이 다른 CPU로 분산되어 conntrack race 발생 가능
aRFS (Accelerated RFS)RX 큐 스티어링DPI 워커, conntrack+소켓/스레드가 실행 중인 CPU로 패킷을 유도하여 캐시 히트율 향상
Flow DirectorRX 큐 스티어링Exception Path+특정 플로우를 지정 큐로 고정하여 예외 경로 패킷의 처리 지연 감소
GRO (Generic Receive Offload)RX 병합DPI 시그니처 매칭±병합된 슈퍼 세그먼트에서 패킷 경계가 사라져 per-packet 시그니처 오탐 가능
LRO (Large Receive Offload)RX 병합 (HW)flowtable, conntrack-nf_flowtable과 호환되지 않으며, conntrack 시퀀스(Sequence) 추적 정확도 저하
GSO (Generic Segmentation Offload)TX 분할TC flower actions±TC flower 액션 후 재분할이 필요하여 eSwitch 오프로드 복잡도 증가
TSO (TCP Segmentation Offload)TX 분할 (HW)TC flower 카운터-슈퍼 세그먼트(Super Segment)가 단일 패킷으로 카운트되어 바이트 통계 왜곡
TX/RX Checksum체크섬 계산NAT rewrite+NAT 변환 후 체크섬 재계산을 HW에 위임하여 CPU 부하 절감
핵심 원칙: NIC 오프로드 기능은 개별적으로는 유익하지만, NGFW 파이프라인의 특정 단계와 결합하면 예상치 못한 부작용이 생깁니다. 오프로드 설정은 NGFW의 동작 모드(DPI 모드 vs 순수 포워딩 모드)에 따라 달라져야 합니다.

RSS/aRFS/Flow Director와 NGFW 세션 친화성

NGFW에서 세션 친화성(Session Affinity)은 동일 세션의 모든 패킷이 동일 CPU 코어에서 처리되는 것을 의미합니다. 이것이 깨지면 conntrack 엔트리의 lock contention이 증가하고, DPI 엔진이 세션 상태를 공유해야 하므로 성능이 급격히 저하됩니다.

RSS 해시와 conntrack zone 정렬

RSS는 NIC 하드웨어가 수신 패킷의 L3/L4 헤더를 해시(Hash)하여 여러 RX 큐에 분배하는 기능입니다. 문제는 RSS 해시 함수가 conntrack의 양방향 세션 매핑을 인식하지 못한다는 점입니다.

예시: TCP 연결 (10.1.1.1:5000 → 192.168.1.1:80)

  순방향 RSS 해시: hash(10.1.1.1, 192.168.1.1, 5000, 80) = 큐 3 → CPU 3
  역방향 RSS 해시: hash(192.168.1.1, 10.1.1.1, 80, 5000) = 큐 7 → CPU 7

  결과: 동일 세션의 양방향 패킷이 서로 다른 CPU에서 처리됨
  → conntrack spinlock contention 발생
  → DPI 워커가 세션 상태를 cross-CPU로 참조해야 함

이 문제를 해결하려면 RSS 해시 키를 대칭 해시(Symmetric Hash)로 설정하여 양방향 패킷이 같은 큐로 분배되도록 해야 합니다.

# RSS 해시 키 확인
ethtool -x eth0

# 대칭(Symmetric) RSS 해시 설정 (Toeplitz 키를 대칭으로 변경)
# 드라이버에 따라 지원 여부가 다름 (mlx5, i40e 등 지원)
ethtool -X eth0 hfunc toeplitz

# RSS 해시 필드 설정: L3+L4 (src/dst IP + src/dst port)
ethtool -N eth0 rx-flow-hash tcp4 sdfn
ethtool -N eth0 rx-flow-hash udp4 sdfn

# 대칭 해시 지원 확인 (mlx5 드라이버)
ethtool --show-priv-flags eth0 | grep symmetric
# symmetric_rss가 있으면:
ethtool --set-priv-flags eth0 symmetric_rss on
conntrack zone과 RSS 정렬: 멀티 테넌트(Multi-Tenant) NGFW에서 conntrack zone을 사용하는 경우, 동일 zone의 세션이 동일 CPU 그룹에서 처리되도록 RSS indirection table을 zone별로 분리해야 합니다. 그렇지 않으면 zone 간 lock contention이 성능 병목이 됩니다.

aRFS: DPI 워커 CPU로 패킷 유도

aRFS(Accelerated Receive Flow Steering)는 커널이 소켓이 처리되는 CPU를 NIC에 알려주어, 해당 소켓의 패킷을 그 CPU의 RX 큐로 직접 유도하는 기능입니다. NGFW에서 NFQUEUE를 통해 DPI 엔진(Suricata, nDPI 등)이 특정 CPU에서 워커 스레드를 실행하고 있을 때, aRFS를 활용하면 해당 패킷이 DPI 워커가 실행 중인 CPU로 직접 전달됩니다.

# aRFS 활성화
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries

# 각 RX 큐의 flow table 크기 설정
for rxq in /sys/class/net/eth0/queues/rx-*/rps_flow_cnt; do
    echo 4096 > "$rxq"
done

# ntuple 필터 활성화 (aRFS가 NIC에 룰을 설치하기 위해 필요)
ethtool -K eth0 ntuple on

# aRFS 동작 확인
cat /proc/net/softnet_stat
# 열 9: flow_limit_count, 열 10: rps_count

aRFS는 NFQUEUE 기반 DPI 파이프라인에서 특히 효과적입니다. DPI 워커가 nfq_set_queue_maxlen()으로 큐를 바인딩한 CPU와 패킷이 도착하는 CPU가 일치하면, cross-CPU IPI(Inter-Processor Interrupt) 없이 패킷이 DPI 워커로 전달됩니다.

Flow Director: Exception Path 전용 큐

Flow Director는 NIC 하드웨어가 특정 플로우 패턴(Flow Pattern)을 매칭하여 지정된 RX 큐로 스티어링(Steering)하는 기능입니다. NGFW에서는 Exception Path 트래픽(TCP RST, ICMP error, ALG 프로토콜)을 전용 큐로 분리하여 Fast Path 트래픽과의 간섭을 방지하는 데 활용합니다.

# Flow Director: TCP RST 패킷을 큐 0(Exception 전용)으로 스티어링
ethtool -N eth0 flow-type tcp4 action 0 loc 100

# ICMP error를 Exception 큐로
ethtool -N eth0 flow-type ip4 proto 1 action 0 loc 101

# FTP 제어 채널(포트 21)을 ALG 전용 큐로
ethtool -N eth0 flow-type tcp4 dst-port 21 action 1 loc 102

# SIP 시그널링(포트 5060)을 ALG 전용 큐로
ethtool -N eth0 flow-type udp4 dst-port 5060 action 1 loc 103

# 설치된 Flow Director 규칙 확인
ethtool -n eth0
실전 패턴: NGFW에서 CPU 코어를 역할별로 분리하는 것이 일반적입니다. 예를 들어 CPU 0~1은 Exception/ALG 처리, CPU 2~7은 Slow Path conntrack/ACL, CPU 8~15는 DPI 워커, 나머지는 Fast Path(flowtable) 처리에 배정합니다. Flow Director와 aRFS를 조합하면 이 구조를 NIC 하드웨어 수준에서 지원할 수 있습니다.

GRO/GSO/LRO와 DPI 검사

패킷 병합(Coalescing) 오프로드는 인터럽트(Interrupt) 빈도를 줄이고 처리량을 높이는 데 효과적이지만, DPI 엔진의 패킷 경계 인식에 중대한 영향을 미칩니다.

GRO와 DPI 시그니처 매칭

GRO(Generic Receive Offload)는 연속된 TCP 세그먼트(Segment)를 하나의 큰 sk_buff로 병합하는 소프트웨어 오프로드입니다. GRO가 활성화되면 하나의 sk_buff최대 64KB의 페이로드가 담기며, 이는 DPI 엔진에 다음과 같은 영향을 줍니다:

/* net/core/dev.c - GRO 수신 경로 */
static int napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
{
    /* GRO 레이어가 동일 플로우의 skb를 병합 시도 */
    skb_gro_reset_offset(skb);
    /* ...
     * 병합 성공 시: skb->len이 원래 MSS의 배수로 증가
     * → NFQUEUE로 전달 시 단일 대형 skb로 전달됨
     * → DPI 엔진은 이를 단일 "논리 패킷"으로 처리
     */
    return napi_gro_complete(napi, skb);
}

LRO와 flowtable 비호환성

LRO(Large Receive Offload)는 GRO와 유사하지만 NIC 하드웨어에서 TCP 세그먼트를 병합합니다. LRO의 핵심 문제는 TCP 헤더를 재작성한다는 것입니다. LRO는 병합된 슈퍼 세그먼트에 대해 새로운 시퀀스 번호와 ACK 번호를 생성하는데, 이는 다음 문제를 일으킵니다:

# flowtable 사용 시 LRO 반드시 비활성화
ethtool -K eth0 lro off

# 확인
ethtool -k eth0 | grep large-receive-offload
# large-receive-offload: off
/* net/netfilter/nf_flow_table_core.c */
static bool nf_flow_offload_check(struct nf_flowtable *flowtable,
                                   struct flow_offload *flow)
{
    /*
     * LRO가 활성화된 인터페이스에서는 TCP 시퀀스 추적이
     * 불안정하므로 flowtable 오프로드가 실패할 수 있음.
     * 커널은 dev->features에서 NETIF_F_LRO 플래그를 확인하고
     * 포워딩 경로에서 자동으로 LRO를 비활성화함.
     * (dev_disable_lro() in net/core/dev.c)
     */
    ...
}
필수 조치: NGFW 장비에서 nf_flowtable HW offload를 사용할 때는 반드시 ethtool -K eth0 lro off를 설정해야 합니다. 커널은 포워딩 경로에서 자동으로 LRO를 비활성화하지만(dev_disable_lro()), 명시적으로 설정하는 것이 안전합니다.

GSO와 TC flower 액션 재분할

GSO(Generic Segmentation Offload)는 TX 경로에서 커널이 큰 세그먼트를 MSS 단위로 분할하는 소프트웨어 오프로드입니다. TC flower 액션이 적용된 후 GSO 재분할이 필요한 경우, 다음과 같은 상호작용이 발생합니다:

TX 경로에서 TC flower + GSO 상호작용:

  1. 커널이 64KB GSO 세그먼트 생성
  2. TC egress에서 flower 규칙 매칭 → NAT rewrite 액션 실행
  3. NAT rewrite 후 체크섬 무효화
  4. GSO가 MSS 단위로 분할 (예: 1460B × 44 세그먼트)
  5. 각 분할 세그먼트에 대해 체크섬 재계산 필요

  → HW TSO가 활성화되면 단계 4~5를 NIC가 처리
  → HW TSO가 비활성화되면 CPU가 44회 분할 + 체크섬 계산

eSwitch HW offload에서는 TC flower 매칭, NAT rewrite, GSO 분할이 단일 하드웨어 파이프라인으로 처리되므로 이 문제가 발생하지 않습니다. 그러나 SW 경로에서는 TC flower 액션과 GSO의 순서가 성능에 영향을 줍니다.

TSO/Checksum 오프로드와 TC flower 카운터

TX 경로의 오프로드 기능은 NGFW의 트래픽 통계와 과금(Accounting)에 직접적인 영향을 미칩니다.

TSO와 바이트 카운터 불일치

TSO(TCP Segmentation Offload)가 활성화되면 커널은 최대 64KB의 슈퍼 세그먼트를 NIC로 전달하고, NIC 하드웨어가 이를 MSS 단위로 분할합니다. 문제는 TC flower의 패킷/바이트 카운터가 분할 전의 슈퍼 세그먼트를 기준으로 계산된다는 것입니다.

TSO가 TC flower 카운터에 미치는 영향:

  실제 전송: 44 × 1460B = 64,240 바이트 (44 패킷)
  TC flower 카운터: 1 패킷, 64,240 바이트

  → 패킷 카운터가 실제보다 1/44로 축소
  → PPS(Packets Per Second) 기반 QoS 정책이 부정확해짐
  → conntrack byte accounting과 TC flower 카운터가 불일치
# TC flower 규칙의 카운터 확인
tc -s filter show dev eth0 ingress

# conntrack 바이트 카운터 비교
conntrack -L -o extended | grep "10.1.1.1"

# 불일치 확인 예시:
# TC flower: packets 1523, bytes 98,234,880
# conntrack: packets 67,012, bytes 98,234,880
# → 바이트는 일치하지만 패킷 수가 44배 차이
해결 방법: NGFW에서 정밀한 패킷 카운팅이 필요한 경우(DDoS 탐지, PPS 기반 QoS), TC flower 카운터 대신 conntrack의 바이트 카운터를 참조하거나, ethtool -K eth0 tso off로 TSO를 비활성화합니다. 다만 TSO 비활성화는 TX 성능을 크게 저하시키므로 트레이드오프(Trade-off) 분석이 필요합니다.

Checksum 오프로드와 NAT 재계산

NAT 변환 후에는 IP 헤더와 TCP/UDP 체크섬을 재계산해야 합니다. 체크섬 오프로드의 SW/HW 처리 방식에 따라 NGFW 파이프라인의 동작이 달라집니다:

시나리오체크섬 처리CPU 비용호환성
HW checksum + HW NAT (eSwitch)NIC가 NAT rewrite와 체크섬을 한 번에 처리없음최적
SW NAT + HW checksum커널이 NAT rewrite 후 partial checksum을 NIC에 위임NAT만 CPU좋음
SW NAT + SW checksum커널이 NAT rewrite와 전체 체크섬을 모두 계산높음범용
HW NAT + SW checksum불가 (논리적 모순)--
/* net/netfilter/nf_nat_core.c - NAT 후 체크섬 처리 */
static void nf_nat_csum_recalc(struct sk_buff *skb,
                                u8 proto, __be32 oldip, __be32 newip)
{
    /*
     * skb->ip_summed == CHECKSUM_PARTIAL이면
     * 체크섬의 pseudo-header 부분만 업데이트하고
     * 나머지는 NIC HW가 최종 계산 (TX checksum offload)
     *
     * skb->ip_summed == CHECKSUM_NONE이면
     * 전체 체크섬을 SW에서 재계산
     */
    inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb,
                             oldip, newip, true);
}

conntrack의 바이트 어카운팅(Byte Accounting)과 관련하여, NAT 변환 전후의 패킷 크기가 변하지 않으므로(IP/포트 필드만 변경) 바이트 카운터에는 영향이 없습니다. 다만 NAT helper(ALG)가 페이로드를 수정하는 경우(FTP PORT 명령의 IP 주소 변경 등)에는 페이로드 크기가 변할 수 있으며, 이때 체크섬과 시퀀스 번호 조정이 모두 필요합니다.

NGFW 최적 NIC 오프로드 설정

NGFW의 동작 모드에 따라 NIC 오프로드 설정이 달라져야 합니다. 아래는 두 가지 대표적인 모드별 권장 설정입니다.

DPI 모드 vs 순수 포워딩 모드 비교

NIC 오프로드DPI 모드
(Suricata/IPS 연동)
순수 포워딩 모드
(ACL + NAT만)
이유
RSSON (대칭 해시)ON (대칭 해시)양방향 세션 친화성 필수
aRFSONOFFDPI 워커 CPU 캐시 최적화. 순수 포워딩은 불필요
Flow DirectorON (Exception 큐 분리)OFFDPI 모드에서 ALG/RST 패킷 격리. 순수 포워딩은 RSS로 충분
GROOFF 또는 조건부ONDPI 시그니처 정확도 vs 처리량 트레이드오프
LROOFFOFFflowtable 비호환. 포워딩 경로에서 항상 비활성화
GSOONONTX 성능 최적화. 두 모드 모두 유익
TSOONONTX 성능 핵심. 카운터 불일치는 conntrack으로 보정
TX ChecksumONONNAT 후 체크섬 재계산 HW 가속. 항상 유익
RX ChecksumONON수신 체크섬 검증 HW 가속. 항상 유익

자동화 설정 스크립트

#!/bin/bash
# NGFW NIC 오프로드 최적 설정 스크립트
# 사용법: ./ngfw-nic-offload.sh <인터페이스> <dpi|forward>

IFACE="${1:?Usage: $0  }"
MODE="${2:?Usage: $0  }"

echo "=== NGFW NIC Offload 설정: ${IFACE} (${MODE} 모드) ==="

# 공통 설정 (두 모드 공유)
ethtool -K "$IFACE" lro off          # flowtable 호환을 위해 항상 OFF
ethtool -K "$IFACE" tx on            # TX checksum offload ON
ethtool -K "$IFACE" rx on            # RX checksum offload ON
ethtool -K "$IFACE" tso on           # TCP Segmentation Offload ON
ethtool -K "$IFACE" gso on           # Generic Segmentation Offload ON

# 대칭 RSS 해시 (드라이버 지원 시)
ethtool --set-priv-flags "$IFACE" symmetric_rss on 2>/dev/null \
    && echo "[OK] symmetric RSS 활성화" \
    || echo "[SKIP] symmetric RSS 미지원"

# RSS 해시 필드: L3+L4 (양방향 세션 친화성)
ethtool -N "$IFACE" rx-flow-hash tcp4 sdfn 2>/dev/null
ethtool -N "$IFACE" rx-flow-hash udp4 sdfn 2>/dev/null
ethtool -N "$IFACE" rx-flow-hash tcp6 sdfn 2>/dev/null
ethtool -N "$IFACE" rx-flow-hash udp6 sdfn 2>/dev/null

case "$MODE" in
  dpi)
    echo "--- DPI 모드 (Suricata/IPS 연동) ---"
    ethtool -K "$IFACE" gro off        # DPI 시그니처 정확도 우선
    ethtool -K "$IFACE" ntuple on      # aRFS/Flow Director 필요
    
    # aRFS 활성화
    echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
    for rxq in /sys/class/net/"$IFACE"/queues/rx-*/rps_flow_cnt; do
        echo 4096 > "$rxq"
    done
    
    # Flow Director: Exception 패킷을 큐 0으로 분리
    ethtool -N "$IFACE" flow-type tcp4 action 0 loc 100 2>/dev/null
    ethtool -N "$IFACE" flow-type ip4 proto 1 action 0 loc 101 2>/dev/null
    
    echo "[DPI] GRO=off, aRFS=on, FlowDir=on"
    ;;
  forward)
    echo "--- 순수 포워딩 모드 (ACL + NAT) ---"
    ethtool -K "$IFACE" gro on         # 처리량 최적화
    
    echo "[FORWARD] GRO=on, aRFS=off, FlowDir=off"
    ;;
  *)
    echo "ERROR: 모드는 'dpi' 또는 'forward'만 지원합니다."
    exit 1
    ;;
esac

echo "=== 최종 오프로드 상태 ==="
ethtool -k "$IFACE" | grep -E "rx-checksumming|tx-checksumming|tcp-segmentation|generic-segmentation|generic-receive|large-receive|ntuple"
GRO 조건부 설정: DPI 모드에서도 GRO를 활성화하는 경우가 있습니다. Suricata 7.0+는 GRO 병합된 세그먼트를 올바르게 처리하는 로직이 포함되어 있으므로, Suricata 버전이 7.0 이상이면 gro on을 유지하여 처리량을 확보할 수 있습니다. suricata --build-info | grep GRO로 지원 여부를 확인하세요.
NIC RX/TX 파이프라인 — NGFW 오프로드 상호작용 RX Pipeline RSS 큐 분배 RX Checksum HW 검증 GRO/LRO 패킷 병합 XDP eBPF 초기 필터 TC ingress flower 매칭 conntrack 세션 추적 flowtable EST 오프로드 + 세션 친화성 (대칭해시 필수) + 항상 유익 - DPI 경계 손실 (LRO: flowtable 비호환) + DDoS 사전필터 + HW offload 핵심 단계 Fast Path 진입 TX Pipeline flowtable TX NAT rewrite TC egress flower 액션 GSO 분할 SW segmentation TSO HW segmentation TX Checksum HW 체크섬 Wire 패킷 송출 HW 직접 전달 + HW offload TC 후 재분할 - 카운터 왜곡 (PPS 부정확) + NAT 후 재계산 eSwitch HW Offload 범위: RSS → TC ingress → conntrack → flowtable → NAT → TC egress → TSO → Checksum → Wire ■ NGFW 파이프라인에 긍정적 ■ 부정적 / 주의 필요 ■ 조건부 (모드에 따라 다름) ■ 핵심 NGFW 단계

세션 오프로드 생명주기

첫 패킷 처리

TCP SYN 또는 첫 UDP 패킷이 도착하면 다음 과정을 거칩니다:

  1. conntrack NEWnf_conntrack_in()에서 새 conntrack 엔트리 생성
  2. 전체 Netfilter 훅 — PREROUTING → FORWARD → POSTROUTING 체인의 모든 규칙 평가
  3. NFQUEUE 전달 — DPI 엔진(Suricata, nDPI 등)이 패킷을 수신하여 프로토콜 분석 시작
  4. App-ID 분류 — 첫 패킷만으로 부족하면 DPI 엔진이 추가 패킷 요청 (보통 3~10패킷)
  5. Verdict 반환 — DPI 엔진이 ACCEPT 또는 DROP verdict를 반환

이 단계에서 오프로드는 발생하지 않습니다. 모든 검사가 완료될 때까지 Slow Path에 머뭅니다.

첫 패킷 conntrack 처리 상세

/* net/netfilter/nf_conntrack_core.c - 새 연결 생성 */
static struct nf_conntrack_tuple_hash *
init_conntrack(struct net *net, struct nf_conn *tmpl,
               const struct nf_conntrack_tuple *tuple,
               struct sk_buff *skb)
{
    struct nf_conn *ct;

    /* conntrack_max 초과 시 early drop (LRU) */
    if (nf_conntrack_max &&
        atomic_read(&net->ct.count) >= nf_conntrack_max) {
        if (!early_drop(net, hash))
            return ERR_PTR(-ENOMEM);  /* DROP: 테이블 가득 참 */
    }

    /* nf_conn 구조체 할당 (slab 캐시) */
    ct = __nf_conntrack_alloc(net, zone, tuple, ...);

    /* L4 프로토콜별 초기 상태 설정 */
    /* TCP: SYN_SENT, UDP: UNREPLIED */
    l4proto->new(ct, skb, dataoff);

    /* ALG helper 자동 할당 (포트 기반) */
    if (net->ct.sysctl_auto_assign_helper)
        nf_ct_helper_find(ct, tuple);

    /* unconfirmed list에 추가 (아직 해시에 삽입하지 않음) */
    /* POSTROUTING에서 confirm되면 해시 테이블에 삽입 */
    nf_ct_add_to_unconfirmed_list(ct);

    return &ct->tuplehash[IP_CT_DIR_ORIGINAL];
}
코드 설명
  • 10-13행 nf_conntrack_max 한계에 도달하면 early_drop()이 가장 오래된 UNREPLIED 연결을 삭제하여 공간을 확보합니다. 이 한계는 NGFW에서 매우 중요합니다.
  • 16행 nf_conn 구조체는 conntrack 엔트리 하나를 나타냅니다. slab 캐시에서 할당되어 메모리 단편화를 줄입니다.
  • 19-20행 TCP는 SYN_SENT 상태로 시작하여 3-way handshake 완료 시 ESTABLISHED로 전환됩니다. UDP는 첫 응답 수신 시 ASSURED 상태가 됩니다.
  • 27-28행 conntrack 엔트리는 처음에 unconfirmed list에 들어갑니다. 패킷이 성공적으로 POSTROUTING까지 도달하면 nf_conntrack_confirm()에서 해시 테이블에 삽입됩니다. 이 2단계 삽입은 DROP된 패킷의 conntrack 엔트리가 테이블을 오염시키는 것을 방지합니다.

DPI 엔진의 패킷 분류 과정

NFQUEUE를 통해 유저스페이스 DPI 엔진(Suricata/nDPI)에 전달된 패킷의 분류 과정입니다:

패킷 번호DPI 동작App-ID 상태Verdict
1 (SYN)TCP 핸드셰이크 감지UNKNOWNACCEPT (통과)
2 (SYN-ACK)서버 응답 확인UNKNOWNACCEPT
3 (ACK)연결 수립 확인UNKNOWNACCEPT
4 (Client Hello)TLS SNI 추출TLS (SNI 확인중)ACCEPT
5 (Server Hello)서버 인증서/프로토콜 분석HTTPS (example.com)ACCEPT
6~ (Application Data)분류 완료, IPS 시그니처 검사CLASSIFIEDACCEPT → 오프로드 가능

일반적으로 3~10개 패킷이면 App-ID 분류가 완료됩니다. TLS 1.3에서 Encrypted Client Hello(ECH)가 사용되면 SNI가 암호화되어 더 많은 패킷이 필요하거나, SSL 복호화 없이는 분류가 불가능합니다.

ESTABLISHED 전환

TCP 3-way handshake가 완료되면 conntrack 상태가 ESTABLISHED로 전환됩니다. 이 시점에서 오프로드 여부를 결정합니다.

오프로드 결정 기준 4가지:

  1. DPI 분류 완료 — App-ID가 결정되고 ALLOW verdict가 나왔는가?
  2. ALG 프로토콜 아닌가 — FTP/SIP/H.323 등 동적 포트 할당이 필요한 프로토콜은 오프로드 불가
  3. IP 단편화 아닌가 — 단편화된 패킷 스트림은 오프로드 불가
  4. HW 지원 여부 — NIC/SmartNIC이 해당 플로우의 오프로드를 지원하는가? (터널 타입, NAT 유형 등)

오프로드 등록 커널 코드

nftables에서 flow add @ft가 실행되면 내부적으로 다음이 호출됩니다:

/* net/netfilter/nft_flow_offload.c */
static void nft_flow_offload_eval(const struct nft_expr *expr,
                                   struct nft_regs *regs,
                                   const struct nft_pktinfo *pkt)
{
    struct nf_conn *ct;
    enum ip_conntrack_info ctinfo;

    ct = nf_ct_get(pkt->skb, &ctinfo);

    /* 오프로드 가능 조건 확인 */
    if (nf_ct_is_dying(ct))
        goto err;
    if (nf_ct_helper(ct))        /* ALG helper 있으면 불가 */
        goto err;

    /* flow_offload 구조체 생성 */
    struct flow_offload *flow = flow_offload_alloc(ct);

    /* 라우팅 캐시 설정 */
    flow_offload_route_init(flow, &route);

    /* flowtable 해시에 등록 */
    flow_offload_add(&ft->ft, flow);

    /* HW offload 플래그가 있으면 NIC에도 등록 */
    if (ft->ft.flags & NF_FLOWTABLE_HW_OFFLOAD)
        nf_flow_offload_hw_add(net, flow, ct);
        /* → TC flower ct 규칙 → NIC eSwitch FDB 삽입 */
}

nf_flow_offload_hw_add()는 내부적으로 TC flower API를 호출하여 eSwitch에 FDB 규칙을 삽입합니다. 이 과정은 워크큐에서 비동기적으로 수행되므로, HW 규칙 설치까지 수 밀리초의 지연이 발생할 수 있습니다. 이 사이에 도착하는 패킷은 SW flowtable에서 처리됩니다.

오프로드 결정 트리

세션 오프로드 결정 트리 패킷 도착 conntrack ESTABLISHED? Slow Path (전체 검사) No DPI verdict = ALLOW? Yes DROP 또는 계속 검사 No ALG/Fragment 프로토콜? Yes SW Slow Path 유지 Yes SmartNIC HW 지원? No HW Offload Yes SW Offload (flowtable) No
conntrack 상태DPI 결과ALGNIC HW 지원오프로드 결과
NEW미분류--Slow Path (전체 검사)
ESTABLISHEDALLOWNoYesHW Offload (eSwitch FDB)
ESTABLISHEDALLOWNoNoSW Offload (flowtable)
ESTABLISHEDALLOWYes (FTP/SIP)-Slow Path 유지 (ALG 필요)
ESTABLISHEDDROP--즉시 DROP
ESTABLISHED미완료--Slow Path (DPI 계속)
RELATED-Yes-Slow Path (헬퍼 추적)
INVALID---DROP (기본 정책)
NGFW 세션 오프로드 상태 머신 NEW Slow Path (전체 검사) DPI_ANALYZING NFQUEUE → App-ID 분류중 CLASSIFIED DPI ALLOW → 오프로드 대기 SW_OFFLOADED flowtable (커널 Fast Path) HW_OFFLOADED eSwitch FDB (NIC Fast Path) TEARDOWN GC 대기 → 리소스 해제 DROPPED RECHECK 주기적 재검사 (샘플링) SYN → conntrack NEW App-ID 완료 + ALLOW DPI DROP flow add @ft NIC HW 지원 → FDB 설치 TCP FIN/RST FIN/RST/timeout 바이트 임계치 초과 ALLOW 재검사 DROP → TEARDOWN Slow Path DPI 처리중 Fast Path (오프로드) 종료/차단 주기적 샘플링 경로

오프로드 해제

오프로드된 세션은 다음 상황에서 해제됩니다:

  1. TCP FIN/RST — 연결 종료 신호가 감지되면 flowtable에서 DYING 상태로 전환
  2. GC 타이머(Timer)nf_flow_offload_gc_step()이 주기적으로 만료된 엔트리 정리
  3. HW rule 삭제nf_flow_offload_hw_del()이 eSwitch FDB 규칙을 제거
  4. conntrack 삭제 — 관련 conntrack 엔트리도 정리하여 리소스 해제
/* flowtable 오프로드 해제 흐름 */
TCP FIN/RST 수신
  → flow_offload_teardown()       /* FLOW_OFFLOAD_TEARDOWN 플래그 설정 */
    → nf_flow_offload_gc_step()   /* GC 워크큐가 DYING 플로우 정리 */
      → nf_flow_table_offload_del() /* HW rule 삭제 (TC flower del) */
        → nf_ct_delete()          /* conntrack 엔트리 삭제 */

GC 메커니즘 상세

flowtable의 Garbage Collection은 두 가지 메커니즘으로 동작합니다:

GC 유형트리거동작지연
Passive GC패킷 도착 시 flow_offload_stale_flow() 확인stale 플로우 감지 → Slow Path 복귀즉시 (패킷 기반)
Active GC워크큐가 주기적 실행 (nf_flow_offload_work)만료된 플로우 정리 + HW rule 삭제1초 주기
Forced GCconntrack destroy 이벤트conntrack 삭제 시 연관 플로우 즉시 정리즉시

HW 카운터 동기화: HW offload된 플로우가 삭제될 때, NIC에서 처리된 패킷/바이트 카운터를 SW 카운터에 동기화합니다. 이를 통해 conntrack -L이나 nft list counter에서 정확한 통계를 확인할 수 있습니다.

/* HW 카운터 동기화 (net/netfilter/nf_flow_table_offload.c) */
static void nf_flow_offload_stats(struct flow_offload *flow,
                                    struct flow_stats *stats)
{
    struct nf_conn_acct *acct = nf_conn_acct_find(flow->ct);

    /* HW에서 읽어온 패킷/바이트 카운터를 conntrack에 반영 */
    atomic64_add(stats[0].pkts, &acct->counter[IP_CT_DIR_ORIGINAL].packets);
    atomic64_add(stats[0].bytes, &acct->counter[IP_CT_DIR_ORIGINAL].bytes);
    atomic64_add(stats[1].pkts, &acct->counter[IP_CT_DIR_REPLY].packets);
    atomic64_add(stats[1].bytes, &acct->counter[IP_CT_DIR_REPLY].bytes);

    /* 타임스탬프 갱신 → GC 타임아웃 리셋 */
    flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
}
타임아웃과 GC의 상호작용: HW offload된 플로우는 NIC에서 패킷 카운터가 주기적으로 SW에 보고됩니다. 이 보고가 있는 한 플로우의 타임아웃이 갱신되어 GC 대상이 되지 않습니다. NIC 보고 주기(보통 1초)보다 짧은 타임아웃을 설정하면 활성 플로우가 불필요하게 정리될 수 있으므로, nf_flowtable_tcp_timeout은 최소 30초 이상으로 설정해야 합니다.

Stateful 방화벽 오프로드

ACL HW 오프로드

TC flower를 사용하여 ct_state 매칭과 함께 ACL 규칙을 eSwitch에 설치할 수 있습니다. 이를 통해 conntrack 상태 기반 방화벽 규칙이 하드웨어에서 직접 평가됩니다.

# eSwitch switchdev 모드에서 TC flower ct 규칙 예시
# 1. ct zone 설정 및 conntrack 추적 시작
tc filter add dev eth0_rep0 ingress prio 1 \
  protocol ip flower \
  ct_state -trk \
  action ct zone 1

# 2. ESTABLISHED+TRACKED 세션 → HW offload forward
tc filter add dev eth0_rep0 ingress prio 2 \
  protocol ip flower \
  ct_state +trk+est \
  action ct zone 1 \
  action mirred egress redirect dev eth1_rep0

# 3. NEW+TRACKED 세션 → CPU (Slow Path)
tc filter add dev eth0_rep0 ingress prio 3 \
  protocol ip flower \
  ct_state +trk+new \
  action pass # CPU로 전달하여 전체 검사

# 4. INVALID → DROP
tc filter add dev eth0_rep0 ingress prio 4 \
  protocol ip flower \
  ct_state +trk+inv \
  action drop
코드 설명
  • 3-5행 아직 conntrack에 의해 추적되지 않은(-trk) 패킷에 대해 ct zone 1에서 conntrack 추적을 시작합니다.
  • 8-12행 이미 추적되고 ESTABLISHED 상태인 패킷(+trk+est)을 하드웨어에서 직접 다른 representor 포트로 리다이렉트합니다. 이것이 HW Fast Path의 핵심입니다.
  • 15-18행 새로운 연결(+trk+new)은 pass로 CPU에 전달하여 nftables → NFQUEUE → DPI 전체 검사를 수행합니다.
  • 21-24행 INVALID 상태(+trk+inv) 패킷은 하드웨어에서 즉시 DROP합니다.

conntrack HW 오프로드

NF_FLOWTABLE_HW_OFFLOAD 플래그가 활성화되면, flowtable에 등록된 플로우가 NIC 하드웨어의 conntrack 테이블에도 설치됩니다.

# flowtable HW offload 활성화
nft add flowtable inet filter ft \
  { hook ingress priority 0\; devices = { eth0, eth1 }\; \
    flags offload\; }

# forward chain에서 established 세션을 flowtable으로 등록
nft add rule inet filter forward \
  ct state established \
  flow add @ft

# 오프로드 상태 실시간 확인
conntrack -L --status OFFLOAD
# 출력 예:
# tcp  6 300 ESTABLISHED src=10.0.0.1 dst=192.168.1.1
#   sport=45678 dport=443 [OFFLOAD] mark=0 use=2

HW offload 내부 메커니즘

flowtable HW offload는 다음 과정으로 NIC에 규칙을 설치합니다:

/* HW offload 규칙 설치 흐름 */
nf_flow_offload_hw_add()
  → nf_flow_offload_tuple()
    → flow_offload_mangle()      /* NAT rewrite 액션 구성 */
    → flow_action_entry_set()    /* TC flow_action 구조체 채움 */
  → nf_flow_table_offload_add()
    → flow_block_cb()            /* NIC 드라이버 콜백 호출 */
      → mlx5e_tc_offload_fdb_rules()  /* mlx5: FDB rule 삽입 */
      → ice_tc_flower_action()         /* ice: TC flower 규칙 */

NIC 드라이버는 FLOW_BLOCK_BIND/FLOW_BLOCK_UNBIND 이벤트를 통해 flowtable과 연결됩니다. 드라이버가 지원하지 않는 플로우 타입(예: 특수 NAT, 미지원 터널)에 대해서는 -EOPNOTSUPP를 반환하고, 이 경우 SW flowtable에서만 처리됩니다.

HW conntrack의 한계:

conntrack HW offload 호환성 매트릭스

기능NVIDIA CX-6 DxNVIDIA CX-7Intel E810Broadcom P2100
CT offload (TCP)지원지원지원지원
CT offload (UDP)지원지원지원지원
CT offload (IPv6)지원지원제한적미지원
CT zone 지원지원지원제한적미지원
CT NAT actionSNAT/DNATSNAT/DNATSNAT/DNATDNAT만
CT mark action지원지원미지원미지원
최대 HW flow 엔트리~1M~4M~64K~128K
flowtable HW offload지원지원지원 (5.15+)미지원

NAT 오프로드

SNAT/DNAT 주소 변환은 flowtable과 eSwitch 모두에서 오프로드할 수 있습니다. (NAT 아키텍처 참고)

기능eSwitch HWflowtable SW비고
SNAT (Source NAT)지원지원NF_FLOW_SNAT 플래그
DNAT (Destination NAT)지원지원NF_FLOW_DNAT 플래그
MASQUERADE제한적지원인터페이스 주소 변경 시 flush 필요
CGNAT (Large-scale NAT)NIC 의존지원포트 범위 제한 시 SW 폴백
1:1 NAT지원지원가장 효율적인 HW offload 대상
Port Forwarding (REDIRECT)지원지원단일 목적지 DNAT
NAT64/NAT46미지원제한적IPv6↔IPv4 변환은 주로 SW
conntrack 기반 NAT지원지원CT action에서 NAT 정보 전달

NAT 오프로드의 커널 구현

flowtable NAT offload는 conntrack의 NAT 정보를 flow_offload 구조체에 복사하여, 이후 패킷을 conntrack 없이 직접 변환합니다:

/* net/netfilter/nf_flow_table_ip.c - NAT 오프로드 적용 */
static int nf_flow_nat_ip(const struct flow_offload *flow,
                           struct sk_buff *skb,
                           unsigned int thoff,
                           enum flow_offload_tuple_dir dir)
{
    struct iphdr *iph = ip_hdr(skb);

    /* SNAT: 소스 IP/포트 교체 */
    if (flow->flags & FLOW_OFFLOAD_SNAT) {
        /* ORIGINAL 방향: src → NAT 주소로 변경 */
        /* REPLY 방향: dst → 원래 주소로 복원 */
        nf_flow_snat_port(skb, thoff,
            flow->tuplehash[!dir].tuple.src_v4.s_addr,
            flow->tuplehash[!dir].tuple.port.src);
        /* IP 체크섬 + L4 체크섬 재계산 */
        csum_replace4(&iph->check, iph->saddr, new_addr);
    }

    /* DNAT: 목적지 IP/포트 교체 (위와 유사) */
    if (flow->flags & FLOW_OFFLOAD_DNAT)
        nf_flow_dnat_port(skb, thoff, ...);

    return 0;
}

CGNAT 대규모 NAT 시나리오

통신사(ISP) 환경의 CGNAT(Carrier-Grade NAT)에서는 수만 개의 내부 IP를 소수의 공인 IP로 변환합니다. 이 경우:

# CGNAT nftables 설정 예시
table ip cgnat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;

        # 내부 대역별 공인 IP 분배 (Deterministic NAT)
        ip saddr 100.64.0.0/24 snat to 203.0.113.1:1024-32767
        ip saddr 100.64.1.0/24 snat to 203.0.113.1:32768-65535
        ip saddr 100.64.2.0/24 snat to 203.0.113.2:1024-32767

        # 폴백: 나머지 → 공인 IP 풀에서 동적 할당
        ip saddr 100.64.0.0/10 snat to 203.0.113.1-203.0.113.10
    }
}

# CGNAT 세션도 flowtable 오프로드 적용
nft add rule ip cgnat forward \
  ct state established flow add @ft

QoS/터널/IPSec 오프로드

DSCP/QoS 오프로드

TC flower로 DSCP 필드를 매칭하고 QoS 큐에 매핑하는 규칙을 eSwitch에 설치할 수 있습니다.

# DSCP EF (46) → TC 큐 0 (높은 우선순위)
tc filter add dev eth0_rep0 ingress prio 1 \
  protocol ip flower \
  ip_tos 0xb8/0xfc \
  action skbedit priority 0

# DSCP AF11 (10) → TC 큐 2 (낮은 우선순위)
tc filter add dev eth0_rep0 ingress prio 2 \
  protocol ip flower \
  ip_tos 0x28/0xfc \
  action skbedit priority 2

DSCP/QoS 매핑 상세

NGFW에서 QoS는 보안 정책과 연계됩니다. DPI 결과(App-ID)에 따라 DSCP 값을 재마킹하고, HW QoS 큐에 매핑하는 패턴입니다:

DSCP 클래스IP ToS 바이트용도HW 큐 매핑
EF (Expedited Forwarding)460xB8VoIP, 실시간 미디어TC 0 (strict priority)
AF41340x88화상회의, 인터랙티브TC 1
AF31260x68스트리밍 비디오TC 2
AF21180x48주요 비즈니스 앱TC 3
AF11100x28일반 트래픽TC 4 (WRR)
BE (Best Effort)00x00기본 트래픽TC 5 (WRR)
CS1 (Scavenger)80x20백업, 대용량 전송TC 6 (lowest)
# NGFW에서 DPI 결과 기반 DSCP 재마킹
# nftables에서 App-ID → DSCP 매핑 (DPI 엔진이 ct mark에 App-ID 기록)
table inet qos_mark {
    map app_dscp {
        type mark : verdict
        elements = {
            0x0001 : accept,    # VoIP → DSCP EF (DPI에서 이미 마킹)
            0x0002 : accept,    # Video → DSCP AF41
            0x0003 : accept,    # Web → DSCP AF11
        }
    }

    chain forward {
        type filter hook forward priority 50; policy accept;
        # DPI 엔진이 ct mark에 기록한 App-ID → DSCP 재마킹
        ct mark 0x0001 ip dscp set ef
        ct mark 0x0002 ip dscp set af41
        ct mark 0x0003 ip dscp set af11
    }
}

# HW QoS 큐 설정 (TC MQPRIO)
tc qdisc add dev eth0 root mqprio \
  num_tc 4 map 3 3 2 2 1 1 0 0 0 0 0 0 0 0 0 0 \
  queues 1@0 1@1 2@2 4@4 hw 1

터널 오프로드

NGFW에서 터널은 두 가지 역할을 합니다: 사이트 간 VPN오버레이(Overlay) 네트워크. eSwitch는 다음 터널 타입의 encap/decap을 하드웨어에서 수행합니다:

터널 + NGFW 오프로드 결합

터널 decap → 내부 패킷 DPI → 오프로드의 전체 흐름을 TC flower로 구성합니다:

# VXLAN 터널 디바이스 생성
ip link add vxlan0 type vxlan id 100 \
  local 10.0.0.1 dport 4789 nolearning external

# eSwitch에서 VXLAN decap + conntrack + forward 규칙
# chain 0: 외부 헤더로 VXLAN 매칭 → decap
tc filter add dev eth0_rep0 ingress chain 0 prio 1 \
  protocol ip flower \
  enc_dst_ip 10.0.0.1 enc_dst_port 4789 enc_key_id 100 \
  action tunnel_key unset pipe \
  action goto chain 1

# chain 1: decap된 내부 패킷에 conntrack 적용
tc filter add dev eth0_rep0 ingress chain 1 prio 1 \
  protocol ip flower ct_state -trk \
  action ct zone 1 pipe \
  action goto chain 2

# chain 2: EST → HW forward, NEW → CPU
tc filter add dev eth0_rep0 ingress chain 2 prio 1 \
  protocol ip flower ct_state +trk+est \
  action ct zone 1 nat pipe \
  action mirred egress redirect dev eth1_rep0

tc filter add dev eth0_rep0 ingress chain 2 prio 2 \
  protocol ip flower ct_state +trk+new \
  action pass # CPU → nftables → NFQUEUE → DPI

IPSec 인라인 크립토 오프로드

IPSec & xfrm의 HW 오프로드를 NGFW 파이프라인에 통합하면, 암호화/복호화를 NIC에서 수행하고 평문 패킷만 DPI 엔진에 전달할 수 있습니다.

# IPSec crypto offload 활성화 (xfrm)
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
  proto esp spi 0x1001 reqid 1 mode tunnel \
  enc 'aes' 0x$(head -c 16 /dev/urandom | xxd -p) \
  offload dev eth0 dir out

IPSec 오프로드 모드 비교

모드암호화ESP 헤더라우팅성능NIC 요구사항
Full SWCPUCPUCPU1~5 Gbps/core없음
Crypto offloadNICCPUCPU10~25 Gbpsinline crypto 지원
Packet offloadNICNICCPU25~50 Gbpspacket offload 지원
Full offloadNICNICNIC50~100 GbpseSwitch + xfrm full offload

NGFW와의 통합 포인트: IPSec 수신 시 NIC이 복호화를 수행하고, 평문(decrypted) 패킷이 커널에 전달됩니다. 이 평문 패킷에 대해 conntrack → flowtable → DPI 파이프라인이 정상 작동합니다. 송신 시에는 flowtable이 평문 패킷을 NIC에 전달하고, NIC이 ESP 캡슐화와 암호화를 인라인으로 수행합니다.

# IPSec + flowtable NGFW 조합 설정
# 1. xfrm SA에 crypto offload 설정
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
  proto esp spi 0x1001 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x$(head -c 20 /dev/urandom | xxd -p) 128 \
  offload crypto dev eth0 dir out

ip xfrm state add src 10.0.0.2 dst 10.0.0.1 \
  proto esp spi 0x1002 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x$(head -c 20 /dev/urandom | xxd -p) 128 \
  offload crypto dev eth0 dir in

# 2. xfrm 정책
ip xfrm policy add src 10.1.0.0/24 dst 10.2.0.0/24 \
  dir out tmpl src 10.0.0.1 dst 10.0.0.2 \
  proto esp reqid 1 mode tunnel

# 3. flowtable에서 decrypted 패킷 오프로드
nft add flowtable inet ngfw ft_ipsec \
  { hook ingress priority 0\; devices = { eth0 }\; flags offload\; }

nft add rule inet ngfw forward \
  ct state established \
  ipsec in reqid 1 \
  flow add @ft_ipsec accept

# 확인: IPSec HW 오프로드 상태
ip xfrm state show | grep -A1 offload
ethtool -S eth0 | grep ipsec

NGFW에서 VXLAN 오버레이 + 보안 통합

데이터센터 NGFW에서 VXLAN 오버레이 네트워크와 보안 검사를 통합하는 아키텍처입니다. eSwitch가 VXLAN 터널의 encap/decap을 하드웨어에서 수행하고, 내부 패킷에 대해 conntrack + DPI를 적용합니다.

# VXLAN + NGFW 통합 구성 (eSwitch offload)

# 1. VXLAN 터널 엔드포인트 생성
ip link add vxlan100 type vxlan id 100 \
  local 10.0.0.1 dport 4789 nolearning external

# 2. nftables에서 decap된 내부 트래픽에 NGFW 정책 적용
table inet vxlan_ngfw {
    flowtable ft_vxlan {
        hook ingress priority 0
        devices = { vxlan100, eth1 }
        flags offload
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
        ct state invalid drop

        # VXLAN 내부 트래픽: EST → offload
        iifname "vxlan100" ct state established,related \
            flow add @ft_vxlan accept

        # VXLAN 내부 트래픽: NEW → DPI
        iifname "vxlan100" ct state new \
            queue num 0-3 fanout

        # 내부 → VXLAN: EST → offload
        oifname "vxlan100" ct state established,related \
            flow add @ft_vxlan accept
    }
}

# 3. eSwitch에서 VXLAN + conntrack 통합 규칙
# 외부 헤더로 VXLAN 패킷 식별 → decap → conntrack → forward
tc filter add dev eth0_rep0 ingress chain 0 prio 1 \
  protocol ip flower \
  enc_dst_ip 10.0.0.1 enc_dst_port 4789 enc_key_id 100 \
  action tunnel_key unset pipe \
  action ct zone 2 pipe \
  action goto chain 1

# chain 1에서 EST/NEW 분기 (위 §8 패턴과 동일)
tc filter add dev eth0_rep0 ingress chain 1 prio 1 \
  protocol ip flower ct_state +trk+est \
  action ct zone 2 nat pipe \
  action mirred egress redirect dev eth1_rep0

tc filter add dev eth0_rep0 ingress chain 1 prio 2 \
  protocol ip flower ct_state +trk+new \
  action pass
VXLAN offload의 성능 효과: eSwitch가 VXLAN decap을 HW에서 수행하면, 내부 패킷의 conntrack + flowtable offload가 자연스럽게 동작합니다. VXLAN encap/decap의 CPU 오버헤드(패킷당 ~200ns)를 완전히 제거할 수 있으며, 이는 소규모 패킷에서 특히 큰 성능 차이를 만듭니다.
IPSec + 터널 + QoS 통합 파이프라인 Ingress (수신) NIC RX IPSec Decrypt (HW crypto) Tunnel Decap VXLAN/GRE/Geneve NAT (DNAT) ACL/DPI QoS 분류 내부 전달 Egress (송신) 내부 출발 ACL NAT (SNAT) QoS 마킹 Tunnel Encap VXLAN/GRE/Geneve IPSec Encrypt (HW crypto) NIC TX SmartNIC/DPU HW Offload 범위 (IPSec + Tunnel + NAT + QoS) CPU 필요 (DPI)
터널 타입NVIDIA ConnectX-6+Intel E810Fortinet NP7Linux SW
VXLANHW encap/decapHW encap/decapHW encap/decap지원
GREHW encap/decapSWHW encap/decap지원
GeneveHW encap/decapHW encap/decap제한적지원
IPSec ESPinline cryptoinline cryptoNP7 내장xfrm SW
WireGuard미지원미지원미지원커널 SW
L2TP미지원미지원HW지원
MPLSHW push/pop미지원HW지원

GTP-U 오프로드와 5G NGFW

5G 모바일 네트워크에서 사용자 트래픽은 GTP-U(GPRS Tunnelling Protocol User Plane)로 캡슐화되어 전송됩니다. NGFW가 5G 환경에 배치되면 GTP-U 터널 내부의 실제 사용자 트래픽을 검사해야 하며, 이때 GTP-U 디캡슐레이션(Decapsulation)과 내부 패킷 검사를 SmartNIC 하드웨어에서 오프로드하면 처리량을 극대화할 수 있습니다. 이 섹션에서는 GTP-U 프로토콜 구조, 커널 GTP 모듈, TC flower 연동, HW 오프로드 구현을 다룹니다.

GTP-U 프로토콜 구조

GTP-U(GPRS Tunnelling Protocol - User Plane)는 3GPP 표준(TS 29.281)에 정의된 터널링 프로토콜로, 모바일 네트워크에서 사용자 데이터 패킷을 캡슐화하여 네트워크 노드 간에 전달합니다. GTP-U는 UDP 포트 2152 위에서 동작하며, 핵심 식별자는 TEID(Tunnel Endpoint Identifier)입니다.

GTP-U 헤더 형식

비트필드크기설명
0~2Version3비트프로토콜 버전 (GTP-U = 1)
3PT (Protocol Type)1비트1 = GTP, 0 = GTP' (과금)
4Reserved1비트예약 (0)
5E (Extension Header)1비트확장 헤더 존재 여부
6S (Sequence Number)1비트시퀀스 번호 존재 여부
7PN (N-PDU Number)1비트N-PDU 번호 존재 여부
8~15Message Type8비트0xFF = T-PDU (사용자 데이터)
16~31Length16비트TEID 이후 페이로드 길이
32~63TEID32비트터널 엔드포인트 식별자 (세션 ID)
64~79Sequence Number16비트옵션 (S=1일 때)
80~87N-PDU Number8비트옵션 (PN=1일 때)
88~95Next Extension Header8비트옵션 (E=1일 때)
최소 GTP-U 헤더: E=S=PN=0일 때 최소 헤더 크기는 8바이트입니다. E, S, PN 중 하나라도 1이면 4바이트가 추가되어 12바이트가 됩니다. 5G에서는 QFI(QoS Flow Identifier) 전달을 위해 확장 헤더(PDU Session Container)를 사용하므로, 실제 GTP-U 헤더는 대부분 12바이트 이상입니다.

GTP-U 캡슐화 스택

GTP-U로 캡슐화된 패킷의 전체 프로토콜 스택은 다음과 같습니다:

┌─────────────────────────────────────────────────────────────────────┐
│ Outer Ethernet │ Outer IP │ UDP(2152) │ GTP-U │ Inner IP │ Payload │
├────────────────┼──────────┼───────────┼───────┼──────────┼─────────┤
│    14 bytes    │ 20 bytes │  8 bytes  │ 8~12B │ 20 bytes │  ...    │
└────────────────┴──────────┴───────────┴───────┴──────────┴─────────┘
                                         
총 오버헤드: 14 + 20 + 8 + 8(~12) = 50~54 bytes (Inner Ethernet 없음)
1500B MTU 기준 실효 페이로드: 1446~1450 bytes
레이어프로토콜크기역할
L2 OuterEthernet14B물리 네트워크 전달
L3 OuterIPv4/IPv620/40BgNB ↔ UPF 간 라우팅
L4 OuterUDP (dst 2152)8BGTP-U 전송 계층
TunnelGTP-U Header8~12BTEID로 사용자 세션 식별
L3 InnerIPv4/IPv620/40B사용자 원본 IP (UE의 실제 IP)
L4 InnerTCP/UDP20/8B사용자 원본 전송 계층
PayloadApplication Data가변사용자 실제 데이터 (DPI 검사 대상)

모바일 네트워크에서 NGFW 배치 위치

5G 네트워크 아키텍처(3GPP TS 23.501)에서 NGFW는 주로 N3 인터페이스(gNB ↔ UPF)와 N6 인터페이스(UPF ↔ Data Network) 두 위치에 배치됩니다.

5G 아키텍처 개요

5G 데이터 플레인 경로:

  UE ──[무선]──→ gNB ──[N3: GTP-U]──→ UPF ──[N6: IP]──→ DN (Internet)
                  │                     │
                  │   ┌──[N9: GTP-U]──┐ │
                  │   │  (UPF 간 중계)  │ │
                  │   └───────────────┘ │
                  │                     │
              ┌───┴───────────────┐   ┌─┴──────────┐
              │  NGFW 위치 A      │   │ NGFW 위치 B │
              │  (N3 인라인)       │   │ (N6 이그레스)│
              │  GTP-U 내부 검사  │   │ 일반 IP 검사 │
              └───────────────────┘   └────────────┘
배치 위치인터페이스트래픽 형태NGFW 요구사항오프로드 방식
위치 A: N3 인라인gNB ↔ UPF 사이GTP-U 캡슐화GTP-U decap 후 inner 패킷 DPIGTP-U HW decap + CT + ACL
위치 B: N6 이그레스UPF ↔ DN 사이일반 IP (디캡슐 후)일반 L3/L4 검사 + DPI표준 flowtable + TC flower
위치 C: N9 중계UPF ↔ UPF 사이GTP-U (재캡슐화)inter-UPF 트래픽 검사이중 GTP-U decap/encap

N3 인라인 배치 시 트래픽 패턴

N3 인터페이스에 NGFW를 배치하면 모든 사용자 트래픽이 GTP-U로 캡슐화된 상태로 통과합니다. NGFW는 다음과 같은 처리를 수행해야 합니다:

성능 도전과제: 5G UPF 하나가 처리하는 가입자 세션 수는 10만~100만에 달합니다. 각 세션의 첫 패킷이 Slow Path를 거쳐야 하므로 CPS(Connections Per Second)가 매우 높아야 합니다. 또한 GTP-U decap/encap 오버헤드까지 더해지면, SW 전용 NGFW로는 100Gbps 이상의 처리량을 달성하기 어렵습니다.

N6 이그레스 배치 시 장단점

N6 인터페이스에서는 UPF가 이미 GTP-U 디캡슐레이션을 완료했으므로, NGFW는 일반 IP 패킷을 처리합니다. 이 경우 GTP-U 처리 오버헤드가 없어 기존 NGFW 파이프라인을 그대로 사용할 수 있지만, TEID 기반 가입자 식별이 불가능하다는 단점이 있습니다. 가입자별 정책(Per-Subscriber Policy)을 적용하려면 UPF가 내부 IP에 DSCP 마킹이나 VLAN 태그로 가입자 정보를 전달해야 합니다.

커널 GTP 모듈과 TC flower 연동

Linux 커널은 gtp.ko 모듈을 통해 GTP-U 터널 인터페이스를 제공합니다. 이 모듈은 커널 4.7부터 포함되어 있으며, Open5GS, free5GC 등 오픈소스 5G 코어에서 UPF 구현에 사용됩니다.

gtp.ko 모듈 아키텍처

# GTP 커널 모듈 로드
modprobe gtp

# GTP 터널 인터페이스 생성 (libgtpnl 사용)
# gtp-link 명령은 genl(generic netlink) 기반
ip link add gtp0 type gtp role sgsn hashsize 131072

# 또는 gtp_newlink netlink API로 직접 생성
# (Open5GS UPF가 내부적으로 사용하는 방식)

# GTP 인터페이스 상태 확인
ip link show gtp0
ip addr add 10.45.0.1/16 dev gtp0
ip link set gtp0 up

# GTP 터널 세션(PDP context) 추가
# TEID 0x12345678, peer 192.168.1.100 (gNB IP)
gtp-tunnel add gtp0 v1 12345678 192.168.1.100 10.45.0.2
/* drivers/net/gtp.c - GTP-U 수신 처리 */
static int gtp1u_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
{
    struct gtphdr *gtp1;
    struct pdp_ctx *pctx;

    /* GTP-U 헤더 파싱 */
    gtp1 = (struct gtphdr *)(skb->data + sizeof(struct udphdr));
    
    if ((gtp1->flags >> 5) != GTP_V1)
        return 1;  /* not GTPv1 */
    
    if (gtp1->type != GTP_TPDU)
        return 1;  /* not T-PDU (user data) */

    /* TEID로 PDP context (세션) 조회 */
    pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid));
    if (!pctx)
        return -1;  /* unknown TEID */

    /* outer 헤더 제거, inner IP 패킷 노출 */
    skb_pull(skb, hdrlen);
    
    /* inner 패킷을 GTP 인터페이스(gtp0)로 수신 처리 */
    skb->dev = gtp->dev;
    netif_rx(skb);
    return 0;
}

TC flower로 GTP-U 매칭

커널 5.7부터 TC flower는 enc_key_id 필드로 GTP-U의 TEID를 매칭할 수 있습니다. 이를 통해 특정 TEID(가입자 세션)에 대한 정책을 TC flower 규칙으로 설정할 수 있습니다.

# TC flower로 GTP-U TEID 매칭
# enc_key_id = TEID (tunnel key)

# 1. GTP-U 터널의 특정 TEID에 대한 트래픽 미러링
tc filter add dev eth0 ingress protocol ip \
    flower \
    enc_key_id 0x12345678 \
    enc_dst_port 2152 \
    action mirred egress mirror dev mon0

# 2. 특정 TEID의 inner IP 기반 ACL
tc filter add dev eth0 ingress protocol ip \
    flower \
    enc_key_id 0x12345678 \
    enc_dst_port 2152 \
    enc_src_ip 192.168.1.100 \
    ip_proto tcp \
    dst_port 443 \
    action pass

# 3. tunnel_key 액션으로 GTP-U decap
tc filter add dev eth0 ingress protocol ip \
    flower \
    enc_dst_port 2152 \
    action tunnel_key unset \
    action mirred egress redirect dev gtp_decap0

# 4. 결합: GTP decap + conntrack + NAT
tc filter add dev eth0 ingress protocol ip \
    flower \
    enc_dst_port 2152 \
    enc_key_id 0x12345678 \
    action tunnel_key unset \
    action ct zone 100 \
    action ct commit zone 100 nat src addr 203.0.113.1 \
    action mirred egress redirect dev eth1
inner + outer 동시 매칭: TC flower는 enc_* 접두사로 외부(Outer) 헤더 필드를, 접두사 없는 필드로 내부(Inner) 헤더를 매칭합니다. 예를 들어 enc_key_id 0x12345678 dst_ip 10.0.0.1은 "TEID가 0x12345678이고 내부 목적지 IP가 10.0.0.1인 패킷"을 의미합니다. 이를 통해 TEID(가입자) + 내부 서비스(목적지) 조합으로 세밀한 정책을 설정할 수 있습니다.

GTP-U HW 오프로드 구현

NVIDIA ConnectX-7(BlueField-3)은 GTP-U 하드웨어 디캡슐레이션을 지원하는 대표적인 SmartNIC입니다. GTP-U decap을 TC flower와 결합하면 디캡슐레이션, conntrack, NAT, ACL을 단일 HW 파이프라인에서 처리할 수 있습니다.

NVIDIA ConnectX-7 GTP-U 오프로드

# ConnectX-7 eSwitch 모드 설정
devlink dev eswitch set pci/0000:03:00.0 mode switchdev

# GTP-U decap offload 활성화
# representor 인터페이스에서 GTP-U 터널 매칭

# 1단계: GTP-U decap + inner 패킷 추출
tc filter add dev eth0_rep ingress protocol ip \
    flower \
    enc_dst_port 2152 \
    enc_key_id 0x12345678 \
    action tunnel_key unset pipe \
    action goto chain 1

# 2단계: chain 1에서 inner 패킷에 대해 conntrack
tc filter add dev eth0_rep ingress chain 1 protocol ip \
    flower \
    ct_state -trk \
    action ct zone 100 pipe \
    action goto chain 2

# 3단계: chain 2에서 ESTABLISHED 세션 offload
tc filter add dev eth0_rep ingress chain 2 protocol ip \
    flower \
    ct_state +trk+est \
    action ct commit zone 100 nat pipe \
    action tunnel_key set \
    id 0x87654321 \
    dst_ip 10.100.1.1 \
    dst_port 2152 \
    action mirred egress redirect dev eth1_rep

# NEW 세션은 SW로 (Slow Path)
tc filter add dev eth0_rep ingress chain 2 protocol ip \
    flower \
    ct_state +trk+new \
    action trap

위 규칙이 eSwitch FDB에 설치되면, 확립된 GTP-U 세션의 패킷은 다음 HW 파이프라인을 거칩니다:

ConnectX-7 HW 파이프라인 (GTP-U offload):

  NIC RX → TEID 매칭 → GTP-U decap → inner IP 추출
  → CT lookup (zone 100) → EST 매칭 → NAT rewrite
  → GTP-U encap (new TEID) → TX → Wire

  전체 과정이 NIC 하드웨어에서 완료 (CPU 개입 없음)
  지연(Latency): ~5μs (SW 경로 대비 1/100)

Stateful GTP 검사 파이프라인

완전한 5G NGFW HW 오프로드 파이프라인은 다음 요소를 결합합니다:

파이프라인 단계HW 처리SW 처리 (Slow Path만)TC flower 액션
GTP-U 디캡슐레이션tunnel_key unsetgtp.ko decapaction tunnel_key unset
TEID → 가입자 매핑enc_key_id 매칭PDP context 조회flower enc_key_id
Inner ACLeSwitch FDB 규칙nftables 규칙flower ip_proto dst_port
conntrackCT HW offloadnf_conntrackaction ct zone
NATHW NAT rewritenf_nataction ct commit nat
DPI/IPS불가 (SW only)NFQUEUE → Suricataaction trap (첫 패킷)
GTP-U 재캡슐레이션tunnel_key setgtp.ko encapaction tunnel_key set
QoS 마킹DSCP rewritetc-skbeditaction skbedit priority
DPI 한계: GTP-U HW 오프로드 환경에서도 DPI/IPS는 여전히 소프트웨어(Slow Path)에서만 수행됩니다. 새 세션의 첫 몇 패킷은 action trap으로 CPU에 전달되어 DPI 분류를 받은 후, ESTABLISHED + ALLOW 판정이 나면 HW offload로 전환됩니다. DPI가 지속적으로 필요한 트래픽(예: 스트리밍 DRM 검증)은 오프로드에서 제외해야 합니다.

5G NGFW 오프로드 성능 특성

5G NGFW 오프로드의 성능은 가입자 세션 밀도, GTP-U 오버헤드, 오프로드 비율에 따라 크게 달라집니다.

가입자 세션 밀도

5G UPF의 가입자 세션 규모는 다음과 같습니다:

배치 규모동시 가입자 세션동시 TEID 수CPS 요구량NGFW 요구 사양
소규모 (Edge)1만~5만2만~10만5K~20K10GbE SmartNIC 1개
중규모 (Regional)5만~50만10만~100만20K~100K25GbE SmartNIC 2개
대규모 (Central)50만~200만100만~400만100K~500K100GbE DPU 또는 전용 ASIC
TEID 수 = 가입자 × 2: 각 가입자 세션은 업링크(Uplink)와 다운링크(Downlink)에 별도의 TEID를 사용합니다. 또한 5G에서는 하나의 가입자가 여러 PDU 세션(예: 인터넷, IMS, IoT)을 동시에 유지할 수 있으므로, 실제 TEID 수는 가입자 수의 2~6배에 달할 수 있습니다.

GTP-U 오버헤드 분석

항목바이트비율 (1500B 기준)비고
Outer Ethernet14B0.9%L2 프레임 헤더
Outer IP (IPv4)20B1.3%IPv6이면 40B (2.7%)
Outer UDP8B0.5%dst port 2152
GTP-U 헤더 (최소)8B0.5%E=S=PN=0
GTP-U 헤더 (5G 확장)12~16B0.8~1.1%QFI 확장 헤더 포함
총 오버헤드 (IPv4, 최소)50B3.3%
총 오버헤드 (IPv6, 5G 확장)76B5.1%최악의 경우

SW 전용 vs HW 오프로드 성능 비교

측정 항목SW 전용
(gtp.ko + nftables)
HW 오프로드
(ConnectX-7 TC flower)
개선 비율
GTP-U decap 처리량12~18 Gbps100+ Gbps (라인 레이트)6~8×
GTP-U decap + conntrack8~14 Gbps100+ Gbps7~12×
GTP-U decap + CT + NAT6~10 Gbps100+ Gbps10~16×
GTP-U decap + DPI (Suricata)2~5 GbpsN/A (DPI는 SW only)-
패킷당 지연 (Latency)50~200 μs3~10 μs10~50×
CPU 사용률 (100Gbps)16+ 코어 (100%)0~2 코어 (EST 세션)8~16×
CPS (Slow Path)50K~200K50K~200K (변동 없음)1× (동일)
동시 오프로드 세션SW flowtable 한계1M~4M (eSwitch FDB)HW 테이블 크기
전력 소비200~400W (서버)15~25W (SmartNIC)10~20×
오프로드 비율의 영향: 5G 트래픽에서 동영상 스트리밍이 70% 이상을 차지합니다. 스트리밍 세션은 첫 DPI 분류 후 대부분 ESTABLISHED 상태가 유지되므로, 오프로드 비율이 80~90%에 달할 수 있습니다. 즉, 100Gbps 트래픽 중 80~90Gbps는 HW가, 10~20Gbps만 CPU가 처리하므로 SW 전용 대비 실효 처리량이 5~8배 향상됩니다.

오프로드 효과 분석

HW 오프로드의 효과는 트래픽 프로파일(Profile)에 따라 달라집니다:

처리량 모델 (100Gbps 환경):

  총 트래픽: 100 Gbps
  
  시나리오 1: 오프로드 비율 0% (SW 전용)
    CPU 필요: 100Gbps ÷ 10Gbps/코어 = 10코어 (GTP decap + CT + NAT)
    DPI 추가 시: 100Gbps ÷ 3Gbps/코어 = 33코어
    → 총 33+ CPU 코어 필요 (불가능에 가까움)

  시나리오 2: 오프로드 비율 80%
    HW 처리: 80 Gbps (CPU 부하 없음)
    SW 처리: 20 Gbps → 20 ÷ 10 = 2코어 (EST)
    DPI (새 세션만): ~5 Gbps → 5 ÷ 3 = 2코어
    → 총 4 CPU 코어로 100Gbps 처리 가능

  시나리오 3: 오프로드 비율 90%
    HW 처리: 90 Gbps
    SW 처리: 10 Gbps → 1코어 (EST) + 1코어 (DPI)
    → 총 2 CPU 코어로 100Gbps 처리 가능
5G NGFW — GTP-U HW 오프로드 토폴로지 UE 사용자 단말 gNB 기지국 무선 SmartNIC NGFW (N3 인라인) GTP-U Decap tunnel_key unset CT + NAT ct zone + nat ACL + QoS eSwitch FDB 규칙 HW Fast Path (EST 세션) DPI / IPS Suricata NFQUEUE App-ID L7 프로토콜 분류 오프로드 결정 ALLOW → HW 전환 SW Slow Path (NEW 세션) EST→HW N3 GTP-U UPF 사용자 플레인 DN Internet / 서비스 N6 IP HW Fast Path 패킷 흐름 (ESTABLISHED 세션) NIC RX TEID 매칭 GTP Decap CT Lookup NAT Rewrite GTP Encap NIC TX CPU 개입 없음 — 전체 HW 파이프라인 (~5μs 지연) SW Slow Path 패킷 흐름 (NEW 세션) NIC RX GTP Decap conntrack ACL DPI/IPS App-ID NAT GTP Encap NIC TX CPU 집약적 — 전체 SW 파이프라인 (~100μs 지연) ■ HW 처리 (SmartNIC) ■ SW 처리 (CPU) ■ DPI/IPS (항상 SW) ■ 5G 네트워크 노드 ■ 코어 네트워크

암/복호화 트래픽 HW 오프로드

NGFW에서 암호화 트래픽(Encrypted Traffic) 처리는 가장 CPU 집약적인 작업입니다. TLS 1.3 시대에 전체 웹 트래픽의 95% 이상이 암호화되어 있으며, NGFW는 이 트래픽을 복호화 → 검사(DPI/IPS) → 재암호화하거나, 암호화 상태로 메타데이터 기반 분류를 수행해야 합니다. 이 절에서는 NIC/SmartNIC/전용 ASIC에서 암·복호화를 하드웨어로 오프로드하는 모든 방식을 심층 분석합니다.

아키텍처 프레임: 이 절의 모든 암호화 오프로드 기술은 오프로드 아키텍처 3대 유형으로 분류됩니다. 각 기술이 어떤 아키텍처에 해당하는지를 아래 매핑 표에서 먼저 파악한 뒤, 개별 기술의 상세를 읽으면 전체 그림을 쉽게 이해할 수 있습니다.

암호화 기술별 아키텍처 매핑

NGFW에서 사용되는 주요 암호화 오프로드 기술을 3대 아키텍처로 분류하면 다음과 같습니다. 동일 프로토콜이라도 오프로드 모드에 따라 아키텍처가 달라집니다.

암호화 기술아키텍처 분류데이터 경로CPU 역할상세 섹션
kTLS HW TX/RX 인라인 (레코드) + CPU/Lookaside (핸드셰이크) NIC이 TLS 레코드 암·복호화 → 와이어 직접 처리 핸드셰이크(RSA/ECDHE)만, 레코드 0% kTLS 오프로드
IPSec Crypto offload CPU중심 Lookaside CPU(xfrm) → NIC(AES-GCM만) → CPU(ESP 헤더) ESP 파싱, SA 관리, 라우팅 전부 IPSec 모드
IPSec Packet offload 부분 인라인 NIC이 ESP 헤더 + AES-GCM + 시퀀스 번호 처리 SA 설정, 라우팅만 IPSec 모드
IPSec Full offload 완전 인라인 eSwitch: 복호화 → 포워딩 → 재암호화 (CPU bypass) SA 초기 설정만 IPSec 모드
MACsec HW offload 완전 인라인 NIC이 L2 프레임 암·복호화 (SecTAG + ICV) 키 교환(MKA)만 MACsec 오프로드
Intel QAT / NITROX CPU중심 Lookaside CPU → PCIe DMA → 가속기 → DMA → CPU 작업 제출/완료 관리, DMA 매핑 전용 크립토 가속기
NXP CAAM / OCTEON CPT SoC중심 Lookaside CPU → 내부 버스 → SoC 크립토 엔진 → 내부 버스 → CPU Job Ring 관리 SoC중심 Lookaside
SSL MITM Proxy CPU중심 (QAT로 핸드셰이크 가속 가능) CPU가 TLS 종단 → 평문 DPI → 재암호화 전체 (QAT는 핸드셰이크만 보조) SSL 검사 파이프라인

아키텍처별 암호화 알고리즘 지원 매트릭스

아키텍처 유형에 따라 지원하는 암호화 알고리즘 범위가 크게 다릅니다. 인라인 방식은 NIC ASIC에 고정된 알고리즘만 지원하고, Lookaside 방식은 가속기 펌웨어로 더 넓은 알고리즘을 지원하며, CPU SW는 커널 crypto API의 모든 알고리즘을 지원합니다.

알고리즘CPU (AES-NI/CE)CPU Lookaside (QAT)SoC Lookaside (CAAM)Inline NIC (CX-7)Inline NIC (E810)
AES-128-GCM지원지원지원지원지원
AES-256-GCM지원지원지원지원지원
AES-CBC + HMAC-SHA256지원지원지원미지원미지원
ChaCha20-Poly1305지원지원제한적미지원미지원
AES-CCM지원지원지원미지원미지원
RSA-2048/4096 (비대칭)지원지원 (140K ops/s)지원 (10K ops/s)미지원미지원
ECDHE P-256/P-384지원지원 (200K ops/s)지원 (20K ops/s)미지원미지원
Ed25519/X25519지원지원 (4xxx+)제한적미지원미지원
SHA-256/384/512지원 (SHA-NI)지원지원N/A (GCM 내장)N/A
3DES (레거시)지원지원지원미지원미지원
인라인 NIC의 알고리즘 제약: 인라인 방식의 NIC은 거의 모든 경우 AES-GCM만 지원합니다. 이는 ASIC에서 라인레이트 처리를 위해 고정 파이프라인으로 설계되기 때문입니다. ChaCha20-Poly1305, AES-CBC, 레거시 3DES 등은 인라인으로 처리할 수 없으며, 이러한 알고리즘이 필요한 세션은 CPU 또는 Lookaside 가속기로 폴백해야 합니다. TLS 1.3에서 AES-GCM이 사실상 표준이므로 대부분의 트래픽은 인라인으로 처리 가능하지만, TLS 1.2 레거시 세션이나 ChaCha20 선호 클라이언트(저전력 디바이스)는 예외입니다.

암호화 파이프라인 단계와 레이턴시

AES-256-GCM 암호화 한 패킷의 처리를 단계별로 분해하면, 각 아키텍처에서 병목이 되는 지점이 어디인지 명확해집니다. 아래 다이어그램은 1,400바이트 페이로드(일반 MTU) 기준의 처리 단계를 보여줍니다.

AES-256-GCM 패킷 암호화: 단계별 처리와 아키텍처별 레이턴시 처리 단계 ① 키 스케줄 AES 라운드 키 확장 ② IV/Nonce 생성 12바이트 nonce 구성 ③ AES-CTR 암호화 14라운드 × 88블록 (1,400B) ④ GHASH (인증) GF(2¹²⁸) 곱셈 × 88블록 ⑤ ICV 태그 출력 16바이트 인증 태그 아키텍처별 소요 시간 (1,400B 패킷 1개) CPU (AES-NI) 동기 처리 ①② ③④ AES-CTR + GHASH (파이프라인) ~0.15μs (CPU 점유 100%, DMA 없음) QAT (PCIe) 비동기 Lookaside DMA Tx HW ①②③④⑤ DMA Rx IRQ ~10-50μs (CPU 해방, PCIe 왕복 지연 포함) CAAM (SoC) SoC 내부 Lookaside JR HW ①②③④⑤ ~1-5μs (내부 버스, PCIe 없음) NIC Inline 인라인 (데이터 경로) 와이어 → HW ①②③④⑤ → 와이어 <1μs (CPU 0%, 호스트 메모리 0%) 패킷당 암호화 레이턴시 스펙트럼 <1μs Inline 1-5μs SoC 10-50μs PCIe Lookaside CPU 동기 (낮은 레이턴시, 코어 점유) 50-200μs SW 폴백 처리량 vs 레이턴시 트레이드오프 패킷당 레이턴시 → 처리량 → Inline 400Gbps <1μs SoC 100Gbps 1-5μs QAT 200Gbps 10-50μs CPU 8Gbps/core ~0.15μs CPU는 레이턴시는 낮지만 코어당 처리량이 제한적

핵심 인사이트: CPU AES-NI는 패킷당 레이턴시가 가장 낮지만(~0.15μs, DMA 없음), 해당 코어를 100% 점유합니다. QAT Lookaside는 PCIe 왕복으로 레이턴시가 높지만(10-50μs), CPU를 해방하여 DPI에 활용할 수 있습니다. NIC Inline은 레이턴시와 처리량 모두 최적이지만 AES-GCM 외 알고리즘을 지원하지 않습니다. NGFW에서의 최적 전략은 트래픽 프로파일에 따라 아키텍처를 혼합하는 것입니다.

암호화 오프로드가 NGFW에서 중요한 이유

AES-256-GCM 암호화/복호화는 CPU 코어당 약 2~8 Gbps(AES-NI 활용 시)의 처리량을 제공합니다. 100Gbps 링크에서 전체 트래픽을 SSL Inspection 하려면 최소 12~50개 코어가 암호화 연산에만 필요합니다. HW 오프로드는 이 부담을 전용 실리콘으로 이전합니다.

암호화 연산CPU (AES-NI)NIC Inline Crypto전용 ASIC (QAT/NITROX)NGFW 전용 칩 (SP5)
AES-256-GCM Encrypt2~8 Gbps/coreNIC 라인레이트100~200 Gbps모델별 (50~100 Gbps)
AES-256-GCM Decrypt2~8 Gbps/coreNIC 라인레이트100~200 Gbps모델별
RSA-2048 핸드셰이크~5K ops/s/core미지원 (CPU 필요)50~100K ops/s벤더별
ECDHE P-256 핸드셰이크~10K ops/s/core미지원100~200K ops/s벤더별
ChaCha20-Poly13053~10 Gbps/core일부 NIC 지원지원벤더별
전력 효율 (Gbps/W)0.1~0.31~52~10벤더 최적화
핵심 관찰: 대칭키(symmetric key) 암호화(AES-GCM)는 NIC inline crypto로 라인레이트 처리가 가능하지만, TLS 핸드셰이크의 비대칭키(asymmetric key) 연산(RSA/ECDHE)은 여전히 CPU 또는 전용 ASIC이 필요합니다. 이는 3대 아키텍처에서 인라인(대칭키)과 Lookaside(비대칭키)를 혼합해야 하는 근본적인 이유입니다. NGFW에서 CPS(Connections Per Second) 병목은 대부분 이 핸드셰이크 단계에서 발생합니다.

kTLS (Kernel TLS) HW 오프로드

kTLS(Kernel TLS)는 TLS 레코드 계층(record layer)의 암·복호화를 커널에서 수행하는 메커니즘입니다. 유저스페이스 TLS 라이브러리(OpenSSL, GnuTLS)가 핸드셰이크를 완료하면, 대칭키와 암호화 파라미터를 setsockopt(SOL_TLS)로 커널에 전달합니다. 이후 데이터 전송은 커널이 직접 TLS 레코드를 구성하고, NIC이 인라인 암호화를 수행합니다.

kTLS의 하이브리드 아키텍처

kTLS는 단일 아키텍처가 아닌 하이브리드입니다. TLS 프로토콜의 두 단계(핸드셰이크와 레코드 전송)가 서로 다른 아키텍처에서 처리됩니다.

이 하이브리드 구조가 중요한 이유는 CPS 병목(핸드셰이크)과 처리량 병목(레코드 전송)을 각각 최적의 아키텍처로 해결하기 때문입니다.

kTLS 하이브리드 아키텍처: 2단계 분리 처리 Phase 1: TLS 핸드셰이크 (CPU / Lookaside) Client Hello CPU (OpenSSL) RSA/ECDHE 연산 QAT (선택) 핸드셰이크 가속 CPS 병목 구간: 코어당 5~10K TLS/s → QAT로 100K+ TLS/s setsockopt(SOL_TLS) → 대칭키를 커널에 전달 → Phase 2로 전환 Phase 2: TLS 레코드 전송 (NIC Inline) 평문 데이터 send() / sendfile() NIC Inline Crypto AES-GCM TLS 레코드 Wire Out 처리량 병목 해소: CPU 0%, NIC 라인레이트 (100~400 Gbps) Zero-copy sendfile() 지원 — 파일 서빙 시 최고 효율 키 전달 NGFW에서의 kTLS 하이브리드 활용 SSL MITM 프록시 구성에서 kTLS 하이브리드는 다음과 같이 동작합니다: ① 클라이언트→NGFW: TLS 핸드셰이크 (CPU + QAT) → 복호화 → DPI/IPS 검사 ② NGFW→서버: kTLS HW TX offload (NIC Inline) → 재암호화 라인레이트 → 서버 전달 ③ 결과: CPU는 DPI에만 집중 (암호화 부하 0%), 재암호화 처리량 = NIC 라인레이트 ④ 폴백: NIC TLS context 초과 시 → SW kTLS (커널 crypto API) 자동 전환

kTLS 동작 모드

모드암호화 위치TLS 헤더sendfile() 지원성능NIC 요구
SW kTLS커널 (crypto API)커널 구성지원 (zero-copy)3~10 Gbps/core없음
HW TX offloadNIC (송신)커널 구성지원NIC 라인레이트tls-hw-tx-offload
HW RX offloadNIC (수신)NIC 파싱-NIC 라인레이트tls-hw-rx-offload
HW Full offloadNIC (양방향)NIC 구성지원NIC 라인레이트TX + RX 모두 지원

kTLS HW offload 설정과 커널 내부

/* 유저스페이스: OpenSSL로 TLS 핸드셰이크 후 kTLS 활성화 */
/* 1. 핸드셰이크 완료 후 대칭키 추출 */
SSL_set_fd(ssl, sockfd);
SSL_connect(ssl);   /* TLS 핸드셰이크 (RSA/ECDHE → CPU) */

/* 2. 커널에 TLS 파라미터 전달 (ULP 설정) */
struct tls12_crypto_info_aes_gcm_256 crypto_info;
crypto_info.info.version = TLS_1_3_VERSION;
crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_256;
/* iv, key, salt, rec_seq 설정 ... */

setsockopt(sockfd, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));
setsockopt(sockfd, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info));
setsockopt(sockfd, SOL_TLS, TLS_RX, &crypto_info_rx, sizeof(crypto_info_rx));

/* 3. 이후 send()/sendfile()은 커널/NIC이 TLS 암호화 수행 */
sendfile(sockfd, filefd, NULL, file_size);  /* zero-copy TLS 전송 */
/* net/tls/tls_device.c — NIC HW offload 등록 경로 */
static int tls_set_device_offload(struct sock *sk,
                                  struct tls_context *ctx)
{
    struct net_device *netdev;
    struct tls_offload_context_tx *offload_ctx;

    /* NIC이 kTLS offload를 지원하는지 확인 */
    netdev = get_netdev_for_sock(sk);
    if (!netdev->tlsdev_ops ||
        !netdev->tlsdev_ops->tls_dev_add)
        return -EOPNOTSUPP;

    /* NIC 드라이버에 TLS 연결 등록 */
    /* 드라이버가 HW crypto context를 할당하고 키 설치 */
    rc = netdev->tlsdev_ops->tls_dev_add(netdev, sk,
        TLS_OFFLOAD_CTX_DIR_TX, &ctx->crypto_send.info);

    /* 성공 시 TLS_TX_DEVICE_OFFLOAD 플래그 설정 */
    /* → send() 호출 시 평문을 NIC에 전달, NIC이 TLS 레코드 구성 + 암호화 */
    ctx->tx_conf = TLS_HW;
    return 0;
}
# kTLS HW offload 지원 확인 및 활성화
ethtool -k eth0 | grep tls
# tls-hw-tx-offload: on
# tls-hw-rx-offload: on

# kTLS HW offload 활성화
ethtool -K eth0 tls-hw-tx-offload on
ethtool -K eth0 tls-hw-rx-offload on

# kTLS 통계 확인
cat /proc/net/tls_stat
# TlsCurrTxSw: 0
# TlsCurrRxSw: 0
# TlsCurrTxDevice: 1234    ← HW TX offload 활성 연결 수
# TlsCurrRxDevice: 1230    ← HW RX offload 활성 연결 수
# TlsTxDevice: 56789       ← 누적 HW TX offload 연결 수
# TlsRxDevice: 55432       ← 누적 HW RX offload 연결 수
# TlsDecryptError: 3       ← HW 복호화 오류 (무결성 실패)

# NIC별 kTLS 카운터
ethtool -S eth0 | grep -i tls
# tx_tls_encrypted_packets: 1234567
# tx_tls_encrypted_bytes: 987654321
# tx_tls_ooo: 0           ← out-of-order resync 횟수
# tx_tls_drop_no_sync_data: 0
# rx_tls_decrypted_packets: 1234000
# rx_tls_decrypted_bytes: 980000000
# rx_tls_resync_req_pkt: 5
# rx_tls_resync_req_start: 2
# rx_tls_resync_req_end: 2

kTLS와 NGFW의 통합

kTLS를 NGFW에 활용하는 핵심 패턴은 SSL Inspection 프록시의 재암호화 가속입니다. NGFW가 SSL MITM(Man-In-The-Middle) 프록시로 동작할 때, 클라이언트→NGFW 복호화 후 DPI를 수행하고, NGFW→서버 재암호화 시 kTLS HW offload로 CPU 부담을 제거합니다.

kTLS offload의 제한 사항:
  • TLS 핸드셰이크는 CPU 필수: kTLS는 레코드 계층(대칭키 암호화)만 오프로드합니다. 핸드셰이크(비대칭키)는 항상 CPU에서 수행
  • 재전송 처리: TCP 재전송 시 NIC이 이전 TLS 레코드를 재구성해야 하므로 "resync" 메커니즘이 필요 (성능 저하 가능)
  • TLS 1.3 전용: 대부분의 NIC HW offload는 TLS 1.2/1.3 AES-GCM만 지원. ChaCha20은 제한적
  • NIC 연결 테이블 크기: NIC HW의 TLS context 저장 용량이 제한적 (수천~수만 개). 초과 시 SW kTLS로 폴백
kTLS HW Offload + NGFW SSL Inspection 파이프라인 Client TLS 암호화 NIC RX kTLS HW Decrypt 평문 NGFW 검사 엔진 DPI / IPS / App-ID 평문 NIC TX kTLS HW Encrypt TLS 재암호화 Server CPU 처리 영역 (DPI만) NIC HW 복호화 NIC HW 암호화 IPSec Inline Crypto 파이프라인 (Site-to-Site VPN) Remote ESP 암호화 NIC Inline Crypto ESP Decrypt + Strip Inner IP conntrack + DPI 평문 inner pkt 검사 NIC Inline Crypto ESP Encap + Encrypt Internal MACsec HW Offload 파이프라인 (L2 암호화) Switch MACsec NIC MACsec HW SecTAG Strip + Decrypt 평문 L2 커널 네트워크 스택 NIC MACsec HW SecTAG Add + Encrypt Peer 암호화 트래픽 평문 트래픽 (검사 가능) NIC HW Crypto Engine CPU 처리 CPU 부담 비교 (100G 링크 기준) kTLS/IPSec HW: CPU 0% (crypto) SW only: CPU 12~50 cores (crypto)

kTLS HW offload NIC 호환성

NICTX offloadRX offloadTLS 1.2TLS 1.3AES-128-GCMAES-256-GCM최대 연결 수커널 최소 버전
NVIDIA CX-6 Dx지원지원지원지원지원지원~1M5.3+ (TX), 5.9+ (RX)
NVIDIA CX-7지원지원지원지원지원지원~4M5.3+
NVIDIA BlueField-3지원지원지원지원지원지원DPU 메모리 의존5.3+
Intel E810지원미지원지원지원 (6.1+)지원지원~16K5.14+
Broadcom P2100제한적미지원지원미지원지원미지원~8K5.17+
Marvell LiquidIO지원지원지원미지원지원지원~32K5.7+

IPSec HW 오프로드 모드

IPSec 오프로드는 암호화 깊이에 따라 3가지 모드로 구분됩니다. NGFW에서 각 모드는 보안 검사 파이프라인과의 통합 방식이 다릅니다. 핵심적으로, 이 3가지 모드는 3대 아키텍처Lookaside에서 Inline으로의 연속적인 스펙트럼입니다.

IPSec 3가지 모드의 아키텍처 분류

모드아키텍처 분류NIC이 처리하는 범위CPU가 처리하는 범위처리량CPU 부하
Crypto offload CPU중심 Lookaside AES-GCM 암·복호화만 ESP 헤더, SPI 룩업, SA 관리, Anti-replay, 라우팅 ~25 Gbps 높음 (xfrm 스택 전체)
Packet offload 부분 인라인 AES-GCM + ESP 헤더 + 패딩 + 시퀀스 번호 + Anti-replay SA 초기 설정, 라우팅, 정책 매칭 ~50 Gbps 중간 (xfrm policy만)
Full offload 완전 인라인 복호화 → eSwitch 포워딩 → 재암호화 (전체 IPSec + 라우팅) SA 초기 설정만 NIC 라인레이트 거의 없음
IPSec 오프로드: Lookaside → Inline 스펙트럼 Crypto Offload (CPU중심 Lookaside) CPU: 70% NIC: AES만 ~25 Gbps ESP 파싱, SA, 라우팅 = CPU NIC: ConnectX-5+, E810 Packet Offload (부분 인라인) CPU: 30% NIC: AES+ESP+SN ~50 Gbps SA 설정, 라우팅만 CPU NIC: ConnectX-6 Dx+, E810 Full Offload (완전 인라인) 0% NIC: 전체 IPSec+FWD NIC 라인레이트 SA 초기 설정만 CPU NIC: ConnectX-7 + eSwitch ← CPU 주도 HW 오프로드 범위 확대 → NIC 전담 → NGFW 장점: DPI 가능 (평문 접근) NGFW 장점: DPI 가능 + CPU 절감 NGFW 주의: DPI 불가 (CPU 우회)
Full offload과 NGFW의 딜레마: IPSec Full offload는 성능 면에서 최적이지만, 패킷이 CPU를 완전히 우회하므로 DPI/IPS 검사가 불가능합니다. 따라서 NGFW에서는 일반적으로 Packet offload를 사용하여 NIC이 ESP 처리를 하되, 복호화된 평문이 CPU로 전달되어 DPI를 수행할 수 있도록 합니다. Full offload는 DPI가 불필요한 사이트 간 VPN 터널이나 이미 DPI 완료된 ESTABLISHED 세션에만 적합합니다.

Crypto Offload 모드

Crypto offload는 가장 기본적인 IPSec HW 가속이며, CPU중심 Lookaside 아키텍처에 해당합니다. NIC이 AES-GCM 암·복호화만 수행하고, ESP 헤더 구성/파싱, SA(Security Association) 관리, 라우팅은 모두 커널 xfrm 스택이 처리합니다.

/* Crypto offload 모드의 패킷 처리 흐름 */

/* [수신 경로] */
NIC_RX:
  → ESP 패킷 수신
  → /* NIC HW: AES-GCM 복호화 + ICV 검증 *//* skb에 복호화된 페이로드 + crypto 결과 태그 */
  → xfrm_input()
    → xfrm_state_lookup()       /* SPI → SA 매핑 *//* HW가 이미 복호화 완료: crypto 연산 skip */
    → xfrm_parse_spi()          /* ESP 헤더 파싱 (CPU) */
    → xfrm_rcv_esp()
      → skb_pull(sizeof(esphdr)) /* ESP 헤더 제거 (CPU) */
      → xfrm_input_resume()
        → /* 내부 IP 패킷 → netfilter 훅 진입 *//* conntrack → DPI 가능 */

/* [송신 경로] */
xfrm_output():
  → xfrm_output_one()
    → esp_output_head()          /* ESP 헤더 + IV + padding 구성 (CPU) *//* NIC HW: AES-GCM 암호화 + ICV 생성 *//* skb에 ESP 헤더 + 암호화된 페이로드 */
  → NIC_TX
# Crypto offload 설정
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
  proto esp spi 0x1001 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x$(head -c 20 /dev/urandom | xxd -p) 128 \
  offload crypto dev eth0 dir out

# offload 상태 확인
ip xfrm state show
# ... offload type crypto dev eth0 dir out

# NIC crypto 카운터
ethtool -S eth0 | grep -i ipsec
# tx_ipsec_encrypt: 1234567
# rx_ipsec_decrypt: 1234000
# rx_ipsec_auth_fail: 0

Packet Offload 모드

Packet offload는 crypto offload에 더해 ESP 헤더 구성/파싱, 패딩, 시퀀스 번호 관리까지 NIC에서 수행합니다. 커널은 평문 IP 패킷을 NIC에 전달하기만 하면 됩니다.

/* Packet offload 모드: 커널에서 평문 IP 패킷만 전달 */

/* [수신] NIC이 ESP 헤더 파싱 + 복호화 + 헤더 제거 */
NIC_RX:
  → ESP 패킷 수신
  → /* NIC HW: SPI lookup → SA 확인 *//* NIC HW: ESP 헤더 제거 + AES-GCM 복호화 + ICV 검증 *//* NIC HW: 시퀀스 번호 anti-replay 검사 *//* 결과: 순수 내부 IP 패킷이 호스트에 전달 *//* skb→sp에 xfrm_state 참조 설정 (정책 검증용) */
  → netif_receive_skb()  /* → 일반 IP 패킷처럼 처리 */
    → nf_hook(PREROUTING) → conntrack → nftables → DPI

/* [송신] 커널이 평문 IP 패킷 전달 → NIC이 ESP 캡슐화 + 암호화 */
ip_output():
  → /* xfrm lookup → 해당 SA의 offload mode 확인 *//* 평문 IP 패킷을 NIC TX 큐에 전달 *//* NIC HW: ESP 헤더 추가 + padding + 시퀀스 번호 *//* NIC HW: AES-GCM 암호화 + ICV 생성 *//* 완성된 ESP 패킷 wire에 전송 */
# Packet offload 설정
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
  proto esp spi 0x1001 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x$(head -c 20 /dev/urandom | xxd -p) 128 \
  offload packet dev eth0 dir out

# Crypto vs Packet offload 성능 차이 확인
# iperf3로 IPSec 터널 처리량 측정
iperf3 -c 10.2.0.1 -t 30 -P 4
# Crypto offload: ~25 Gbps (ESP 헤더 처리가 CPU 병목)
# Packet offload: ~50 Gbps (전체 ESP 처리 HW)

Full Offload 모드

Full offload는 packet offload에 추가로 라우팅/포워딩까지 NIC eSwitch에서 수행합니다. IPSec 터널의 내부 패킷이 eSwitch FDB 규칙에 매칭되면, 복호화 → 포워딩 → 재암호화가 모두 NIC 내부에서 완료되어 CPU를 전혀 사용하지 않습니다.

# Full offload: eSwitch + IPSec 결합
# 1. SA를 full offload 모드로 설정
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
  proto esp spi 0x1001 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x$(head -c 20 /dev/urandom | xxd -p) 128 \
  offload packet dev eth0 dir out

ip xfrm state add src 10.0.0.2 dst 10.0.0.1 \
  proto esp spi 0x1002 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x$(head -c 20 /dev/urandom | xxd -p) 128 \
  offload packet dev eth0 dir in

# 2. eSwitch에서 decrypted inner 패킷을 직접 포워딩
# TC flower로 IPSec decrypted + EST 세션 → HW forward
tc filter add dev eth0_rep0 ingress chain 0 prio 1 \
  protocol ip flower \
  ct_state +trk+est \
  enc_type ipsec \
  action ct zone 1 nat pipe \
  action mirred egress redirect dev eth1_rep0

# 결과: 암호화된 패킷 수신 → NIC 내부에서 decrypt → forward → encrypt → 송신
# CPU 사용률: 거의 0% (ESTABLISHED 세션)
IPSec HW 오프로드 3가지 모드 — CPU/NIC 역할 분담 Crypto Offload 10~25 Gbps NIC: 암·복호화 CPU: ESP 헤더 CPU: 시퀀스 번호 CPU: 라우팅 CPU 부담: ■■■■□□ (ESP 처리) Packet Offload 25~50 Gbps NIC: 암·복호화 NIC: ESP 헤더 NIC: 시퀀스 번호 CPU: 라우팅 CPU 부담: ■■□□□□ (라우팅만) Full Offload 50~100 Gbps (라인레이트) NIC: 암·복호화 NIC: ESP 헤더 NIC: 시퀀스 번호 NIC: eSwitch 포워딩 CPU 부담: □□□□□□ (EST 세션 zero) 커널 xfrm Device Offload 내부 흐름 ip xfrm state add offload packet dev eth0 xfrm_dev_offload_ok() NIC caps 확인 ndo_xfrm_add_state() NIC 드라이버 콜백 HW SA Table SPI+키+algo 설치 HW Offload Active NGFW 파이프라인과의 통합 포인트 ESP 수신 암호화 패킷 NIC HW Decrypt crypto/packet mode 선택 평문 conntrack inner pkt 상태추적 DPI / IPS NEW만 (첫 패킷) flowtable EST → offload NIC HW Encrypt ESP 재캡슐화 + 암호화 핵심: NIC 복호화 → 평문에 DPI 적용 → NIC 재암호화 CPU는 NEW 세션 DPI만 담당, EST 세션은 NIC이 전구간 처리 NIC별 IPSec offload 지원 현황 CX-6 Dx: crypto+packet CX-7/BF-3: crypto+packet+full E810: crypto only 커널 5.4+ 커널 5.17+ 커널 5.14+

IPSec HW offload NIC 호환성 매트릭스

기능NVIDIA CX-6 DxNVIDIA CX-7NVIDIA BF-3Intel E810Marvell CN10K
Crypto offload지원지원지원지원지원
Packet offload지원지원지원미지원지원
Full offload (eSwitch)미지원지원 (6.2+)지원미지원미지원
AES-128-GCM지원지원지원지원지원
AES-256-GCM지원지원지원지원지원
최대 SA 수~2K~8K~16K~1K~4K
Anti-replay HW지원지원지원제한적지원
ESN (Extended SN)지원지원지원지원지원
IPv6 ESP지원지원지원지원지원
Transport mode지원지원지원지원미지원

MACsec HW 오프로드

MACsec(IEEE 802.1AE)는 L2(이더넷 프레임) 수준의 암호화를 제공합니다. IPSec이 L3 이상을 보호하는 반면, MACsec는 이더넷 프레임 전체를 암호화하여 같은 L2 세그먼트 내의 도청/변조를 방지합니다.

MACsec과 NGFW의 관계

# MACsec HW offload 설정
# 1. MACsec 인터페이스 생성 (offload 모드)
ip link add link eth0 macsec0 type macsec \
  sci ff:ff:ff:ff:ff:ff:00:01 \
  encrypt on protect on \
  offload mac

# 2. 수신 SA 추가
ip macsec add macsec0 rx sci ff:ff:ff:ff:ff:ff:00:02 sa 0 \
  pn 1 on key 00 $(head -c 16 /dev/urandom | xxd -p)

# 3. 송신 SA 추가
ip macsec add macsec0 tx sa 0 \
  pn 1 on key 01 $(head -c 16 /dev/urandom | xxd -p)

# 4. 인터페이스 활성화
ip link set macsec0 up
ip addr add 10.0.0.1/24 dev macsec0

# offload 상태 확인
ip macsec show
# TXSC: ... (offload: mac)
# RXSC: ... (offload: mac)

# NIC MACsec 카운터
ethtool -S eth0 | grep -i macsec
# tx_macsec_pkts: 1234567
# rx_macsec_pkts: 1234000
# rx_macsec_decrypt_fail: 0

MACsec offload NIC 지원 현황

NICMACsec HW offloadGCM-AES-128GCM-AES-256XPN (Extended PN)최대 SC 수커널 최소
NVIDIA CX-6 Dx지원지원지원지원 (6.6+)~1285.12+
NVIDIA CX-7지원지원지원지원~2565.12+
Intel E810미지원-----
Microchip VSC7558지원 (switchdev)지원지원미지원~645.7+
Marvell CN10K지원지원지원지원~5126.1+

전용 크립토 가속기 (Intel QAT, Marvell NITROX)

NIC inline crypto와 별도로, 전용 크립토 가속 카드는 대량의 비대칭키 연산(RSA/ECDHE 핸드셰이크)과 대칭키 암호화를 모두 처리할 수 있습니다. NGFW에서 SSL Inspection의 TLS 핸드셰이크 병목(CPS 한계)을 해소하는 핵심 구성 요소입니다.

주요 크립토 가속기 비교

가속기유형대칭키 처리량RSA-2048 ops/sECDHE P-256 ops/sTLS 핸드셰이크/sLinux 드라이버
Intel QAT 4xxx (4th Gen Xeon 내장)내장 ASIC100 Gbps100K200K~100Kqat_4xxx (커널 5.18+)
Intel QAT 8970 (PCIe 카드)PCIe 카드200 Gbps140K280K~140Kqat_c62x
Marvell NITROX VPCIe 카드100 Gbps100K200K~100Knitrox (crypto API)
Marvell LiquidSecurityHSM + 가속50 Gbps50K100K~50K전용 드라이버
ARM CryptoCellSoC 내장1~5 Gbps5K10K~5Kccree
CPU (AES-NI)CPU 명령어2~8 Gbps/core5K/core10K/core~5K/coreaesni_intel

Intel QAT와 Linux crypto API 연동

/* Linux crypto API를 통한 QAT 가속 사용 */
/* 커널이 자동으로 HW 가속기를 선택하는 구조 */

/* 1. crypto API에서 알고리즘 요청 */
struct crypto_aead *aead;
aead = crypto_alloc_aead("gcm(aes)", 0, 0);
/* → 커널이 우선순위에 따라 선택: */
/*   1. QAT HW 가속 드라이버 (최고 우선순위) */
/*   2. AES-NI (CPU 가속) */
/*   3. 일반 SW 구현 (최저) */

/* 2. 비동기(Async) 암호화 요청 */
struct aead_request *req;
req = aead_request_alloc(aead, GFP_KERNEL);
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                          crypto_complete_cb, &result);
aead_request_set_crypt(req, src_sg, dst_sg, plaintext_len, iv);
aead_request_set_ad(req, aad_len);

/* 3. 비동기 전송 → QAT 엔진이 처리 */
ret = crypto_aead_encrypt(req);
if (ret == -EINPROGRESS || ret == -EBUSY) {
    /* QAT가 비동기로 처리 중 → 콜백에서 완료 통지 */
    wait_for_completion(&result.completion);
}
# Intel QAT 상태 확인
# 모듈 로드
modprobe qat_4xxx    # 또는 qat_c62x (PCIe 카드)
modprobe intel_qat

# QAT 디바이스 확인
lspci | grep -i "Co-processor\|DH895\|C62x\|4xxx"
# 0000:6b:00.0 Co-processor: Intel Corporation 4xxx Series (rev 02)

# QAT 서비스 상태
adf_ctl status
# qat_dev0 - type: 4xxx, ... state: up

# crypto API에 등록된 가속기 확인
cat /proc/crypto | grep -B2 "driver.*qat"
# name         : gcm(aes)
# driver       : gcm-aes-qat
# priority     : 4001

# IPSec에서 QAT 자동 활용 확인
# xfrm SA가 gcm(aes)를 사용하면 QAT가 자동으로 선택됨
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
  proto esp spi 0x1001 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x$(head -c 20 /dev/urandom | xxd -p) 128

# QAT 성능 카운터
cat /sys/kernel/debug/qat_4xxx_0000:6b:00.0/fw_counters
# 또는 OpenSSL QAT 엔진 벤치마크
openssl speed -engine qatengine -evp aes-256-gcm -bytes 8192 -seconds 10
QAT와 NGFW SSL Inspection의 결합: Intel QAT는 OpenSSL QAT Engine을 통해 SSL 프록시(haproxy, nginx, Suricata)의 TLS 핸드셰이크를 가속합니다. NGFW SSL Inspection에서 CPS 병목의 80%는 RSA/ECDHE 핸드셰이크이므로, QAT가 이 부분을 처리하면 SSL Inspection CPS가 5~20배 향상됩니다.

SSL/TLS 검사(Inspection) 오프로드 파이프라인

NGFW에서 SSL/TLS 암호화 트래픽을 검사하는 방식은 크게 4가지로 분류됩니다. 각 방식은 보안 수준, 성능, 구현 복잡도에서 다른 트레이드오프를 가집니다.

방식 1: SSL MITM 프록시 (Forward Proxy)

가장 전통적인 SSL Inspection 방법입니다. NGFW가 클라이언트와 서버 사이에서 두 개의 별도 TLS 세션을 수립하고, 중간에서 평문을 검사합니다.

단계처리 내용CPU 비용HW 오프로드 가능
1. 클라이언트→NGFW TLS 핸드셰이크NGFW가 서버 인증서를 동적 생성 (CA 서명)매우 높음 (RSA/ECDHE)QAT/NITROX (비대칭키)
2. NGFW→서버 TLS 핸드셰이크NGFW가 실제 서버와 TLS 연결 수립매우 높음QAT/NITROX
3. 클라이언트→NGFW 데이터 복호화클라이언트 TLS 세션의 레코드 복호화높음 (AES-GCM)kTLS HW RX / SP5
4. 평문 DPI/IPS 검사HTTP/2 파싱, 시그니처 매칭, App-ID중간~높음일부 (regex 가속기)
5. NGFW→서버 데이터 재암호화서버 TLS 세션의 레코드 암호화높음kTLS HW TX / SP5

방식 2: 인증서 기반 복호화 (Inbound Inspection)

NGFW가 서버의 개인키(Private Key)를 보유하고, 인바운드 TLS 트래픽을 수동적으로 복호화합니다. MITM이 아닌 패시브 복호화이므로 클라이언트에 인증서를 설치할 필요가 없습니다.

방식 3: eBPF 기반 TLS 가시성 (에이전트 방식)

호스트에 eBPF 프로그램을 배포하여 TLS 라이브러리(OpenSSL/BoringSSL)의 SSL_read()/SSL_write()를 후킹하고, 평문 데이터를 캡처합니다. NGFW의 네트워크 경로에서 복호화할 필요가 없으므로 성능 영향이 최소화됩니다.

/* eBPF: OpenSSL SSL_write() uprobe로 평문 캡처 */
SEC("uprobe/SSL_write")
int probe_ssl_write(struct pt_regs *ctx)
{
    void *ssl = (void *)PT_REGS_PARM1(ctx);
    void *buf = (void *)PT_REGS_PARM2(ctx);
    int num = (int)PT_REGS_PARM3(ctx);

    /* 평문 데이터를 ring buffer로 전달 */
    struct ssl_data_t data = {};
    data.pid = bpf_get_current_pid_tgid() >> 32;
    data.len = num < 256 ? num : 256;
    bpf_probe_read_user(data.buf, data.len, buf);

    bpf_ringbuf_output(&events, &data, sizeof(data), 0);
    return 0;
}

방식 4: 메타데이터 기반 분류 (복호화 없는 검사)

TLS 트래픽을 복호화하지 않고, 외부에서 관찰 가능한 메타데이터만으로 위협을 탐지합니다:

SSL/TLS Inspection 4가지 방식 — HW 오프로드 포인트 방식 1: SSL MITM 프록시 (Forward Proxy) Client TLS① HW Decrypt kTLS/SP5/QAT DPI 평문 검사 HW Encrypt kTLS/SP5/QAT TLS② Server 보안: ★★★★★ | 성능: ★★☆☆☆ | 복잡도: 높음 | 핸드셰이크 2배 방식 2: 인바운드 복호화 (서버 키 보유) Client TLS 패시브 복호화 서버 Private Key DPI 복사본 검사 Server 보안: ★★★★☆ | 성능: ★★★★☆ | PFS cipher 미지원 (TLS 1.3 불가) 방식 3: eBPF 기반 TLS 가시성 App uprobe 평문 eBPF ringbuf SSL_write 캡처 분석 엔진 DPI/IPS 네트워크 암호화 유지 보안: ★★★★☆ | 성능: ★★★★★ | 엔드포인트 에이전트 필요 방식 4: 메타데이터 기반 분류 (복호화 없음) Client JA4 + DNS 분석 복호화 없이 분류 패스스루 Server 보안: ★★☆☆☆ | 성능: ★★★★★ | ECH 환경에서 제한적 암/복호화 HW 오프로드 가능 포인트 종합 TLS 핸드셰이크 RSA/ECDHE (비대칭) → QAT / NITROX / SP5 CPS 병목 해소 TLS 레코드 암/복호화 AES-GCM (대칭) → kTLS / NIC Inline 라인레이트 처리 IPSec ESP AES-GCM + ESP 헤더 → NIC Packet/Full CPU zero (Full mode) MACsec (L2) AES-GCM-128/256 → NIC MACsec HW L2 라인레이트 WireGuard ChaCha20-Poly1305 → CPU only (현재) HW offload 미지원 NGFW 최적 전략: 핸드셰이크는 QAT/ASIC, 레코드 암호화는 NIC inline, DPI는 CPU에 집중 NGFW 암호화 오프로드 전략 선택 가이드 기업 내부망 (Full Inspection 필요) → 방식 1 + QAT + kTLS 클라우드/SaaS 환경 → 방식 3 (eBPF) + 방식 4 (JA4) 자사 서버 보호 → 방식 2 (인바운드) + NIC crypto VPN 게이트웨이 → IPSec Full offload + flowtable

NGFW 암호화 오프로드 통합 구성 예제

아래 3가지 패턴은 3대 아키텍처의 서로 다른 조합으로, NGFW의 요구사항(VPN, SSL Inspection, 클라우드)에 따라 최적의 하이브리드 구성을 보여줍니다.

패턴아키텍처 조합핵심 HW예상 Fast Path 처리량CPS (SSL 포함)CPU 사용률
패턴 1
IPSec + DPI
인라인 (IPSec packet offload)
+ 인라인 (flowtable HW)
ConnectX-7 + eSwitch 100 Gbps (flowtable) N/A (IPSec, 세션 기반) Slow Path: DPI만
Fast Path: 0%
패턴 2
SSL MITM
CPU Lookaside (QAT 핸드셰이크)
+ 인라인 (kTLS 레코드)
4th Gen Xeon + QAT 내장
+ ConnectX-7 kTLS
100 Gbps (kTLS TX) 100K+ TLS/s (QAT) DPI + SSL 파싱만
암호화: 0%
패턴 3
eBPF 가시성
CPU중심 (eBPF uprobe)
+ 인라인 (flowtable HW)
범용 서버 + SmartNIC 100 Gbps (flowtable) 제한 없음 (복호화 없음) eBPF probe: 최소
복호화 없음

패턴 1: IPSec Full Offload + flowtable + DPI 조합 [인라인 아키텍처]

VPN 게이트웨이 역할의 NGFW에서, IPSec 복호화 → DPI → 오프로드 → IPSec 재암호화 전체 파이프라인을 구성합니다. 이 패턴은 인라인 아키텍처의 대표적 활용으로, SmartNIC eSwitch가 IPSec + 포워딩을 모두 처리합니다:

#!/bin/bash
# NGFW VPN Gateway: IPSec Full Offload + DPI 통합 구성
# NIC: NVIDIA ConnectX-7 (IPSec packet offload + eSwitch)

# === 1. eSwitch switchdev 모드 활성화 ===
devlink dev eswitch set pci/0000:03:00.0 mode switchdev

# === 2. IPSec SA 설정 (packet offload) ===
# 원격 사이트와의 IPSec 터널 (AES-256-GCM)
KEY_OUT=$(head -c 36 /dev/urandom | xxd -p)
KEY_IN=$(head -c 36 /dev/urandom | xxd -p)

ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
  proto esp spi 0x1001 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x${KEY_OUT} 128 \
  offload packet dev eth0 dir out

ip xfrm state add src 10.0.0.2 dst 10.0.0.1 \
  proto esp spi 0x1002 reqid 1 mode tunnel \
  aead 'rfc4106(gcm(aes))' 0x${KEY_IN} 128 \
  offload packet dev eth0 dir in

# xfrm 정책
ip xfrm policy add src 10.1.0.0/24 dst 10.2.0.0/24 \
  dir out tmpl src 10.0.0.1 dst 10.0.0.2 \
  proto esp reqid 1 mode tunnel
ip xfrm policy add src 10.2.0.0/24 dst 10.1.0.0/24 \
  dir in tmpl src 10.0.0.2 dst 10.0.0.1 \
  proto esp reqid 1 mode tunnel

# === 3. nftables NGFW 규칙 (복호화된 내부 패킷에 적용) ===
nft -f - << 'EOF'
table inet vpn_ngfw {
    flowtable ft_vpn {
        hook ingress priority 0
        devices = { eth0, eth1 }
        flags offload
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # EST 세션 → flowtable HW offload
        # (NIC이 decrypt → forward → re-encrypt 전구간 처리)
        ct state established,related flow add @ft_vpn counter accept

        # INVALID → drop
        ct state invalid counter drop

        # NEW → Suricata DPI (NFQUEUE)
        ct state new counter queue num 0-3 fanout,bypass
    }
}
EOF

# === 4. Suricata IPS 시작 (NFQUEUE 모드) ===
# suricata.yaml에서 nfqueue 모드 설정 필요
systemctl start suricata

# === 5. 확인 ===
echo "IPSec offload 상태:"
ip xfrm state show | grep -A1 offload
echo ""
echo "flowtable HW offload 확인:"
nft list flowtable inet vpn_ngfw ft_vpn
echo ""
echo "NIC 카운터:"
ethtool -S eth0 | grep -E "ipsec|flow_table"

패턴 2: SSL MITM 프록시 + QAT + kTLS 구성 [CPU Lookaside + 인라인 하이브리드]

HTTPS 트래픽을 복호화하여 DPI를 수행하는 SSL Inspection 구성입니다. 이 패턴은 CPU중심 Lookaside(QAT 핸드셰이크 가속)와 인라인(kTLS NIC 레코드 오프로드)의 하이브리드입니다. TLS 핸드셰이크는 QAT가, 레코드 암호화는 kTLS NIC offload가 처리합니다:

# SSL MITM NGFW 구성 (nginx reverse proxy + Suricata)

# === 1. QAT 활성화 ===
modprobe qat_4xxx
modprobe intel_qat

# === 2. kTLS NIC offload 활성화 ===
ethtool -K eth0 tls-hw-tx-offload on
ethtool -K eth0 tls-hw-rx-offload on

# === 3. nginx SSL 프록시 설정 (kTLS + QAT) ===
# /etc/nginx/nginx.conf
# ssl_engine qatengine;        # QAT 가속 핸드셰이크
# sendfile on;                 # kTLS + sendfile zero-copy
# ssl_conf_command Options KTLS;  # kTLS 활성화

# === 4. nftables: SSL 프록시로 리다이렉트 ===
nft -f - << 'EOF'
table inet ssl_inspect {
    chain prerouting {
        type nat hook prerouting priority -100; policy accept;

        # HTTPS 트래픽 → SSL 프록시 (nginx)로 REDIRECT
        tcp dport 443 redirect to :8443
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # SSL 프록시가 복호화한 평문 → Suricata DPI
        iifname "lo" oifname "eth1" ct state new \
            queue num 0-3 fanout,bypass

        ct state established,related accept
    }
}
EOF

# === 5. QAT 성능 확인 ===
cat /proc/crypto | grep -A3 "driver.*qat"
adf_ctl status

패턴 3: eBPF TLS 가시성 + flowtable 오프로드 [CPU중심 + 인라인 하이브리드]

# eBPF 기반 TLS 가시성 (복호화 없이 평문 캡처)
# bpftrace로 OpenSSL SSL_write/SSL_read 후킹

# SSL_write 평문 캡처 (간단한 예시)
bpftrace -e '
  uprobe:/usr/lib/x86_64-linux-gnu/libssl.so.3:SSL_write {
    printf("PID %d SSL_write %d bytes\n", pid, arg2);
    /* 실제 환경에서는 ring buffer로 DPI 엔진에 전달 */
  }
  uprobe:/usr/lib/x86_64-linux-gnu/libssl.so.3:SSL_read_ex /retval > 0/ {
    printf("PID %d SSL_read %d bytes\n", pid, arg2);
  }
'

# 네트워크 경로에서는 암호화 유지 → 최고 성능
# flowtable HW offload 그대로 적용 가능
nft add flowtable inet filter ft \
  { hook ingress priority 0\; devices = { eth0, eth1 }\; flags offload\; }
nft add rule inet filter forward \
  ct state established flow add @ft accept
암호화 오프로드 방식 선택 가이드:
  • VPN 게이트웨이 (Site-to-Site): IPSec packet/full offload + flowtable → 최소 CPU, 라인레이트
  • 엔터프라이즈 NGFW (SSL Inspection): QAT(핸드셰이크) + kTLS(레코드) + DPI → CPU는 DPI에만 집중
  • 클라우드 네이티브 NGFW: eBPF TLS 가시성 + JA4 + NIC offload → 복호화 없이 최대 성능
  • 데이터센터 내부 (East-West): MACsec HW offload + 상위 계층 DPI → L2 암호화 투명 처리

Regex/DPI 하드웨어 가속 엔진

NGFW의 핵심 기능인 심층 패킷 검사(DPI, Deep Packet Inspection)는 네트워크 트래픽의 페이로드(Payload)를 정규식(Regular Expression) 패턴으로 분석하여 악성 코드, 침입 시도, 애플리케이션 프로토콜을 식별합니다. 이 과정은 CPU 집약적이며, 10Gbps 이상의 환경에서 소프트웨어만으로는 라인 레이트 처리가 불가능합니다. 이 절에서는 정규식 매칭의 비용 구조와 하드웨어 가속 엔진 3종(NVIDIA RXP, Marvell REE, Intel Hyperscan+QAT)의 아키텍처 및 통합 방법을 다룹니다.

NGFW에서 정규식 매칭의 비용

IDS/IPS 엔진(Suricata, Snort)의 CPU 프로파일링(Profiling) 데이터를 보면, 멀티 패턴 매칭(Multi-Pattern Matching, MPM)이 전체 CPU 사이클의 40~60%를 소비합니다. 이는 수천 개의 시그니처(Signature)를 동시에 매칭해야 하기 때문입니다.

오토마톤 유형시간 복잡도메모리 사용특성대표 구현
DFA (Deterministic Finite Automaton)O(n) — 입력 길이에 비례O(2^m) — 상태 폭발 가능예측 가능한 처리 시간, 메모리 집약적하드웨어 엔진 (RXP, REE)
NFA (Non-deterministic Finite Automaton)O(n×m) — 최악 시 패턴 수에 비례O(m) — 패턴 크기에 비례메모리 효율적, 처리 시간 가변적PCRE, RE2
Hybrid DFA/NFAO(n) 평균, 일부 NFA 폴백중간DFA 이점 + NFA 폴백으로 상태 폭발 회피Hyperscan, Suricata MPM
성능 병목: Suricata에서 Aho-Corasick MPM은 단일 패킷당 수만 개 시그니처를 순회합니다. 10Gbps(약 14.88Mpps 최소 크기 기준)에서 패킷당 사용 가능한 CPU 시간은 약 67ns에 불과하며, 복잡한 정규식 매칭에는 수백 ns~수 μs가 소요되므로 소프트웨어만으로는 한계가 명확합니다.

다음 명령으로 Suricata 프로세스의 CPU 프로파일을 수집할 수 있습니다.

# perf를 이용한 Suricata CPU 프로파일링 (30초 샘플링)
sudo perf record -g -p $(pidof suricata) -- sleep 30
sudo perf report --sort=dso,symbol --stdio | head -60

# 특정 함수별 CPU 비중 확인
sudo perf report --stdio --sort=symbol | grep -E "(SCACSearch|MpmSearch|DetectMatch)"

# bpftrace로 MPM 함수 레이턴시 분포 확인
sudo bpftrace -e '
uprobe:/usr/bin/suricata:SCACSearch {
    @start[tid] = nsecs;
}
uretprobe:/usr/bin/suricata:SCACSearch /@start[tid]/ {
    @latency_ns = hist(nsecs - @start[tid]);
    delete(@start[tid]);
}
interval:s:10 { exit(); }
'

# flamegraph 생성 (CPU 핫스팟 시각화)
sudo perf script | stackcollapse-perf.pl | flamegraph.pl > suricata-flame.svg
프로파일링 팁: perf report 결과에서 SCACSearch(Aho-Corasick), hs_scan(Hyperscan), pcre2_match(PCRE2) 함수가 상위에 나타나면 정규식 매칭이 병목입니다. 이러한 워크로드가 전체의 30%를 초과하면 하드웨어 가속 도입을 검토해야 합니다.

10Gbps 이상 환경에서 하드웨어 가속이 중요한 이유를 정리하면 다음과 같습니다.

NVIDIA BlueField-3 RXP 엔진

NVIDIA BlueField-3 DPU에 내장된 RXP(RegEx Processing Unit)는 하드웨어 DFA 기반 정규식 가속 엔진입니다. 최대 400Gbps의 정규식 매칭 처리량을 제공하며, DOCA(Data Center Infrastructure on a Chip Architecture) SDK를 통해 프로그래밍합니다.

항목사양
엔진 아키텍처하드웨어 DFA + NFA 폴백 하이브리드
최대 처리량최대 400Gbps (BlueField-3 기준)
최대 규칙 수수만 개 PCRE 호환 패턴
레이턴시결정론적 — 패턴 수에 무관
컴파일러rxpc — PCRE 패턴 → RXP 바이너리 규칙
APIDOCA RegEx API (doca_regex)
배치 처리복수 버퍼를 단일 요청으로 일괄 제출

RXP 엔진의 워크플로는 다음과 같습니다.

  1. 규칙 컴파일: rxpc 컴파일러가 PCRE 형식의 정규식 패턴 파일(.rules)을 RXP 하드웨어가 이해하는 바이너리 규칙 파일(.rxp)로 변환합니다.
  2. 엔진 초기화: DOCA RegEx 컨텍스트를 생성하고, 컴파일된 규칙을 RXP 엔진에 로드합니다.
  3. 배치 제출: 검사할 패킷 버퍼들을 배치(Batch)로 묶어 RXP 엔진에 비동기 제출합니다.
  4. 결과 수집: 폴링(Polling) 또는 이벤트 기반으로 매칭 결과를 수집하고, 매칭된 규칙 ID와 오프셋 정보를 확인합니다.
# rxpc를 이용한 규칙 컴파일
# 입력: PCRE 패턴 파일, 출력: RXP 바이너리 규칙
rxpc -f suricata_patterns.rules -o compiled_rules.rxp \
     --max-rules 10000 \
     --optimize-level 3

# 컴파일 결과 통계 확인
rxpc -f suricata_patterns.rules --stats-only
# 출력 예: Total rules: 8432, DFA states: 124567, Memory: 48MB

다음은 DOCA RegEx API를 사용한 정규식 하드웨어 가속 코드 예제입니다.

#include <doca_regex.h>
#include <doca_buf.h>
#include <doca_ctx.h>
#include <doca_dev.h>
#include <doca_error.h>
#include <doca_log.h>

DOCA_LOG_REGISTER(REGEX_DPI);

#define MAX_BATCH_SIZE  256
#define MAX_MATCHES     16

struct regex_dpi_ctx {
    struct doca_dev       *dev;
    struct doca_regex     *regex;
    struct doca_ctx       *ctx;
    struct doca_pe        *pe;       /* Progress engine */
    struct doca_buf_arr   *buf_arr;
    struct doca_mmap      *mmap;
    uint32_t               total_matches;
    uint32_t               total_scanned;
};

/* 매칭 완료 콜백 — 비동기 결과 처리 */
static void regex_task_completion_cb(struct doca_regex_task_search *task,
                                     union doca_data task_user_data,
                                     union doca_data ctx_user_data)
{
    struct regex_dpi_ctx *dpi = (struct regex_dpi_ctx *)ctx_user_data.ptr;
    struct doca_regex_search_result *result;
    uint32_t num_matches = 0;
    doca_error_t err;

    err = doca_regex_task_search_get_result(task, &result);
    if (err != DOCA_SUCCESS) {
        DOCA_LOG_WARN("regex result retrieval failed: %s",
                      doca_error_get_descr(err));
        goto cleanup;
    }

    num_matches = doca_regex_search_result_get_num_matches(result);
    if (num_matches > 0) {
        dpi->total_matches += num_matches;

        /* 매칭된 각 규칙 ID와 오프셋 순회 */
        for (uint32_t i = 0; i < num_matches && i < MAX_MATCHES; i++) {
            struct doca_regex_match *match;
            doca_regex_search_result_get_match(result, i, &match);

            uint32_t rule_id = doca_regex_match_get_rule_id(match);
            uint32_t offset  = doca_regex_match_get_offset(match);
            uint32_t length  = doca_regex_match_get_length(match);

            DOCA_LOG_DBG("Match: rule=%u offset=%u len=%u",
                         rule_id, offset, length);
        }
    }
    dpi->total_scanned++;

cleanup:
    doca_task_free(doca_regex_task_search_as_task(task));
}

/* RXP 엔진 초기화: 디바이스 탐색, 규칙 로드, 컨텍스트 생성 */
static doca_error_t init_regex_engine(struct regex_dpi_ctx *dpi,
                                      const char *rules_path)
{
    doca_error_t err;

    /* BlueField DPU의 RegEx 디바이스 열기 */
    err = doca_dev_open_by_capability(DOCA_DEV_CAP_REGEX, &dpi->dev);
    if (err != DOCA_SUCCESS) {
        DOCA_LOG_ERR("RegEx device not found: %s",
                     doca_error_get_descr(err));
        return err;
    }

    /* DOCA RegEx 인스턴스 생성 */
    err = doca_regex_create(dpi->dev, &dpi->regex);
    if (err != DOCA_SUCCESS)
        return err;

    /* 컴파일된 규칙 파일 로드 */
    err = doca_regex_set_hardware_compiled_rules(dpi->regex, rules_path);
    if (err != DOCA_SUCCESS) {
        DOCA_LOG_ERR("Failed to load rules from %s", rules_path);
        return err;
    }

    /* Progress Engine 생성 (비동기 태스크 관리) */
    err = doca_pe_create(&dpi->pe);
    if (err != DOCA_SUCCESS)
        return err;

    /* 컨텍스트 연결 및 시작 */
    dpi->ctx = doca_regex_as_ctx(dpi->regex);
    err = doca_pe_connect_ctx(dpi->pe, dpi->ctx);
    if (err != DOCA_SUCCESS)
        return err;

    /* 완료 콜백 설정 */
    union doca_data user_data = { .ptr = dpi };
    err = doca_regex_task_search_set_conf(
              dpi->regex,
              regex_task_completion_cb,  /* 성공 콜백 */
              regex_task_completion_cb,  /* 에러 콜백 */
              MAX_BATCH_SIZE);
    if (err != DOCA_SUCCESS)
        return err;

    err = doca_ctx_set_user_data(dpi->ctx, user_data);
    if (err != DOCA_SUCCESS)
        return err;

    return doca_ctx_start(dpi->ctx);
}

/* 패킷 버퍼 배치를 RXP 엔진에 제출 */
static doca_error_t submit_packet_batch(struct regex_dpi_ctx *dpi,
                                        void **pkt_bufs,
                                        uint32_t *pkt_lens,
                                        int count)
{
    doca_error_t err;

    for (int i = 0; i < count; i++) {
        struct doca_regex_task_search *task;
        struct doca_buf *buf;

        /* 패킷 데이터를 DOCA 버퍼에 매핑 */
        err = doca_buf_arr_get_buf(dpi->buf_arr, i, &buf);
        if (err != DOCA_SUCCESS)
            continue;

        doca_buf_set_data(buf, pkt_bufs[i], pkt_lens[i]);

        /* 검색 태스크 생성 및 제출 */
        union doca_data task_data = { .u64 = i };
        err = doca_regex_task_search_alloc_init(
                  dpi->regex, buf, task_data, &task);
        if (err != DOCA_SUCCESS)
            continue;

        err = doca_task_submit(
                  doca_regex_task_search_as_task(task));
        if (err != DOCA_SUCCESS) {
            doca_task_free(doca_regex_task_search_as_task(task));
            continue;
        }
    }

    /* Progress Engine 폴링 — 완료된 태스크의 콜백 호출 */
    while (dpi->total_scanned < (uint32_t)count) {
        (void)doca_pe_progress(dpi->pe);
    }

    return DOCA_SUCCESS;
}
규칙 호환성: RXP 컴파일러(rxpc)는 대부분의 PCRE 구문을 지원하지만, 역참조(Back-reference), 재귀 패턴(Recursive Pattern), 무제한 반복(Unbounded Repetition) 등 일부 고급 기능은 지원하지 않습니다. Suricata 시그니처를 변환할 때 rxpc --check-only 옵션으로 호환성을 사전 검증해야 합니다.

Marvell REE (RegEx Engine)

Marvell OCTEON CN10K SoC에 내장된 REE(RegEx Engine)는 하드웨어 DFA/NFA 하이브리드 정규식 코프로세서(Coprocessor)입니다. DPDK의 rte_regexdev API를 통해 접근하며, 이벤트 기반 비동기 처리 모델을 지원합니다.

항목NVIDIA RXP (BlueField-3)Marvell REE (CN10K)
기반 하드웨어DPU (SmartNIC)네트워크 SoC (OCTEON)
오토마톤하드웨어 DFA + NFA 폴백DFA/NFA 하이브리드
프로그래밍 인터페이스DOCA RegEx APIDPDK rte_regexdev API
규칙 컴파일rxpc CLI 도구roc-re 컴파일러 / REE SDK
배치 처리DOCA Progress EngineDPDK eventdev 연동
최대 규칙 수수만 개수만 개
통합 대상DOCA DPI 프레임워크DPDK 인라인 파이프라인

DPDK rte_regexdev API의 핵심 구성 요소는 다음과 같습니다.

#include <rte_regexdev.h>
#include <rte_mbuf.h>
#include <rte_log.h>

#define REGEX_DEV_ID    0
#define REGEX_QP_ID     0
#define BATCH_SIZE      64
#define MAX_MATCHES     8

/* REE 디바이스 초기화 및 규칙 로드 */
static int init_ree_device(const char *rules_file)
{
    struct rte_regexdev_config cfg = {
        .nb_queue_pairs   = 4,
        .nb_max_matches   = MAX_MATCHES,
        .nb_rules         = 10000,
        .rule_db_len      = 0,      /* 자동 감지 */
        .dev_cfg_flags    = 0,
    };
    struct rte_regexdev_info dev_info;
    int ret;

    /* 디바이스 정보 조회 */
    ret = rte_regexdev_info_get(REGEX_DEV_ID, &dev_info);
    if (ret < 0) {
        RTE_LOG(ERR, USER1, "REE device info failed: %d\n", ret);
        return ret;
    }
    RTE_LOG(INFO, USER1, "REE device: %s, max_rules=%u\n",
            dev_info.driver_name, dev_info.max_rules);

    /* 디바이스 설정 */
    ret = rte_regexdev_configure(REGEX_DEV_ID, &cfg);
    if (ret < 0)
        return ret;

    /* 규칙 DB 업데이트 — 컴파일된 바이너리 규칙 로드 */
    struct rte_regexdev_rule *rules;
    uint32_t nb_rules;

    /* 규칙 파일 파싱 (실제 구현에서는 파일 I/O) */
    ret = load_compiled_rules(rules_file, &rules, &nb_rules);
    if (ret < 0)
        return ret;

    ret = rte_regexdev_rule_db_update(REGEX_DEV_ID,
                                       rules, nb_rules);
    if (ret < 0)
        return ret;

    ret = rte_regexdev_rule_db_compile_activate(REGEX_DEV_ID);
    if (ret < 0)
        return ret;

    /* 큐 페어 설정 */
    struct rte_regexdev_qp_conf qp_conf = {
        .nb_desc = 1024,
        .qp_conf_flags = RTE_REGEX_QUEUE_PAIR_CFG_OOS_F,
    };
    ret = rte_regexdev_queue_pair_setup(REGEX_DEV_ID,
                                         REGEX_QP_ID, &qp_conf);
    if (ret < 0)
        return ret;

    return rte_regexdev_start(REGEX_DEV_ID);
}

/* 패킷 배치를 REE 엔진에 제출하고 결과 수집 */
static int process_packet_batch(struct rte_mbuf **pkts,
                                uint16_t nb_pkts,
                                uint32_t *match_flags)
{
    struct rte_regex_ops *ops[BATCH_SIZE];
    struct rte_regex_ops *results[BATCH_SIZE];
    uint16_t enqueued, dequeued;
    int i;

    /* 검색 오퍼레이션 생성 */
    for (i = 0; i < nb_pkts && i < BATCH_SIZE; i++) {
        ops[i] = rte_malloc(NULL, sizeof(struct rte_regex_ops), 0);
        if (!ops[i])
            return -ENOMEM;

        ops[i]->mbuf     = pkts[i];
        ops[i]->group_id0 = 0;      /* 규칙 그룹 ID */
        ops[i]->user_id   = i;      /* 패킷 식별자 */
        ops[i]->req_flags = 0;
    }

    /* 배치 제출 (enqueue) */
    enqueued = rte_regexdev_enqueue_burst(REGEX_DEV_ID,
                                           REGEX_QP_ID,
                                           ops, nb_pkts);

    /* 결과 수집 (dequeue) — 폴링 루프 */
    dequeued = 0;
    while (dequeued < enqueued) {
        uint16_t n = rte_regexdev_dequeue_burst(
                         REGEX_DEV_ID, REGEX_QP_ID,
                         results + dequeued,
                         enqueued - dequeued);
        dequeued += n;
    }

    /* 매칭 결과 처리 */
    for (i = 0; i < dequeued; i++) {
        uint16_t nb_matches = results[i]->nb_matches;
        uint32_t pkt_idx    = results[i]->user_id;

        if (nb_matches > 0) {
            match_flags[pkt_idx] = 1;

            for (uint16_t m = 0; m < nb_matches; m++) {
                struct rte_regexdev_match *match;
                match = &results[i]->matches[m];
                RTE_LOG(DEBUG, USER1,
                        "pkt[%u] match: rule=%u off=%u len=%u\n",
                        pkt_idx, match->rule_id,
                        match->start_offset, match->len);
            }
        } else {
            match_flags[pkt_idx] = 0;
        }
        rte_free(results[i]);
    }

    return dequeued;
}
eventdev 연동: DPDK의 rte_event_regex_adapter를 사용하면 REE 엔진의 완료 이벤트를 eventdev 큐에 자동으로 전달할 수 있습니다. 이 방식은 폴링 루프 대신 이벤트 기반으로 CPU 효율을 높이며, 암호화(crypto)·압축(compress) 등 다른 하드웨어 가속기와 동일한 이벤트 파이프라인에서 조합할 수 있습니다.

Hyperscan + Intel QAT 가속

Hyperscan은 Intel이 개발한 고성능 정규식 매칭 라이브러리로, SIMD(SSE4.2/AVX2/AVX-512) 명령어를 활용한 멀티 패턴 매칭을 제공합니다. 전용 하드웨어가 아닌 CPU 기반이지만, 하드웨어 수준에 근접하는 성능을 달성합니다. Intel QAT(QuickAssist Technology)와 조합하면 암호 해제 + 정규식 매칭 파이프라인을 구성할 수 있습니다.

모드설명사용 사례
Block 모드단일 버퍼를 한 번에 스캔개별 패킷 페이로드 검사
Streaming 모드여러 버퍼에 걸친 연속 스캔 (상태 유지)TCP 스트림 재조립 후 검사
Vectored 모드비연속 버퍼 세트를 논리적으로 연결하여 스캔scatter-gather 버퍼 검사

Hyperscan의 핵심 장점은 다음과 같습니다.

Suricata에서 Hyperscan MPM을 활성화하는 설정 예제입니다.

# /etc/suricata/suricata.yaml — Hyperscan MPM 설정

# Multi-Pattern Matching 엔진 선택
mpm-algo: hs  # 'ac' (Aho-Corasick) 대신 'hs' (Hyperscan)

# 패턴 매칭 상세 설정
detect:
  profile: high       # high = 더 많은 메모리, 더 빠른 매칭
  sgh-mpm-context: full  # 시그니처 그룹별 독립 MPM 컨텍스트
  inspection-recursion-limit: 3000

# Hyperscan 관련 상세 설정
# Suricata 빌드 시 --enable-hyperscan 필요
# 의존성: libhs-dev (Intel Hyperscan 라이브러리)

# Intel QAT 암호 해제 가속 (AF_ALG 또는 OpenSSL QAT engine)
# TLS 복호화 → Hyperscan 매칭 파이프라인
app-layer:
  protocols:
    tls:
      enabled: yes
      detection-ports:
        dp: 443
      # QAT 가속 OpenSSL 엔진 사용 시 별도 설정 필요
# Suricata 빌드 시 Hyperscan 활성화
./configure --enable-hyperscan \
            --with-libhs-includes=/usr/include/hs \
            --with-libhs-libraries=/usr/lib/x86_64-linux-gnu

# Hyperscan 성능 벤치마크
# hsbench: Hyperscan 공식 벤치마크 도구
hsbench -e /path/to/patterns.db \
        -c /path/to/corpus/ \
        -T 8            # 8 스레드

# Intel QAT 디바이스 확인
lspci | grep "QuickAssist"
# 출력 예: 0000:6b:00.0 Co-processor: Intel Corporation
#          C62x Chipset QuickAssist Technology

# QAT 상태 확인
adf_ctl status
# 출력 예: qat_dev0 - type: c6xx, state: up

# QAT OpenSSL 엔진 설정 확인
openssl engine -t qatengine
# 출력 예: (qatengine) Reference implementation of QAT engine
#          [ available ]
QAT + Hyperscan 파이프라인: SSL/TLS Inspection 환경에서는 QAT가 암호 해제(Decryption)를 담당하고, 복호화된 평문(Plaintext)을 Hyperscan이 검사하는 2단계 파이프라인을 구성합니다. QAT 없이 CPU만으로 TLS 복호화 + 정규식 매칭을 수행하면 10Gbps 환경에서 처리량이 1~2Gbps로 급감할 수 있습니다.

Regex HW와 NGFW 파이프라인 통합 패턴

정규식 하드웨어 가속 엔진을 NGFW 파이프라인에 효율적으로 통합하려면 2단계 필터링 모델을 사용합니다. 모든 패킷을 하드웨어 정규식 엔진에 보내는 것은 비효율적이므로, 저비용 사전 필터(Pre-filter)로 후보를 먼저 선별하고, 후보 패킷만 정밀 매칭 엔진에 전달합니다.

단계처리 위치알고리즘비용정확도목적
1단계 — Pre-filterCPU (SIMD) 또는 NIC HW블룸 필터(Bloom Filter), 해시 매칭매우 낮음 (ns/pkt)위양성 있음 (false positive)빠른 거부 (fast reject)
2단계 — Exact MatchRegex HW 엔진DFA/NFA 정규식 매칭높음 (μs/pkt)정확정밀 시그니처 판정

이 2단계 모델의 핵심은 1단계에서 대부분의 정상 트래픽을 빠르게 통과시키고(95~99%), 의심 트래픽(1~5%)만 2단계 하드웨어 엔진으로 전달하는 것입니다.

통합 방식장점단점적합 환경
XDP/TC + Regex HW최소 레이턴시, 커널 바이패스 가능구현 복잡, BPF 제약SmartNIC/DPU 기반 인라인 DPI
NFQUEUE + Regex HW기존 Netfilter 파이프라인 재활용사용자 공간 복사 오버헤드기존 IDS/IPS에 HW 가속 추가
DPDK 인라인최고 처리량, zero-copy커널 바이패스로 모니터링 제한전용 DPI 어플라이언스
통합 설계 원칙: 2단계 모델에서 1단계 사전 필터의 품질이 전체 시스템 성능을 결정합니다. Hyperscan의 HS_FLAG_PREFILTER 플래그는 이 목적에 최적화되어 있으며, 사전 필터용 경량 DFA를 별도로 생성합니다. 사전 필터 히트율(Hit Rate)이 5%를 초과하면 블룸 필터 크기를 늘리거나 리터럴 추출 전략을 재검토해야 합니다.
NIC RX 1단계 Pre-filter Bloom Filter / Hash (SW SIMD 또는 HW) No Match → PASS 95~99% 2단계 Regex HW RXP / REE / Hyperscan (DFA/NFA 정밀 매칭) 1~5% No Match → PASS 위양성 Action 결정 DROP / LOG / ALERT (시그니처별 정책) Match NIC TX PASS DROP DPI 하드웨어 가속 파이프라인 — 2단계 필터링 모델 1단계: 저비용 사전 필터 (Bloom/Hash) 2단계: Regex HW 정밀 매칭 (RXP/REE/Hyperscan) 정상 트래픽 바이패스 경로 매칭 → 차단/로그/경고 Pre-filter 단계에서 대부분의 정상 트래픽(95~99%)을 바이패스하여 Regex HW 엔진 부하를 최소화 전체 처리량: 1단계 처리율에 의해 결정 (100Gbps+ 가능)

위 다이어그램은 2단계 DPI 파이프라인의 전체 흐름을 보여줍니다. 1단계 사전 필터에서 95~99%의 정상 트래픽을 즉시 통과시키고, 나머지 1~5%의 의심 트래픽만 2단계 Regex HW 엔진으로 전달합니다. 2단계에서도 위양성 패킷은 PASS로 처리되며, 실제 시그니처 매칭이 확인된 패킷만 DROP/LOG/ALERT 정책을 적용합니다.

처리량 산정: 2단계 모델의 전체 처리량은 1단계 사전 필터의 처리율에 의해 결정됩니다. 1단계가 100Gbps를 처리하고 히트율이 2%이면, 2단계 Regex HW 엔진은 2Gbps만 처리하면 됩니다. 따라서 1단계 블룸 필터 최적화(해시 함수 수, 비트 배열 크기)가 전체 시스템 성능의 핵심입니다.

상용 NGFW HW 아키텍처

상용 NGFW는 암호화·DPI 가속을 위해 크게 두 가지 하드웨어 처리 모델을 사용합니다:

구분인라인(Inline) 처리룩어사이드(Lookaside) 처리
패킷 경로패킷이 전용 HW를 통과하며 처리 (NIC → ASIC/FPGA → NIC)패킷을 별도 HW 엔진으로 보내고 결과를 돌려받음 (CPU ↔ 코프로세서)
지연최소 — 데이터 경로에 HW가 직접 위치복사/전송 오버헤드 발생 — PCIe 왕복
적용 예세션 오프로드, NAT rewrite, IPSec inline cryptoSSL/TLS 가속, AV 패턴 매칭, 압축
장점라인레이트 처리, CPU bypass 가능범용 CPU와 독립적 확장, 유연한 알고리즘 지원
단점ASIC/FPGA 설계 복잡, 새 프로토콜 지원 느림PCIe 대역폭 병목, 배치 처리 필요

대부분의 상용 NGFW는 두 모델을 혼합(Hybrid)하여 사용합니다. 아래 표는 벤더별 주요 기능의 inline/lookaside 분류입니다:

기능FortinetPalo AltoCheck PointJuniperLinux NGFW
세션 오프로드Inline (NP7)Inline (FE FPGA)Inline (SecureXL 커널)Inline (NP Express Path)Inline (eSwitch FDB)
NAT RewriteInline (NP7)Inline (FE FPGA)Inline (SecureXL)Inline (NP)Inline (eSwitch / flowtable)
IPSec 암·복호화Inline (NP7 ASIC)Lookaside (CPU AES-NI)Lookaside (CPU)Lookaside (SPC3 카드)Inline (NIC crypto) / Lookaside (QAT)
SSL/TLS 복호화Lookaside (SP5 ASIC)Lookaside (CPU AES-NI)Lookaside (CPU)Lookaside (SPC3 SSL Proxy)Lookaside (kTLS NIC / QAT)
IPS / App-IDLookaside (CP9 + CPU)Inline (CPU Single-Pass)Inline (CoreXL FW Instance)Inline (flowd)Lookaside (NFQUEUE → Suricata)
AV / DLP 패턴Lookaside (CP9)Inline (CPU Single-Pass)Inline (CoreXL fwd)Inline (flowd)Lookaside (Suricata)
처리 모델 요약Inline ASIC + Lookaside 코프로세서Inline FPGA + CPU 통합순수 SW (Inline 커널 가속)Inline NP + Lookaside SPC3Inline SmartNIC + Lookaside SW
Inline vs Lookaside 핵심 판별법: 패킷이 해당 HW를 반드시 통과해야 전달되면 inline, CPU가 패킷 데이터를 별도 엔진에 복사·위임하고 결과를 받으면 lookaside입니다. Inline은 라인레이트에 유리하고, lookaside는 CPU와 독립적으로 확장할 수 있습니다. 동일 벤더라도 기능에 따라 inline과 lookaside를 혼합하는 것이 일반적입니다.

암호화 오프로드 아키텍처 3분류

앞선 표에서 lookaside를 단일 카테고리로 분류했지만, 실제 구현을 살펴보면 lookaside 방식은 가속기의 물리적 위치와 버스 토폴로지에 따라 크게 두 가지로 나뉩니다. CPU중심 룩어사이드(CPU-Centric Lookaside)는 PCIe 카드 형태의 외장 가속기를, SoC중심 룩어사이드(SoC-Centric Lookaside)는 SoC 다이 내장 크립토 엔진을 사용합니다. 여기에 데이터 경로 자체에 암호화를 삽입하는 인라인(Inline) 방식까지 포함하면, 암호화 오프로드는 3분류로 정리됩니다.

각 아키텍처의 핵심 차이는 패킷 데이터가 암호화 엔진에 도달하는 경로결과가 반환되는 지연 시간입니다. 기존 전용 크립토 가속기 섹션의 HW 스펙표와 함께 참조하면 전체 그림을 파악할 수 있습니다.

CPU중심 룩어사이드(CPU-Centric Lookaside)

CPU중심 룩어사이드는 CPU가 호스트 메모리에 있는 패킷 데이터를 PCIe 버스를 통해 외장 가속기 카드에 전송하고, 가속기가 처리한 결과를 다시 PCIe DMA로 돌려받는 모델입니다. CPU가 submission ring에 작업을 큐잉하면, 가속기가 비동기로 처리한 뒤 completion ring을 통해 완료를 통보합니다.

CPU중심 룩어사이드 아키텍처: CPU와 PCIe 가속기 간 데이터 플로우 호스트 시스템 (Host) CPU crypto API 호출 호스트 메모리 패킷 버퍼 (DMA 영역) Submission Ring 작업 디스크립터 큐 Completion Ring 완료 통보 큐 PCIe Bus (Gen4/5 x16) PCIe 가속기 카드 AES-GCM 엔진 대칭키 처리 RSA/ECC 엔진 비대칭키 처리 내부 SRAM + DMA 컨트롤러 PCIe 인터페이스 DMA Req DMA Resp ① 작업 제출 ④ 완료 수신 ② DMA 전송 ③ HW 처리

대표 하드웨어:

커널 crypto API에 등록된 가속기의 우선순위 확인:

# 등록된 암호화 알고리즘과 우선순위 확인
cat /proc/crypto | grep -A4 "name.*gcm(aes)"
# 출력 예시: driver = qat_aes_gcm, priority = 4001
# 우선순위가 높을수록 먼저 선택됨 (SW fallback은 보통 100~200)

# QAT 디바이스 상태 확인
cat /sys/kernel/debug/qat_4xxx_0000:6b:00.0/fw_counters
/* CPU중심 룩어사이드: 비동기 콜백 패턴 */
struct aead_request *req = aead_request_alloc(tfm, GFP_ATOMIC);
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                          crypto_done_callback, &result);
aead_request_set_crypt(req, src_sg, dst_sg, payload_len, iv);
aead_request_set_ad(req, assoclen);

ret = crypto_aead_encrypt(req);
if (ret == -EINPROGRESS || ret == -EBUSY) {
    /* 가속기가 비동기 처리 중 — completion 대기 */
    wait_for_completion(&result.completion);
    ret = result.err;
}
/* QAT: PCIe DMA 왕복 지연 ~10-50μs 포함 */
CPU중심 룩어사이드 장단점
장점: ① PCIe 슬롯으로 독립 확장 가능 — CPU 교체 없이 가속 능력 증대 ② SR-IOV로 VM별 격리된 VF 제공 — 클라우드/가상화 환경에 유리 ③ 대용량 RSA/ECDHE 핸드셰이크 처리에서 CPU 부하 90%+ 절감
단점: ① PCIe 왕복 지연(~10-50μs)이 패킷당 추가 — 소형 패킷 다수 시 병목 ② DMA 매핑/해제 오버헤드 — dma_map_single() 호출 비용 ③ 별도 전원·냉각·슬롯 필요 — 임베디드/엣지에 부적합

SoC중심 룩어사이드(SoC-Centric Lookaside)

SoC중심 룩어사이드는 크립토 엔진이 SoC 다이 내부에 통합되어 있으며, CPU와 내부 버스(AXI/AHB/ACE)로 직접 연결됩니다. PCIe를 거치지 않으므로 DMA 왕복 지연이 크게 줄어들고, 별도 전원·슬롯이 필요 없어 임베디드·네트워크 장비에 널리 사용됩니다. CPU가 Job Ring(또는 Command Ring)에 작업을 큐잉하면, 내장 크립토 엔진이 내부 버스를 통해 메모리에서 직접 데이터를 읽어 처리합니다.

SoC중심 룩어사이드 아키텍처: SoC 다이 내부 CPU와 크립토 엔진 간 데이터 플로우 SoC 다이 (System-on-Chip) CPU 클러스터 ARM Cortex-A72 × 4~16 또는 MIPS64 / OCTEON TX2 공유 메모리 L3 캐시 + DDR 컨트롤러 Job Ring 디스크립터 저장 크립토 엔진 CAAM / OCTEON CPT AES·SHA·RSA·ECC HW 코어 내부 인터커넥트 (AXI / ACE-Lite / AMBA) Job Ring (입력) 작업 디스크립터 큐 Job Ring (출력) 완료 디스크립터 큐 네트워크 포트 SoC 내장 GbE / 10GbE ① 작업 제출 ② HW 처리 ③ 완료 내부 버스 지연: ~1-5μs (PCIe 대비 5-10배 짧음)

대표 하드웨어:

Device Tree 바인딩 예시 (NXP CAAM):

/* NXP Layerscape SoC — CAAM Device Tree 바인딩 */
crypto@1700000 {
    compatible = "fsl,sec-v5.4", "fsl,sec-v5.0",
                 "fsl,sec-v4.0";
    reg = <0x0 0x1700000 0x0 0x100000>;
    interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
    #address-cells = <1>;
    #size-cells = <1>;
    ranges = <0x0 0x0 0x1700000 0x100000>;

    /* Job Ring 0 */
    jr0: jr@10000 {
        compatible = "fsl,sec-v5.4-job-ring",
                     "fsl,sec-v4.0-job-ring";
        reg = <0x10000 0x10000>;
        interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
    };
    /* Job Ring 1 */
    jr1: jr@20000 {
        compatible = "fsl,sec-v5.4-job-ring";
        reg = <0x20000 0x10000>;
        interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
    };
};
SoC중심 룩어사이드 장단점
장점: ① 초저지연(1-5μs) — PCIe 왕복 불필요, 내부 버스 직접 접근 ② 전력 효율 — 별도 PCIe 카드 전원 불필요, 임베디드/엣지에 최적 ③ BOM 절감 — SoC 가격에 포함, 추가 부품 불필요
단점: ① 확장 불가 — SoC에 고정된 처리량이 상한, HW 교체 없이 증설 불가 ② 처리량 한계 — 서버급 가속기(100-200 Gbps) 대비 1-20 Gbps 수준 ③ SoC 벤더 종속 — 드라이버와 DT 바인딩이 벤더별로 상이

인라인 암호화(Inline Crypto)

인라인 암호화는 가속기가 네트워크 데이터 경로(data path) 자체에 위치하여, 패킷이 NIC/SmartNIC을 통과하는 과정에서 암호화·복호화가 수행됩니다. CPU는 암호 키 설정과 SA(Security Association) 구성만 담당하고, 실제 패킷 데이터에는 전혀 관여하지 않습니다. IPSec, MACsec, kTLS(커널 TLS) 3가지 프로토콜이 인라인 오프로드의 대표적 사례입니다.

인라인 암호화 아키텍처: NIC 데이터 경로에서 직접 암복호화 처리 Wire In NIC / SmartNIC (Inline Crypto Engine) IPSec 경로 ESP 암호화/복호화 + Anti-replay — xfrm offload 200 Gbps MACsec 경로 IEEE 802.1AE L2 암호화 — SecTAG + ICV 처리 라인레이트 kTLS 경로 TLS 레코드 암호화 — sendfile() zero-copy 지원 100 Gbps 컨트롤 플레인(Control Plane) SA/키 설정만 CPU에서 수행 — 데이터 경로 미관여 Wire Out 호스트 CPU 키 교환·SA 관리만 키·SA 설정 패킷 데이터가 호스트 메모리를 거치지 않음 → Zero-copy, CPU 부하 0%

대표 하드웨어:

인라인 IPSec 오프로드 설정 확인(상세는 kTLS 오프로드 섹션 참조):

# NIC의 inline crypto 기능 확인
ethtool -k eth0 | grep -E "esp-hw-offload|tls-hw"
# esp-hw-offload: on        ← IPSec inline 지원
# tls-hw-tx-offload: on     ← kTLS TX inline 지원
# tls-hw-rx-offload: on     ← kTLS RX inline 지원

# xfrm (IPSec) offload 설정 — SA에 offload 플래그 추가
ip xfrm state add src 10.0.0.1 dst 10.0.0.2 \
    proto esp spi 0x100 reqid 1 mode tunnel \
    aead "rfc4106(gcm(aes))" 0x$(xxd -l 20 -p /dev/urandom) 128 \
    offload dev eth0 dir out    # ← inline offload 핵심 옵션

# offload 상태 확인
ip xfrm state show | grep -A2 offload
인라인 암호화 장단점
장점: ① Zero-copy — 패킷 데이터가 호스트 메모리를 거치지 않아 CPU 부하 0% ② 라인레이트 — NIC ASIC이 와이어 속도로 처리, 100-400 Gbps 가능 ③ 극소 지연(~1μs 이하) — 데이터 경로에 직접 삽입
단점: ① 프로토콜 고정 — NIC 펌웨어가 지원하는 프로토콜(IPSec/MACsec/kTLS)만 가능 ② SA 수 제한 — NIC TCAM/메모리에 따라 SA 수천~수만 개 상한 ③ SSL Inspection 불가 — TLS 핸드셰이크·DPI는 인라인으로 처리할 수 없음 (lookaside 필수)

3종 아키텍처 종합 비교

CPU중심 룩어사이드, SoC중심 룩어사이드, 인라인 암호화 3종 비교 CPU중심 룩어사이드 CPU PCIe Bus PCIe 가속기 QAT / NITROX 지연: 10-50μs 처리량: 100-200 Gbps 확장: PCIe 슬롯 추가 SoC중심 룩어사이드 CPU AXI / AMBA 내장 크립토 CAAM / OCTEON 지연: 1-5μs 처리량: 1-100 Gbps 확장: SoC 교체 필요 인라인 암호화 CPU (미관여) NIC Inline Engine ConnectX-7 / E810 IPSec · MACsec · kTLS 데이터 경로 직접 처리 지연: <1μs 처리량: 라인레이트 확장: NIC 교체/추가 Wire Wire 지연 시간 스펙트럼 <1μs 1-5μs 10-50μs 50-200μs (SW) Inline SoC Lookaside CPU Lookaside SW Fallback 빠름 ← → 느림
항목CPU중심 룩어사이드SoC중심 룩어사이드인라인 암호화
가속기 위치PCIe 슬롯 (외장)SoC 다이 내부NIC/SmartNIC 데이터 경로
버스PCIe Gen4/5AXI / AMBA / ACEN/A (와이어 직접)
지연 시간10-50μs1-5μs<1μs
대칭키 처리량100-200 Gbps1-100 Gbps라인레이트 (100-400 Gbps)
CPU 오버헤드중간 (DMA 매핑 + 콜백)낮음 (Job Ring 관리)거의 없음 (SA 설정만)
프로토콜 유연성높음 (모든 crypto API 알고리즘)중간 (SoC 지원 알고리즘)낮음 (IPSec/MACsec/kTLS 고정)
확장성PCIe 슬롯 추가SoC 교체 필요NIC 교체/추가
대표 HWIntel QAT 8970/4xxx, NITROX VNXP CAAM, OCTEON CPT, CryptoCellConnectX-6 Dx/7, E810, Pensando DSC
주요 Linux 드라이버qat_4xxx, nitroxcaam, octeontx2-cpt, ccreemlx5_core, ice
주요 용도SSL 프록시, HSM, 대량 핸드셰이크임베디드 라우터, CPE, IoT 게이트웨이데이터센터 IPSec VPN, CDN kTLS

하드웨어별 아키텍처 분류 상세:

하드웨어아키텍처 분류버스대칭키 처리량RSA-2048 ops/sLinux 드라이버
Intel QAT 8970CPU중심 LookasidePCIe Gen3 x16200 Gbps140Kqat_c62x
Intel QAT 4xxx (SPR 내장)CPU중심 LookasidePCIe 도메인100 Gbps100Kqat_4xxx
Marvell NITROX VCPU중심 LookasidePCIe Gen3 x16100 Gbps100Knitrox
NXP CAAMSoC중심 LookasideAXI (SoC 내부)10-20 Gbps10Kcaam
Marvell OCTEON CPTSoC중심 LookasideAMBA (SoC 내부)100 Gbps50Kocteontx2-cpt
Broadcom SPUSoC중심 LookasideAXI (SoC 내부)10 Gbps10Kbcm_crypto_spu
ARM CryptoCellSoC중심 LookasideAHB (SoC 내부)1-5 Gbps5Kccree
NVIDIA ConnectX-7InlineN/A (와이어)400 GbpsN/Amlx5_core
Intel E810InlineN/A (와이어)100 GbpsN/Aice
AMD Pensando DSC-200InlineN/A (와이어)200 GbpsN/Aionic

리눅스 커널 Crypto API 매핑

리눅스 커널의 다양한 암호화 서브시스템은 3종 아키텍처를 각각 다른 경로로 활용합니다. 아래 표는 주요 서브시스템별 매핑을 보여줍니다:

서브시스템CPU중심 LookasideSoC중심 LookasideInline
crypto API
/proc/crypto
qat_aes_gcm (pri=4001)
비동기 aead/skcipher
caam-aes-gcm (pri=3000)
비동기 Job Ring
미사용 (데이터 경로 직접)
xfrm (IPSec)
ip xfrm
crypto API 경유
SW ESP + HW 암호화
crypto API 경유
SW ESP + HW 암호화
xfrm_offload
NIC이 ESP 전체 처리
kTLS
setsockopt(SOL_TLS)
미사용 (SW kTLS만)미사용 (SW kTLS만)tls_device_offload
NIC TX/RX 오프로드
MACsec
ip macsec
미사용미사용macsec_offload
NIC L2 암호화
dm-crypt
디스크 암호화
crypto API 경유crypto API 경유미사용

커널 crypto API의 우선순위 기반 자동 선택(fallback chain):

# /proc/crypto에서 동일 알고리즘의 우선순위 확인
# 우선순위가 높은 드라이버가 자동 선택됨
$ grep -B1 -A5 "gcm(aes)" /proc/crypto

name         : gcm(aes)
driver       : qat_aes_gcm           # ← QAT 가속기 (CPU중심 Lookaside)
priority     : 4001                    # ← 최우선
async        : yes

name         : gcm(aes)
driver       : caam-gcm-aes           # ← CAAM (SoC중심 Lookaside)
priority     : 3000
async        : yes

name         : gcm(aes)
driver       : generic-gcm-aesni      # ← CPU AES-NI (SW fallback)
priority     : 400
async        : no

# Fallback chain: QAT(4001) → CAAM(3000) → AES-NI(400) → generic(100)
# 가속기 장애 시 자동으로 다음 우선순위 드라이버로 전환

암호화 완료 모델: 동기·비동기·폴링

커널 crypto API에서 암호화 요청이 HW 가속기에 제출된 뒤 결과를 수신하는 방식은 크게 3가지로 나뉩니다: 동기(Synchronous), 비동기 인터럽트(Asynchronous Interrupt), 비동기 폴링(Asynchronous Polling). 각 모델은 지연 시간, CPU 활용률, 처리량 특성이 근본적으로 다르며, NGFW의 성능 프로파일을 결정하는 핵심 요소입니다.

동기 처리(Synchronous)

동기 모델에서 CPU는 암호화 함수를 호출한 뒤 결과가 반환될 때까지 블로킹됩니다. CPU 자체의 AES-NI/ARMv8-CE 명령어로 처리하는 경우가 대표적이며, 함수 호출과 반환이 동일 컨텍스트에서 완료됩니다.

/* 동기(Synchronous) 처리 — CPU 명령어(AES-NI) 직접 실행 */
struct skcipher_request *req = skcipher_request_alloc(tfm, GFP_KERNEL);
skcipher_request_set_crypt(req, src_sg, dst_sg, len, iv);

/* 콜백 없이 직접 호출 — 반환 시 이미 완료 */
ret = crypto_skcipher_encrypt(req);
/* ret == 0: 즉시 완료 (동기)
 * CPU AES-NI의 경우 /proc/crypto에서 async: no 표시 */

if (ret == 0) {
    /* 암호화 완료 — 결과가 dst_sg에 이미 기록됨 */
    process_encrypted_packet(dst_sg);
}
skcipher_request_free(req);
동기 모델의 특성: CPU가 암호화 연산을 직접 실행하므로 함수 호출 오버헤드 최소(DMA 매핑·인터럽트 없음)이지만, 연산 동안 해당 CPU 코어가 100% 점유됩니다. /proc/crypto에서 async: no로 표시되는 알고리즘이 이에 해당합니다. 소형 패킷(64-256B)에서는 HW 가속기의 DMA 셋업 오버헤드보다 빠를 수 있습니다.
비동기 인터럽트 처리(Asynchronous Interrupt-Driven)

비동기 인터럽트 모델은 커널 crypto API에서 가장 일반적인 HW 가속기 활용 패턴입니다. CPU가 요청을 가속기의 submission ring에 큐잉하면 즉시 반환되고, 가속기가 처리를 완료하면 인터럽트(IRQ)를 발생시켜 등록된 콜백 함수를 호출합니다.

동기·비동기 인터럽트·비동기 폴링 3종 처리 모델 타임라인 비교 암호화 완료 모델 3종 타임라인 비교 요청 제출 HW 처리 중 완료 ① 동기 (AES-NI) CPU 블로킹 (AES-NI 명령어 실행) ret = 0 ② 비동기 (인터럽트) 제출+DMA CPU 해방 (다른 패킷 처리 가능) -EINPROGRESS 가속기 HW 처리 (DMA → 암호화 → DMA) IRQ 콜백 완료 통보 ③ 비동기 (폴링) 제출+DMA -EINPROGRESS P P P P 가속기 HW 처리 완료! 처리 완료 P = completion ring 확인 (인터럽트 없음) 패킷당 지연 동기: 높음 (CPU 점유) 비동기IRQ: 중간 (IRQ 지연) 폴링: 최소 (즉시 감지) 처리량 (높을수록 좋음) 동기 비동기IRQ 폴링 CPU 오버헤드 동기: 100% (블로킹) IRQ: 최소 (콜백만) 폴링: 중간 (주기적 확인) 최적 시나리오 동기: 소형 패킷, SW 전용, 단순 암호화 IRQ: 범용 HW 가속, 대용량 배치 처리 폴링: 초저지연 NGFW, DPDK 연동

커널 crypto API에서 비동기 요청의 반환값 의미와 콜백 처리 흐름:

/*
 * crypto API 반환값 — 완료 모델을 결정하는 핵심
 *
 *  0            : 동기 완료 — 결과가 이미 준비됨
 * -EINPROGRESS  : 비동기 처리 시작됨 — 콜백으로 완료 통보 예정
 * -EBUSY        : 백로그(backlog) 큐에 진입 — 큐 공간 확보 후 처리 예정
 * -ENOSPC       : 큐 가득 참(백로그 미허용 시) — 호출자가 재시도해야 함
 * 기타 음수     : 오류 (키 설정 오류, 메모리 부족 등)
 */

/* ── 비동기 콜백 구조체 ── */
struct crypto_async_result {
    struct completion completion;   /* wait_for_completion() 대상 */
    int err;                        /* 콜백에서 설정되는 최종 에러 코드 */
};

/* ── 콜백 함수 — 가속기 인터럽트 핸들러에서 호출됨 ── */
static void crypto_op_complete(void *data, int err)
{
    struct crypto_async_result *result = data;
    /*
     * err == 0        : 암호화 성공
     * err == -EINPROGRESS : 백로그에서 꺼내어 처리 시작
     *                       (CRYPTO_TFM_REQ_MAY_BACKLOG 설정 시)
     * err < 0 (기타)  : HW 오류
     */
    if (err == -EINPROGRESS)
        return;  /* 아직 완료 아님 — 실제 완료 시 다시 호출됨 */

    result->err = err;
    complete(&result->completion);  /* 대기 중인 스레드 깨움 */
}

/* ── 요청 제출 — CRYPTO_TFM_REQ_MAY_BACKLOG 플래그 상세 ── */
struct aead_request *req = aead_request_alloc(tfm, GFP_ATOMIC);
aead_request_set_callback(req,
    CRYPTO_TFM_REQ_MAY_BACKLOG |   /* 큐 가득 차도 백로그 허용 */
    CRYPTO_TFM_REQ_MAY_SLEEP,      /* 콜백에서 sleep 가능 (프로세스 컨텍스트) */
    crypto_op_complete, &result);
aead_request_set_crypt(req, src_sg, dst_sg, payload_len, iv);
aead_request_set_ad(req, assoclen);

ret = crypto_aead_encrypt(req);
switch (ret) {
case 0:
    /* 동기 완료 — SW fallback이 선택된 경우 또는
     * 가속기가 즉시 처리 완료한 경우 */
    process_result(req);
    break;

case -EINPROGRESS:
    /* 비동기 처리 시작 — 가속기가 DMA로 데이터 전송 중
     * 완료 시 crypto_op_complete() 콜백 호출됨 */
    break;

case -EBUSY:
    /* 가속기 큐 가득 참 + 백로그에 진입
     * CRYPTO_TFM_REQ_MAY_BACKLOG 덕분에 거부되지 않음
     * 콜백이 두 번 호출됨:
     *   1차: err=-EINPROGRESS (백로그→실제 큐 이동 시)
     *   2차: err=0 (처리 완료 시) */
    break;

default:
    /* 오류 — 키 미설정, 메모리 부족, HW 장애 등 */
    pr_err("crypto op failed: %d\n", ret);
    break;
}

백로그(Backlog) 큐 동작 상세:

┌─────────────────────────────────────────────────────────┐
│              가속기 Submission Ring (크기: 512)            │
│  [req1] [req2] [req3] ... [req510] [req511] [req512]    │
│  ← 가득 참 (new request 도착)                            │
└─────────────────────────────────────────────────────────┘
                         │
    ┌────────────────────┼────────────────────┐
    │ MAY_BACKLOG 미설정  │  MAY_BACKLOG 설정   │
    ▼                    │                    ▼
 -ENOSPC 반환            │              -EBUSY 반환
 (호출자가 재시도)        │         (백로그 큐에 진입)
                         │                    │
                         │    ┌───────────────┘
                         │    ▼
                         │  Backlog Queue
                         │  [req513] [req514] ...
                         │    │
                         │    │  Ring 슬롯 빌 때
                         │    ▼
                         │  콜백(err=-EINPROGRESS)
                         │  → 실제 큐로 이동
                         │    │
                         │    │  HW 처리 완료
                         │    ▼
                         │  콜백(err=0)
                         │  → 최종 완료
                         └────────────────────
비동기 폴링 처리(Asynchronous Polling)

비동기 폴링 모델에서는 인터럽트 대신 CPU가 주기적으로 completion ring(또는 상태 레지스터)을 직접 확인합니다. 인터럽트 발생·처리·컨텍스트 전환 오버헤드를 제거하여 초저지연을 달성할 수 있지만, 폴링 동안 CPU 사이클을 소모합니다.

커널 6.0+에서 도입된 crypto_engine 폴링 모드와 DPDK 환경의 busy-polling이 대표적입니다:

비동기 인터럽트 방식과 폴링 방식의 세부 타이밍 비교 인터럽트 방식 — 완료 감지 타이밍 상세 CPU 요청 제출 다른 작업 수행 가능 (CPU 해방) HW DMA↓ 암호화 연산 DMA↑ IRQ ISR softirq 콜백 실행 ~2-5μs 오버헤드 총 지연: HW 처리 시간 + IRQ 오버헤드 + 콜백 실행 폴링 방식 — 완료 감지 타이밍 상세 CPU 요청 제출 P₁ P₂ P₃ P₄ Hit! 결과 처리 HW DMA↓ 암호화 연산 DMA↑ CQ 기록 IRQ 없음! 폴링 사이클 (간격: ~1-10μs) 총 지연: HW 처리 시간 + 최대 1 폴링 간격 (IRQ 오버헤드 제거) 완료 감지 지연 비교 인터럽트: HW 처리 IRQ 지연 콜백 → 총 ~15-55μs 폴링: HW 처리 poll → 총 ~11-15μs 폴링으로 IRQ 대비 30-70% 지연 감소

커널 crypto_engine 폴링 모드 — 커널 6.0+에서 struct crypto_engine은 가속기 드라이버에 폴링 기반 완료 처리를 지원합니다:

/*
 * crypto_engine 폴링 모드 (커널 6.0+)
 * drivers/crypto/crypto_engine.c
 *
 * 기본 인터럽트 모드 대비 폴링 모드 전환 조건:
 * 1. 고처리량 시나리오 (인터럽트 스톰 방지)
 * 2. 초저지연 요구 (IRQ 컨텍스트 전환 제거)
 */

/* ── 드라이버에서 폴링 모드 지원 등록 ── */
struct crypto_engine *engine;
engine = crypto_engine_alloc_init(dev, true);  /* rt=true: 실시간 우선순위 */

/* 폴링 기반 완료 처리 — 전용 kthread가 CQ를 확인 */
static int hw_accel_poll_completions(struct crypto_engine *engine)
{
    struct hw_completion_ring *cq = engine->priv;
    int completed = 0;

    /* completion ring의 유효한 엔트리를 순회 */
    while (cq->head != cq->tail) {
        struct crypto_async_request *req;
        struct hw_cq_entry *entry = &cq->entries[cq->head];

        /* 완료 여부 확인 (HW가 done 비트 설정) */
        if (!(READ_ONCE(entry->flags) & HW_CQ_DONE))
            break;

        req = entry->async_req;
        /* DMA 매핑 해제 */
        dma_unmap_sg(dev, req->src, sg_nents(req->src),
                     DMA_BIDIRECTIONAL);

        /* 콜백 호출 — 인터럽트 컨텍스트가 아닌
         * kthread 컨텍스트에서 실행 */
        crypto_finalize_request(engine, req, 0);

        cq->head = (cq->head + 1) % cq->ring_size;
        completed++;
    }
    return completed;
}

/*
 * 인터럽트 vs 폴링 전환 (적응형 모드)
 * 처리량이 임계치를 초과하면 자동으로 폴링 전환
 */
static irqreturn_t hw_accel_irq_handler(int irq, void *data)
{
    struct hw_accel_dev *hdev = data;

    if (hdev->completions_per_sec > POLL_THRESHOLD) {
        /* 고처리량 → 인터럽트 비활성화 + 폴링 모드 전환 */
        disable_irq_nosync(irq);
        hdev->polling = true;
        /* kthread가 폴링 루프 시작 */
        wake_up_process(hdev->poll_thread);
        return IRQ_HANDLED;
    }
    /* 일반 모드 — 인터럽트 기반 완료 */
    return hw_accel_process_irq(hdev);
}

DPDK / 유저스페이스 busy-polling — NGFW에서 DPDK 기반 데이터 플레인(VPP, Suricata AF_XDP)을 사용할 경우:

/*
 * DPDK cryptodev 폴링 모드 — 유저스페이스 busy-polling
 * rte_cryptodev_dequeue_burst()로 완료된 작업 수집
 */

/* 1. 암호화 요청 배치 제출 (enqueue) */
uint16_t enqueued = rte_cryptodev_enqueue_burst(
    cdev_id,        /* crypto device ID */
    qp_id,          /* queue pair */
    crypto_ops,     /* 요청 배열 */
    nb_ops          /* 배치 크기 (32-256) */
);

/* 2. busy-polling으로 완료 수집 (dequeue) */
uint16_t dequeued;
do {
    dequeued = rte_cryptodev_dequeue_burst(
        cdev_id, qp_id,
        completed_ops,  /* 완료된 요청 배열 */
        MAX_BURST       /* 최대 수집 수 */
    );
    /*
     * dequeued == 0: 아직 완료된 작업 없음 → 재폴링
     * 인터럽트·컨텍스트 전환 없이 즉시 재확인
     * → 지연 최소화, 단 CPU 100% 사용
     */
} while (dequeued == 0);

/* 3. 완료된 작업 처리 */
for (int i = 0; i < dequeued; i++) {
    if (completed_ops[i]->status ==
        RTE_CRYPTO_OP_STATUS_SUCCESS) {
        /* 암호화 완료 — 다음 파이프라인 단계로 전달 */
        forward_packet(completed_ops[i]->sym->m_dst);
    }
}
완료 모델 종합 비교
항목동기(Synchronous)비동기 인터럽트(Async IRQ)비동기 폴링(Async Polling)
완료 감지 방식함수 반환 (ret == 0)IRQ → softirq → 콜백CPU가 completion ring 직접 확인
반환값0 (즉시 완료)-EINPROGRESS-EINPROGRESS
CPU 동작블로킹 (연산 직접 수행)해방 (콜백 대기)폴링 루프 (주기적 확인)
패킷당 지연~0.5-2μs (AES-NI)
~5-20μs (SW SHA)
HW처리 + IRQ 2-5μsHW처리 + 최대 1 폴링간격
초당 처리량CPU 코어 × 클럭 한계높음 (CPU 병렬 활용)최고 (IRQ 제거 + 배치)
CPU 오버헤드100% (코어 점유)최소 (콜백 시만)중간 (폴링 사이클)
인터럽트 부하없음높음 (요청당 1회)없음
배치 처리불가가능 (NAPI식 coalescing)최적 (burst dequeue)
컨텍스트호출자 컨텍스트softirq / taskletkthread / 유저스페이스
/proc/crypto 표시async: noasync: yesasync: yes
대표 드라이버aesni-intel, ghash-clmulniqat_4xxx, caam, nitroxDPDK cryptodev, QAT UIO
최적 시나리오소형 패킷, 단순 대칭키
SW 전용 환경
범용 HW 가속
SSL Inspection 핸드셰이크
초저지연 NGFW
DPDK/VPP 데이터 플레인
적응형 인터럽트 병합과 하이브리드 폴링

실무 NGFW에서는 순수 인터럽트나 순수 폴링이 아닌, 트래픽 부하에 따라 동적으로 전환하는 적응형(adaptive) 모델을 사용합니다. 리눅스 커널 NAPI(New API)가 네트워크 드라이버에서 사용하는 것과 동일한 원리입니다:

                     트래픽 부하
        낮음 ◀──────────────────────────▶ 높음
        ┌───────────┬───────────┬──────────────┐
 완료   │ 인터럽트   │ 인터럽트   │    폴링      │
 감지   │ (즉시)     │ (병합)    │ (busy-poll)  │
 방식   │           │           │              │
        ├───────────┼───────────┼──────────────┤
 IRQ    │ 요청당     │ N개 묶음  │   비활성화    │
 빈도   │ 1회       │ (coalesce)│   (0회)      │
        ├───────────┼───────────┼──────────────┤
 CPU    │ 최소       │ 낮음      │   전용 코어   │
 사용   │           │           │   100%       │
        ├───────────┼───────────┼──────────────┤
 지연   │ ~5μs      │ ~10-30μs  │   <1μs       │
        │           │ (병합     │   (즉시      │
        │           │  대기시간) │    감지)     │
        └───────────┴───────────┴──────────────┘

        ◀─ 유휴 시    적응형 전환 ──────▶ 포화 시
/*
 * 적응형 인터럽트/폴링 전환 — NAPI식 crypto 완료 처리
 * 고처리량 시 인터럽트 스톰을 방지하고 배치 처리 효율 극대화
 */
#define POLL_BUDGET      64    /* 한 번의 폴링에서 최대 처리 수 */
#define IRQ_TO_POLL_THRESH  1000  /* IRQ/초 임계치 → 폴링 전환 */
#define POLL_TO_IRQ_THRESH  100   /* 폴링 공회전 → IRQ 복귀 */

/* ── 인터럽트 핸들러: 고부하 감지 시 폴링 전환 ── */
static irqreturn_t crypto_irq_handler(int irq, void *data)
{
    struct crypto_hw_queue *q = data;

    q->irq_count++;

    if (q->irq_count > IRQ_TO_POLL_THRESH) {
        /* 인터럽트 빈도 과다 → 폴링 모드 전환 */
        disable_irq_nosync(irq);
        q->mode = CRYPTO_MODE_POLL;
        napi_schedule(&q->napi);   /* 폴링 스케줄링 */
        return IRQ_HANDLED;
    }

    /* 일반 모드: 개별 완료 처리 */
    crypto_process_completions(q, 1);
    return IRQ_HANDLED;
}

/* ── NAPI식 폴링 핸들러 ── */
static int crypto_napi_poll(struct napi_struct *napi, int budget)
{
    struct crypto_hw_queue *q =
        container_of(napi, struct crypto_hw_queue, napi);
    int completed = 0;

    /* completion ring에서 완료된 항목 배치 수집 */
    completed = crypto_poll_completions(q, budget);

    if (completed < budget) {
        /*
         * 배치 미달 → 트래픽 감소 감지
         * 폴링 종료 + 인터럽트 복원
         */
        q->idle_polls++;
        if (q->idle_polls > POLL_TO_IRQ_THRESH) {
            napi_complete(napi);
            q->mode = CRYPTO_MODE_IRQ;
            q->irq_count = 0;
            q->idle_polls = 0;
            enable_irq(q->irq_num);  /* 인터럽트 복원 */
        }
    } else {
        q->idle_polls = 0;  /* 배치 꽉 참 → 계속 폴링 */
    }
    return completed;
}

인터럽트 병합(Interrupt Coalescing) 설정 — QAT 가속기 예시:

# QAT 인터럽트 병합 설정
# /etc/sysconfig/qat 또는 sysfs 경로

# 병합 타이머: N μs 동안 완료를 모아서 단일 IRQ 발생
echo 10 > /sys/kernel/debug/qat_4xxx_0000:6b:00.0/irq_coal_timer_ns
# 10μs 간격 → 초당 최대 100K IRQ (vs 병합 없이 수백만)

# 병합 카운트: N개 완료마다 IRQ 1회
echo 32 > /sys/kernel/debug/qat_4xxx_0000:6b:00.0/irq_coal_count
# 32개 완료 묶음 → IRQ 횟수 1/32로 감소

# 현재 모드 확인
cat /sys/kernel/debug/qat_4xxx_0000:6b:00.0/irq_mode
# adaptive / timer / count / poll

# ethtool로 NIC crypto 인터럽트 병합 설정 (ConnectX-7)
ethtool -C eth0 rx-usecs 10 tx-usecs 10
# 10μs 간격으로 RX/TX 인터럽트 병합
NGFW 시나리오별 완료 모델 선택 가이드
① SSL Inspection 프록시: 비동기 인터럽트 — RSA/ECDHE 핸드셰이크는 연산 시간이 길어(~ms) 폴링의 CPU 낭비가 큼. QAT의 인터럽트 병합(32개 묶음)으로 IRQ 부하를 제어하면서 CPU를 DPI에 할당.
② IPSec VPN 게이트웨이(100G+): 인라인(NIC 직접 처리)이 이상적이나, lookaside 사용 시 비동기 폴링 — 소형 ESP 패킷 대량 처리에서 IRQ 스톰 방지와 초저지연 달성.
③ DPDK/VPP 데이터 플레인: busy-polling 전용 — 전용 CPU 코어에서 rte_cryptodev_dequeue_burst() 무한 루프. IRQ 완전 비활성화로 최대 처리량.
④ 임베디드 CPE(1-10G): 비동기 인터럽트 — 전력 제약으로 폴링의 CPU 100% 점유 불가. SoC CAAM Job Ring 인터럽트가 최적.
⑤ 적응형 NGFW: 인터럽트 + 폴링 자동 전환 — 유휴 시 인터럽트(전력 절약), 포화 시 폴링(최대 성능). ethtool -C adaptive 모드 활성화.

아키텍처 선택 가이드

시나리오별로 최적의 암호화 오프로드 아키텍처를 선택하는 기준:

시나리오추천 아키텍처근거
데이터센터 IPSec VPN
사이트 간 100G+ 터널
인라인 (ConnectX-7, E810)라인레이트 ESP 처리, CPU 부하 0%, SA 수 충분
SSL/TLS 프록시 (NGFW)
수만 CPS 핸드셰이크
CPU중심 Lookaside (QAT)RSA/ECDHE 비대칭 연산 대량 처리, SR-IOV 멀티테넌트
CDN / 웹서버 kTLS
sendfile() 대량 전송
인라인 (ConnectX-6 Dx)TLS 레코드 zero-copy TX, sendfile() 성능 극대화
임베디드 라우터 / CPE
1-10G IPSec, 저전력
SoC중심 Lookaside (CAAM)추가 HW 불필요, 저전력, BOM 최소화
IoT 게이트웨이
TLS 종단, 저전력
SoC중심 Lookaside (CryptoCell)TrustZone 연동 키 보호, mW급 전력
클라우드 VM 암호화
VM별 격리 필요
CPU중심 Lookaside (QAT VF)SR-IOV VF per VM, 격리된 crypto 인스턴스
MACsec L2 보안
DC 패브릭 암호화
인라인 (ConnectX-7)L2 와이어스피드 암호화, NIC에서 완전 처리
디스크 암호화 (dm-crypt)CPU중심 or SoC중심 Lookasidecrypto API 경유, 블록 단위 비동기 처리
하이브리드 전략: 실무에서는 단일 아키텍처만 사용하는 경우가 드뭅니다. 예를 들어 NGFW 어플라이언스에서 IPSec bulk 암호화는 인라인(NIC), SSL Inspection 핸드셰이크는 CPU중심 룩어사이드(QAT), SoC 내장 엔진은 관리 플레인 TLS로 3종을 동시에 활용하는 것이 일반적입니다. 관련 HW 스펙 상세는 전용 크립토 가속기 섹션, kTLS 오프로드 상세는 kTLS HW 오프로드 섹션을 참조하세요.

하드웨어 이벤트 스케줄러 (Intel DLB / Marvell SSO)

NGFW 데이터 플레인에서 수백만 플로우를 다수의 CPU 코어에 효율적으로 분배하는 것은 핵심 과제입니다. RSS(Receive Side Scaling)는 해시 기반 정적 분배만 가능하여 코어 간 부하 불균형이 발생하고, 소프트웨어 큐 관리는 락 경합과 캐시 바운싱 오버헤드를 유발합니다. 하드웨어 이벤트 스케줄러(Hardware Event Scheduler)는 이 문제를 전용 ASIC/SoC 블록으로 해결합니다.

대표적인 HW 이벤트 스케줄러로 Intel의 DLB(Dynamic Load Balancer)와 Marvell의 SSO(Schedule/Synchronize/Order)가 있으며, 둘 다 원자적 플로우 스케줄링, 순서 보장, 동적 부하 분산을 하드웨어 수준에서 제공합니다.

이벤트 스케줄러 핵심 개념

HW 이벤트 스케줄러는 패킷을 직접 전달하지 않고, 이벤트(Event) 단위로 작업을 추상화합니다. 하나의 이벤트는 패킷 도착, 타이머 만료, 크립토 완료 등 다양한 소스에서 발생하며, 스케줄러가 이를 워커 코어(Worker Core)에 분배합니다.

하드웨어 이벤트 스케줄러: 이벤트 소스 → HW 스케줄러 → 워커 코어 분배 구조 하드웨어 이벤트 스케줄러 아키텍처 개요 이벤트 소스 NIC RX 패킷 수신 이벤트 Crypto 완료 암복호화 완료 Timer 세션 타임아웃 SW 이벤트 파이프라인 단계 전달 HW 이벤트 스케줄러 Intel DLB / Marvell SSO Atomic 큐 Ordered 큐 Parallel 큐 스케줄링 로직 플로우 해시 매칭 부하 균형 분배 순서 보장 (reorder) 원자성 보장 (lock-free) Atomic: 동일 플로우 → 동일 코어 (lock-free) Ordered: 병렬 처리 후 원래 순서로 재정렬 워커 코어 Core 0: 방화벽 룰 conntrack + ACL Core 1: IPS/DPI Suricata 시그니처 Core 2: 암호화 SSL/TLS 복호화 Core 3: NAT/QoS NAT rewrite + 큐잉 Core N: 동적 할당 부하에 따라 확장 3종 스케줄링 모드 비교 Atomic (원자적) 동일 flow_id → 동일 코어 한 번에 하나만 처리 (lock-free) 용도: conntrack, NAT 상태 갱신 세션별 순서 보장 필수 시 락 경합 제거 ✓ Ordered (순서 보장) 여러 코어에서 병렬 처리 출력 시 원래 순서로 재정렬 용도: IPSec ESP 암복호화 패킷 순서 유지 + 병렬 처리 HW 재정렬 버퍼 ✓ Parallel (병렬) 순서·원자성 제약 없음 최대 처리량 (fan-out) 용도: 무상태 패턴 매칭 AV 스캔, 로깅, 통계 수집 최대 병렬성 ✓

3종 스케줄링 모드가 NGFW 파이프라인에서 각각 다른 단계에 적용됩니다:

스케줄링 모드동작 방식NGFW 적용 단계핵심 보장
Atomic동일 flow_id의 이벤트가 동시에 하나의 코어에서만 처리됨. 다른 코어는 해당 플로우를 볼 수 없음conntrack 갱신, NAT 상태 변경, 세션 테이블 writeLock-free 상호 배제
Ordered여러 코어에서 병렬 처리하되, 출력 시 입력 순서대로 HW가 재정렬IPSec ESP 암복호화, TCP 스트림 재조립, QoS 큐잉패킷 순서 보장 + 병렬 처리
Parallel순서·원자성 제약 없이 가용한 코어에 즉시 분배IPS 시그니처 매칭, AV 스캔, 로깅, 미러링최대 처리량

Intel DLB (Dynamic Load Balancer)

Intel DLB(이전 명칭 HQM — Hardware Queue Manager)는 4th Gen Xeon(SPR) 이후 CPU에 내장된 하드웨어 이벤트 스케줄러입니다. PCIe 디바이스로도 출시되었으며(DLB 2.0/2.5), DPDK eventdev 라이브러리를 통해 VPP, DPDK 기반 NGFW, Open vSwitch 등에서 활용됩니다.

Intel DLB 내부 아키텍처: Producer → Credit → QID → CQ → Consumer 플로우 Intel DLB 2.5 내부 아키텍처 Producer NIC RX Core DPDK rte_eth_rx Crypto 완료 QAT dequeue Timer 이벤트 세션 만료 DLB 2.5 HW Engine Credit 관리기 흐름 제어 (배압) Directed Port/Queue LB QID (Queue ID) QID 0: Atomic (FW) QID 1: Ordered (Crypto) QID 2: Parallel (IPS) 최대 128 QID 스케줄링 엔진 • 플로우 해시 → 코어 매핑 • Atomic lock 관리 • Reorder 버퍼 (Ordered) • Credit 기반 배압 (backpressure) • 부하 균형 (WRR 가중치) CQ (Consumer Queue) — 워커별 1개 CQ 0 CQ 1 CQ 2 CQ 3 CQ 인터럽트 또는 폴링으로 이벤트 수신 (최대 64 CQ) Consumer (Worker) Worker Core 0-N DPDK eventdev poll DLB 2.5: 96 QID × 64 CQ, 4K 플로우 추적, ~200ns 스케줄링 지연

DLB 핵심 사양:

항목DLB 1.0 (PCIe)DLB 2.0 (SPR 내장)DLB 2.5 (EMR/GNR)
QID (Queue ID)326496
CQ (Consumer Queue)646464
Directed Port646496
플로우 추적2K4K4K
스케줄링 지연~300ns~200ns~200ns
이벤트 처리량~200M events/s~400M events/s~500M events/s
Credit 풀8K8K16K
Linux 드라이버dlb (out-of-tree)dlb2 (커널 5.18+)dlb2 (커널 6.2+)
SR-IOV VF161616

DLB의 핵심 구성 요소:

DPDK eventdev를 통한 DLB 설정과 NGFW 파이프라인 구성:

/*
 * DPDK eventdev API로 DLB 기반 NGFW 파이프라인 구성
 * rte_event_dev → rte_event_queue → rte_event_port 매핑
 */
#include <rte_eventdev.h>
#include <rte_event_eth_rx_adapter.h>
#include <rte_event_crypto_adapter.h>

/* 1. DLB eventdev 초기화 */
struct rte_event_dev_config dev_conf = {
    .nb_event_queues = 4,        /* QID 4개 (FW/IPS/Crypto/TX) */
    .nb_event_ports = 8,         /* 워커 코어 8개 */
    .nb_events_limit = 4096,     /* 최대 동시 이벤트 수 */
    .nb_event_queue_flows = 1024,/* 플로우 해시 엔트리 수 */
    .nb_event_port_dequeue_depth = 32,
    .nb_event_port_enqueue_depth = 32,
};
rte_event_dev_configure(evdev_id, &dev_conf);

/* 2. 파이프라인 단계별 QID 설정 */
struct rte_event_queue_conf q_conf;

/* QID 0: 방화벽 (Atomic — conntrack 상태 보호) */
q_conf.schedule_type = RTE_SCHED_TYPE_ATOMIC;
q_conf.priority = RTE_EVENT_DEV_PRIORITY_HIGHEST;
q_conf.nb_atomic_flows = 1024;   /* 동시 추적 플로우 수 */
rte_event_queue_setup(evdev_id, 0, &q_conf);

/* QID 1: IPSec 암복호화 (Ordered — 순서 보장 + 병렬) */
q_conf.schedule_type = RTE_SCHED_TYPE_ORDERED;
q_conf.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
rte_event_queue_setup(evdev_id, 1, &q_conf);

/* QID 2: IPS/DPI (Parallel — 최대 처리량) */
q_conf.schedule_type = RTE_SCHED_TYPE_PARALLEL;
rte_event_queue_setup(evdev_id, 2, &q_conf);

/* QID 3: TX (Directed — 특정 TX 코어로 직접 전달) */
/* Directed는 별도 API로 설정 */

/* 3. 워커 포트 설정 — 각 코어에 CQ 바인딩 */
struct rte_event_port_conf p_conf = {
    .dequeue_depth = 32,
    .enqueue_depth = 32,
    .new_event_threshold = 128,  /* credit 기반 배압 임계치 */
};
for (int i = 0; i < 8; i++) {
    rte_event_port_setup(evdev_id, i, &p_conf);
    /* 포트 i → QID 0,1,2 매핑 (어떤 단계든 처리 가능) */
    rte_event_port_link(evdev_id, i, queues, priorities, 3);
}

/* 4. NIC RX → DLB 이벤트 어댑터 연결 */
rte_event_eth_rx_adapter_create(rx_adapter_id, evdev_id, &p_conf);
rte_event_eth_rx_adapter_queue_add(rx_adapter_id,
    eth_port_id, -1, /* 모든 RX 큐 */
    &(struct rte_event_eth_rx_adapter_queue_conf){
        .ev.queue_id = 0,    /* 첫 단계: FW QID */
        .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
        .ev.flow_id = 0,     /* RSS 해시를 flow_id로 사용 */
    });
rte_event_eth_rx_adapter_start(rx_adapter_id);

/* 5. 워커 루프 — 이벤트 수신·처리·전달 */
static void worker_loop(uint8_t port_id)
{
    struct rte_event events[32];
    while (!quit) {
        uint16_t nb = rte_event_dequeue_burst(
            evdev_id, port_id, events, 32, 0 /* no wait */);

        for (int i = 0; i < nb; i++) {
            struct rte_mbuf *pkt = events[i].mbuf;
            uint8_t cur_qid = events[i].queue_id;

            switch (cur_qid) {
            case 0: /* 방화벽 단계 — Atomic */
                if (firewall_check(pkt) == FW_PASS) {
                    /* 다음 단계(Crypto)로 전달 */
                    events[i].queue_id = 1;
                    events[i].op = RTE_EVENT_OP_FORWARD;
                } else {
                    rte_pktmbuf_free(pkt);
                    events[i].op = RTE_EVENT_OP_RELEASE;
                }
                break;

            case 1: /* IPSec 단계 — Ordered */
                ipsec_process(pkt);
                events[i].queue_id = 2;
                events[i].op = RTE_EVENT_OP_FORWARD;
                /* DLB가 자동으로 원래 순서 복원 */
                break;

            case 2: /* IPS/DPI 단계 — Parallel */
                ips_inspect(pkt);
                /* TX로 직접 전송 */
                rte_eth_tx_burst(tx_port, 0, &pkt, 1);
                events[i].op = RTE_EVENT_OP_RELEASE;
                break;
            }
        }
        rte_event_enqueue_burst(evdev_id, port_id, events, nb);
    }
}
# DLB 디바이스 확인
lspci | grep -i "dynamic load balancer"
# 6b:00.0 System peripheral: Intel Corporation
#         Dynamic Load Balancer (DLB) [8086:2710]

# 커널 드라이버 로드
modprobe dlb2
ls /dev/dlb*    # /dev/dlb0, /dev/dlb1, ...

# sysfs에서 DLB 리소스 확인
cat /sys/class/dlb2/dlb0/total_resources
# num_sched_domains: 32
# num_ldb_queues: 96
# num_ldb_ports: 64
# num_dir_ports: 96
# num_ldb_credits: 16384

# DPDK에서 DLB eventdev 바인딩
dpdk-devbind.py -b vfio-pci 0000:6b:00.0
# EAL 파라미터
--vdev=event_dlb2 --allow=0000:6b:00.0

Marvell OCTEON SSO (Schedule/Synchronize/Order)

Marvell OCTEON SSO는 OCTEON TX2/CN10K SoC에 내장된 하드웨어 이벤트 스케줄러입니다. Intel DLB와 유사한 기능을 제공하지만, SoC 내부의 모든 HW 가속기(크립토, 정규식, 압축)와 내부 버스로 직접 연동되는 것이 핵심 차이입니다. 패킷이 NIC에서 수신되면 SSO를 거쳐 CPU 코어에 분배되고, 크립토 처리 완료 후 다시 SSO로 돌아와 다음 단계 코어로 전달됩니다.

OCTEON CN10K SSO: SoC 내부 HW 가속기 통합 이벤트 스케줄링 OCTEON CN10K SoC RPM 네트워크 포트 25/50/100G RX → WQE 생성 패킷 수신 시 자동으로 SSO에 이벤트 제출 WQE SSO (Schedule / Synchronize / Order) SSOW (Workslot) 코어별 1개 할당 GET_WORK / ADD_WORK SWTAG (모드 전환) GWS (Group/Queue) 최대 256 그룹 그룹별 스케줄 타입 8단계 우선순위 태그 기반 스케줄링 엔진 tag = {flow_hash, sched_type} → 코어 결정, lock-free 보장 Atomic Ordered Untagged CPU 클러스터 ARM Neoverse N2 × 24 Core 0 Core 1 Core 2 Core 3 … × 24 각 코어에 SSOW 1개 MMIO GET_WORK 폴링 이벤트 SoC 내장 HW 가속기 (SSO 직접 연동) CPT (Crypto) AES/SHA/RSA 완료 → SSO 이벤트 REE (RegEx) IPS 시그니처 매칭 완료 → SSO 이벤트 ZIP (압축) deflate/zlib 완료 → SSO 이벤트 TIM (Timer) HW 타이머 휠 만료 → SSO 이벤트 NIX TX 패킷 송신 SSO에서 직접 TX SSO 핵심 차별점: 모든 HW 가속기 완료가 자동으로 SSO 이벤트로 변환 CPU가 가속기 완료를 폴링할 필요 없음 → 완전한 이벤트 드리븐 파이프라인

SSO 핵심 사양 (CN10K 기준):

항목OCTEON TX2 (CN96xx)CN10K (CN106xx)
SSO 그룹 (큐)256256
SSOW (Workslot)코어당 1개 (최대 36)코어당 1개 (최대 24)
스케줄링 모드Atomic, Ordered, UntaggedAtomic, Ordered, Untagged
태그 비트32-bit32-bit
우선순위 레벨88
이벤트 처리량~300M events/s~500M events/s
HW 가속기 연동CPT, ZIP, TIM, REECPT, ZIP, TIM, REE, ML(추론)
Linux 드라이버octeontx2-ssopf (커널 5.14+)octeontx2-ssopf (커널 6.1+)
DPDK eventdev 지원event_octeontx2event_cnxk

SSO의 DLB 대비 핵심 차별점:

SSO를 활용한 NGFW 이벤트 드리븐 파이프라인:

/*
 * OCTEON CN10K SSO 기반 NGFW 파이프라인
 * DPDK eventdev API (event_cnxk 드라이버)
 *
 * 파이프라인: NIC RX → [SSO] → FW(Atomic) → [SSO] →
 *            CPT(Crypto) → [SSO] → IPS(Ordered) → TX
 */

/* 1. SSO 이벤트 수신 — MMIO GET_WORK */
static void sso_worker_loop(uint8_t port_id)
{
    struct rte_event ev;
    while (!quit) {
        /* SSO에서 이벤트 수신 (HW 폴링, ~10ns 지연) */
        if (rte_event_dequeue_burst(evdev_id, port_id,
                                     &ev, 1, 0) == 0)
            continue;

        struct rte_mbuf *pkt = ev.mbuf;
        uint32_t tag = ev.flow_id;  /* 플로우 해시 */

        switch (ev.queue_id) {
        case SSO_GRP_FIREWALL:  /* Atomic 모드 */
            /*
             * 동일 tag(flow)의 이벤트는 이 코어에서만 처리됨
             * → conntrack 조회/갱신에 락 불필요!
             */
            if (conntrack_lookup(tag, pkt) == CT_NEW) {
                conntrack_insert(tag, pkt);  /* lock-free */
            }
            if (!acl_check(pkt)) {
                rte_pktmbuf_free(pkt);
                ev.op = RTE_EVENT_OP_RELEASE;
                break;
            }

            /* IPSec 필요 시 → CPT(크립토)로 전달 */
            if (needs_ipsec(pkt)) {
                /*
                 * SSO → CPT 직접 전달 (CPU 미개입)
                 * CPT 완료 시 자동으로 SSO 이벤트 재생성
                 * → SSO_GRP_POST_CRYPTO 그룹으로 도착
                 */
                submit_to_cpt(pkt, SSO_GRP_POST_CRYPTO);
                ev.op = RTE_EVENT_OP_RELEASE;
            } else {
                ev.queue_id = SSO_GRP_IPS;
                ev.op = RTE_EVENT_OP_FORWARD;
                /* SWTAG: Atomic → Ordered 전환 */
                ev.sched_type = RTE_SCHED_TYPE_ORDERED;
            }
            break;

        case SSO_GRP_POST_CRYPTO:  /* CPT 완료 이벤트 */
            /*
             * CPU가 CPT를 폴링하지 않음!
             * HW가 암호화 완료 → SSO에 이벤트 자동 생성
             */
            ev.queue_id = SSO_GRP_IPS;
            ev.sched_type = RTE_SCHED_TYPE_ORDERED;
            ev.op = RTE_EVENT_OP_FORWARD;
            break;

        case SSO_GRP_IPS:  /* Ordered 모드 */
            ips_pattern_match(pkt);
            /* NIX TX로 직접 전송 — 순서 자동 보장 */
            ev.queue_id = SSO_GRP_TX;
            ev.op = RTE_EVENT_OP_FORWARD;
            break;
        }

        rte_event_enqueue_burst(evdev_id, port_id, &ev, 1);
    }
}

/* 2. HW 타이머를 이용한 세션 타임아웃 */
static void setup_session_timeout(uint32_t flow_tag,
                                   uint64_t timeout_ns)
{
    /*
     * OCTEON TIM(Timer Wheel)에 타이머 등록
     * 만료 시 SSO 이벤트로 자동 변환 → CPU 인터럽트 불필요
     */
    struct rte_event_timer tim = {
        .ev.queue_id = SSO_GRP_TIMEOUT,
        .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
        .ev.flow_id = flow_tag,
        .timeout_ticks = timeout_ns / tim_tick_ns,
        .state = RTE_EVENT_TIMER_ARMED,
    };
    rte_event_timer_arm_burst(timer_adapter_id, &tim, 1);
    /* timeout_ns 후 SSO_GRP_TIMEOUT에 이벤트 도착 */
}

DLB vs SSO 종합 비교

항목Intel DLB 2.5Marvell OCTEON SSO (CN10K)
위치Xeon CPU 내장 / PCIe 카드OCTEON SoC 내장 (ARM 기반)
스케줄링 모드Atomic, Ordered, Parallel, DirectedAtomic, Ordered, Untagged
큐 수96 QID256 그룹
워커 포트64 CQ코어당 1 SSOW (최대 24)
스케줄링 지연~200ns~50-100ns (SoC 내부)
이벤트 처리량~500M events/s~500M events/s
HW 가속기 연동CPU가 중개 필요 (SW enqueue)CPT/REE/ZIP/TIM 직접 연동 (HW 자동)
타이머SW 관리TIM HW 타이머 휠 (자동 SSO 이벤트)
태그 전환 (SWTAG)미지원 (이벤트 재제출)HW SWTAG (런타임 모드 변경)
WQESW 정의 이벤트 구조HW 정의 WQE (NIC 자동 생성)
SR-IOV16 VFSoC 내장 (가상화 제한적)
Credit 기반 배압지원 (16K credit)XAQ(External Admission Queue) 기반
DPDK 드라이버event_dlb2event_cnxk
커널 드라이버dlb2 (5.18+)octeontx2-ssopf (5.14+)
주요 타겟x86 서버, 클라우드 NGFW, 5G UPF네트워크 어플라이언스, 임베디드 DPI

NGFW 파이프라인에서의 이벤트 스케줄러 활용

기존 NGFW 데이터 플레인은 run-to-completion(단일 코어가 패킷을 끝까지 처리) 또는 SW 파이프라인(SW 큐로 단계 간 전달) 모델을 사용합니다. HW 이벤트 스케줄러는 이를 HW 파이프라인으로 대체하여 락 경합·캐시 미스·부하 불균형을 제거합니다.

처리 모델Run-to-CompletionSW 파이프라인HW 이벤트 파이프라인
코어 간 전달없음 (단일 코어)SW ring (rte_ring)DLB QID / SSO 그룹
플로우 친화성RSS 해시 고정SW 해시 + 락HW Atomic 태그
순서 보장자동 (단일 코어)SW 시퀀스 넘버HW Ordered 모드
부하 분산정적 (RSS)SW 동적 (lock 경합)HW 동적 (lock-free)
코어 추가 시RSS 재설정 필요큐 추가 + 재분배CQ/SSOW 추가만
캐시 효율최적 (단일 코어)낮음 (코어 간 데이터 이동)중간 (HW 최적화 분배)
가속기 연동동기 대기 or 콜백콜백 + SW enqueueHW 자동 이벤트 (SSO)
지연 시간최소 (단일 경로)중간 (SW 큐 지연)낮음 (~200ns/단계)
최대 처리량코어 수 × 단일 성능중간 (락 병목)최고 (lock-free 확장)
복잡도낮음중간높음 (HW 구성)

 NGFW 이벤트 드리븐 파이프라인 예시 (DLB/SSO 공통)

 ┌──────────┐     ┌─────────┐     ┌──────────┐     ┌─────────┐
 │  NIC RX  │────▶│  HW     │────▶│  Stage 1 │────▶│  HW     │
 │ (패킷    │     │  Event  │     │ conntrack│     │  Event  │
 │  수신)   │     │  Sched  │     │ + ACL    │     │  Sched  │
 └──────────┘     │ [Atomic]│     │ (lock-   │     │[Ordered]│
                  └─────────┘     │  free)   │     └────┬────┘
                                  └──────────┘          │
                  ┌─────────────────────────────────────┘
                  │
                  ▼
 ┌──────────┐     ┌─────────┐     ┌──────────┐     ┌─────────┐
 │ Stage 2  │────▶│  HW     │────▶│  Stage 3 │────▶│  NIC TX │
 │ IPSec    │     │  Event  │     │  IPS/DPI │     │ (패킷   │
 │ 암복호화 │     │  Sched  │     │ 시그니처 │     │  송신)  │
 │ (QAT/CPT)│     │[Parallel│     │  매칭    │     └─────────┘
 └──────────┘     │ or Auto]│     └──────────┘
   ↑ HW 완료 시   └─────────┘      순서 복원은
   SSO: 자동 이벤트                  HW reorder 버퍼가
   DLB: SW re-enqueue              자동 처리
HW 이벤트 스케줄러 도입 시 고려사항
① 적합한 시나리오: 다수 코어(8+)에서 수백만 플로우를 처리하는 고성능 NGFW. RSS만으로 부하 균형이 어렵고, 플로우별 상태(conntrack/NAT)에 동시 접근이 빈번한 환경에서 효과가 극대화됩니다.
② 부적합한 시나리오: 4코어 이하 임베디드 장비에서는 run-to-completion이 더 효율적입니다. HW 이벤트 스케줄러의 ~200ns 단계 지연이 오히려 오버헤드가 될 수 있습니다.
③ DPDK eventdev 생태계: DLB와 SSO 모두 rte_eventdev API를 통해 추상화되므로, 애플리케이션 코드를 변경하지 않고 HW 백엔드만 교체할 수 있습니다. event_sw(SW eventdev)로 개발 후 HW로 전환하는 전략이 일반적입니다.
④ 관련 기술: NIC RSS/RPS와 상호 보완적입니다. RSS가 NIC 수준의 정적 분배라면, DLB/SSO는 파이프라인 단계 간 동적 재분배를 담당합니다. 두 기술을 결합하면 NIC→SSO→코어 3단계 부하 분산이 가능합니다.

Fortinet NP7 / SP5

Fortinet FortiGate는 자체 ASIC 칩을 사용하여 데이터 플레인을 가속합니다. Inline ASIC(NP7) + Lookaside 코프로세서(SP5/CP9) 하이브리드 모델로, 패킷 전달은 NP7이 데이터 경로에서 직접(inline) 처리하고, 암호화·패턴 매칭은 전용 칩에 위임(lookaside)합니다:

NP7 세션 오프로드 프로세스(Process)

FortiGate에서 세션이 NP7으로 오프로드되는 과정:

  1. 첫 패킷: CPU(IPS Engine)가 수신 → conntrack + UTM(IPS/AV/App Control) 전체 검사
  2. 세션 수립: 검사 통과 시 CPU가 ISF(Iterate Session Filter)에 오프로드 결정 쿼리
  3. NP7 등록: session_offload_add() → NP7 Session Table에 5-tuple + NAT 정보 + QoS 태그 기록
  4. 후속 패킷: NP7 ASIC이 Session Table lookup → NAT rewrite → QoS → forwarding (CPU bypass)
  5. 세션 종료: TCP FIN/RST → NP7이 CPU에 알림 → Session Table 삭제 → 통계 동기화
FortiGate 구성 요소처리 방식역할성능
NP7 ASICInlineL2~L4 세션 오프로드, NAT, IPSec, VXLAN, QoS200Gbps (단일 칩)
SP5 (Security Processor)LookasideSSL/TLS 가속 (복호화/암호화)SSL 검사 시 CPU 부하 감소
CP9 (Content Processor)LookasideAV 시그니처, IPS 패턴 매칭 보조CPU DPI 성능 ~2배 향상
CPU (FortiOS)제어 플레인정책 결정, App Control, DLP, 관리모델별 차이
# FortiGate 진단 명령
diagnose npu np7 session-stats         # NP7 오프로드 세션 통계
diagnose npu np7 sse-stats all         # Session Search Engine 통계
diagnose npu np7 port-list             # NP7 포트 매핑 확인
diagnose sys session filter dport 443  # 특정 포트 세션 확인
get system performance firewall statistics # 전체 성능 통계

# NP7 오프로드 비율 확인
diagnose npu np7 session-stats
# 출력 예:
# NP7 offload sessions: 1,234,567
# CPU sessions: 12,345
# Offload ratio: 99.0%

# 특정 세션의 오프로드 상태 확인
diagnose sys session filter src 10.0.0.1
diagnose sys session list
# 출력에서 npu_state=offloaded 확인
FortiGate 오프로드 제외 조건: UTM(AV/IPS/DLP/App Control)이 활성화된 정책의 세션은 첫 패킷 검사 이후에만 오프로드됩니다. 단, SSL 딥 인스펙션이 적용된 세션은 SP5가 전 구간 복호화/암호화를 수행하므로, 패킷당 처리지만 NP7 수준의 세션 오프로드는 불가합니다. 이 경우 SP5의 SSL 가속이 병목 해소의 핵심입니다.
Fortinet 참고 문서:

SP5 (Security Processor) 암·복호화 아키텍처

SP5는 FortiGate의 SSL/TLS 전용 하드웨어 가속 프로세서입니다. CPU에서 수행하면 병목이 되는 TLS 핸드셰이크(비대칭키 연산)와 레코드 암·복호화(대칭키 연산)를 전담합니다.

SP5 기능처리 내용성능 효과비고
TLS 핸드셰이크 가속RSA-2048/4096, ECDHE P-256/P-384 키 교환CPU 대비 CPS 10~20배 향상TLS 1.2/1.3 모두 지원
대칭키 암·복호화AES-128/256-GCM, AES-CBC, ChaCha20-Poly1305CPU 대비 처리량 5~10배SSL Inspection의 레코드 계층
인증서 동적 생성MITM 프록시용 서버 인증서 실시간 서명CA 서명 연산 HW 가속FortiGate SSL Inspection 핵심
TLS 세션 재개Session ID / Session Ticket 캐시 관리재연결 시 핸드셰이크 생략SP5 내부 세션 캐시
IPSec 암호화ESP AES-GCM encap/decapNP7과 협업 (NP7 = ESP 헤더, SP5 = crypto)VPN 트래픽 처리

SP5의 SSL Deep Inspection 파이프라인

FortiGate가 SSL Deep Inspection(SSL 딥 인스펙션)을 수행할 때의 내부 패킷 흐름입니다:

  1. 클라이언트 → FortiGate TLS 핸드셰이크: SP5가 ECDHE/RSA 키 교환 수행. FortiGate의 CA 인증서로 서버 인증서를 동적 생성하여 클라이언트에 제공
  2. FortiGate → 서버 TLS 핸드셰이크: SP5가 실제 서버와 별도의 TLS 세션 수립. 서버의 진짜 인증서를 검증
  3. 데이터 복호화: SP5가 클라이언트 TLS 세션의 레코드를 하드웨어에서 복호화 → 평문을 CPU(IPS 엔진)에 전달
  4. DPI/IPS 검사: CPU + CP9가 평문에 대해 App Control, IPS 시그니처 매칭, AV 스캔, DLP 수행
  5. 재암호화: SP5가 서버 TLS 세션의 레코드로 재암호화 → NP7이 전달
SP5 SSL Inspection의 성능 특성:
  • SSL Inspection 활성 시 세션은 NP7 session offload 대상에서 제외됩니다. 모든 패킷이 SP5를 통과해야 하기 때문
  • FortiGate 7081F 기준: FW 처리량 700Gbps → SSL Inspection 시 35Gbps로 감소 (1/20 수준)
  • SP5의 병목은 주로 CPS(TLS 핸드셰이크/초): 모델별 50K~200K CPS
  • TLS 1.3 vs 1.2: TLS 1.3은 핸드셰이크가 1-RTT로 줄어 CPS가 약 20% 향상되지만, PFS 필수로 키 교환 연산 비용은 동일
  • SP5 세션 캐시(Session Resumption)를 활용하면 재연결 시 핸드셰이크 비용을 80% 절감
# FortiGate SSL Inspection 진단 명령
diagnose sys session filter proto 6 dport 443
diagnose sys session list
# 출력에서 확인할 항목:
# npu_state=0 (SSL Inspection 세션은 offload 안 됨)
# ssl_action=deep-inspection
# ssl_cipher=ECDHE-RSA-AES256-GCM-SHA384

# SP5 처리 통계
diagnose hardware deviceinfo nic sp5
# SP5 crypto throughput:
#   Encrypt: 18.5 Gbps
#   Decrypt: 19.2 Gbps
#   Handshake: 95,000 TPS

# SSL Inspection 통계
get system performance firewall statistics
# ssl_proxy_sessions: 45,678
# ssl_proxy_bandwidth: 12.3 Gbps

# SSL Inspection 정책 설정
config firewall ssl-ssh-profile
  edit "deep-inspect"
    set ssl-anomaly-log enable
    config https
      set ports 443
      set status deep-inspection
      set cert-validation-timeout 30
    end
  next
end

# NP7 + SP5 협업 확인
diagnose npu np7 session-stats
# ssl_sessions_to_sp5: 45,678 (SP5로 전달된 SSL 세션)
# non_ssl_offloaded: 1,189,000 (NP7 오프로드된 비-SSL 세션)

NP7의 IPSec 암호화 처리 상세

NP7은 IPSec VPN 트래픽에 대해 ESP 패킷의 전체 처리(캡슐화 + 암호화 + 포워딩)를 하드웨어에서 수행합니다:

IPSec 기능NP7 역할SP5 역할CPU 역할
IKE 핸드셰이크-DH 키 교환 가속IKE daemon (iked)
ESP 캡슐화/디캡슐화HW 처리--
AES-GCM 암·복호화HW 처리 (내장 crypto)폴백 시 보조-
Anti-replay 검사HW 시퀀스 윈도우--
SA 관리SA 테이블 (최대 ~50K SA)-SA 라이프사이클
터널 모드 포워딩decap → session lookup → encap--
NAT-T (UDP 4500)HW 처리--
Fortinet FortiGate — NP7/SP5/CP9 암호화 트래픽 파이프라인 SSL Deep Inspection 경로 (HTTPS 트래픽) Client TLS NP7 세션 분류 SSL? SP5 TLS Decrypt 평문 CPU (FortiOS) App-ID / IPS CP9 AV/DLP 매칭 SP5 TLS Re-Encrypt NP7 전달 Server IPSec VPN 경로 (오프로드 가능) Remote ESP NP7 (IPSec Engine) ESP Decap + AES-GCM Decrypt + Session Lookup 평문 CPU (첫 패킷만) NP7 Session Offload EST → NP7 직접: Decrypt → Forward → Encrypt Internal 비-암호화 트래픽 경로 (최고 성능) Source NP7 (첫 패킷→CPU) EST → NP7 Session Offload (CPU bypass) NP7 200Gbps 라인레이트 Dest FortiGate 7081F — 트래픽 유형별 성능 비교 FW (비암호화): 700 Gbps NP7 session offload IPSec VPN: 200 Gbps NP7 crypto offload NGFW (DPI): 60 Gbps CPU + CP9 SSL Inspection: 35 Gbps SP5 + CPU + CP9 SSL Inspection 활성화 시 처리량이 FW의 1/20로 감소 → SP5 가속이 핵심

Palo Alto Networks FPGA

Palo Alto PA 시리즈는 FPGA 기반 SP3 (Security Processing) 아키텍처를 사용합니다. Inline FPGA + CPU 통합 모델로, 세션 오프로드는 FPGA가 inline 처리하고, DPI와 SSL은 범용 CPU에서 single-pass로 처리합니다. 전용 크립토 ASIC이 없어 SSL/IPSec은 CPU(AES-NI)에 의존하는 lookaside 구조입니다:

Single-Pass 아키텍처 상세

Palo Alto의 핵심 차별점은 Single-Pass Parallel Processing (SP3) 아키텍처입니다:

전통적 방화벽Palo Alto SP3
패킷이 FW → IPS → AV → URL 순서로 직렬 통과FW, App-ID, IPS, AV, URL이 단일 패스에서 병렬 처리
각 엔진마다 패킷 복사/버퍼(Buffer)링스트림 기반 처리 (패킷 복사 최소화)
지연 = 각 엔진 지연의 합지연 = 가장 느린 엔진의 지연
엔진 추가 시 성능 선형 감소엔진 추가 시 성능 영향 최소

FE FPGA의 역할: FPGA는 패킷 분류(5-tuple lookup), 세션 테이블 검색, 디캡슐레이션, NAT rewrite를 수행합니다. CPU는 App-ID 엔진만 실행하므로, FPGA가 처리할 수 있는 세션(이미 분류된 ESTABLISHED)은 CPU를 완전히 bypass합니다.

Palo Alto SSL 복호화 아키텍처

Palo Alto는 전용 크립토 ASIC 없이 범용 CPU 코어에서 SSL 복호화를 수행합니다. SP3 아키텍처의 핵심은 SSL 복호화를 Single-Pass 파이프라인의 일부로 통합하여, 별도의 프록시 단계 없이 인라인(Inline)에서 처리하는 것입니다.

SSL 처리 단계처리 위치특성
TLS 핸드셰이크 (RSA/ECDHE)CPU 코어 (멀티스레드)CPS 병목. PA-5440 기준 ~15K SSL CPS
TLS 레코드 복호화 (AES-GCM)CPU 코어 (AES-NI)코어당 ~4 Gbps. PA-5440: 총 12 Gbps SSL
인증서 검증CPU 코어OCSP/CRL 확인, 인증서 체인 검증
Forward Trust CA 서명CPU 코어MITM용 인증서 동적 생성 (RSA/ECDSA)
App-ID (복호화 후)CPU 코어 (SP3 병렬)평문에 대해 App-ID + IPS + URL 동시 실행
TLS 재암호화CPU 코어 (AES-NI)서버 세션의 레코드 암호화

Palo Alto의 접근법은 Fortinet(SP5 전용 칩)과 대조적입니다. 장점: 범용 CPU로 유연한 TLS 버전/cipher suite 지원 (TLS 1.3 초기 지원이 빨랐음). 단점: 전용 칩 대비 SSL 처리량이 낮고, SSL 활성화 시 CPU 부하가 크게 증가합니다.

Palo Alto SSL 복호화 성능 특성:
  • PA-5440 기준: FW 75 Gbps → SSL 복호화 활성 시 12 Gbps (1/6 수준)
  • SSL Forward Proxy + Full Threat Prevention 시 더 감소 (TLS 핸드셰이크 + DPI + AV 복합)
  • SSL Inbound Inspection(서버 키 보유)은 Forward Proxy 대비 ~30% 빠름 (인증서 생성 불필요)
  • Hardware Security Module(HSM) 연동: FIPS 140-2 준수 환경에서 SafeNet HSM으로 CA 개인키 보호
  • TLS 1.3 0-RTT 복호화: PAN-OS 11.0+에서 지원하지만 CPU 부담 증가
# Palo Alto SSL 복호화 진단 명령
show counter global filter delta yes | match ssl
# ssl_proxy_session_new: 연결/초 (CPS)
# ssl_proxy_session_active: 현재 활성 SSL 세션
# ssl_decrypt_success: 복호화 성공 패킷
# ssl_decrypt_fail: 복호화 실패 (cipher 미지원 등)
# ssl_cert_verify_fail: 인증서 검증 실패

show session all filter ssl-decrypt yes
# SSL 복호화 중인 세션 목록

show system resources
# CPU 사용률 확인 → SSL 활성 시 증가폭

# SSL 복호화 정책 설정 (PAN-OS)
set rulebase decryption rules "decrypt-outbound" {
    from any; to any;
    source any; destination any;
    service any; action decrypt;
    type { ssl-forward-proxy { }; };
    profile "default";
}

# SSL 복호화 프로파일
set profiles decryption "strict" {
    ssl-forward-proxy {
        block-expired-certificate yes;
        block-untrusted-issuer yes;
        block-unsupported-version yes;
        block-unsupported-cipher yes;
        min-version tls1-2;
    };
}
# Palo Alto CLI 진단 명령
show running resource-monitor           # CPU/메모리/세션 사용률
show session all filter state active    # 활성 세션 목록
show session info                       # 세션 통계 (CPS, CC)
show counter global filter delta yes \
  packet-filter yes                     # 실시간 카운터
debug dataplane packet-diag set filter \
  match src 10.0.0.1                    # 특정 IP 패킷 추적
Palo Alto 참고 문서:
Palo Alto Networks — SP3 Single-Pass Parallel Processing 아키텍처 SP3 Single-Pass 파이프라인 (첫 패킷 + NEW 세션) Packet In FE FPGA 5-tuple Lookup Session Table NAT Rewrite NEW CPU — Single-Pass 병렬 처리 App-ID IPS URL Filter AV DLP 모든 엔진이 동일 패킷에 대해 동시 실행 (Single-Pass) 허용 FE FPGA 세션 설치 Packet Out ESTABLISHED 세션 — FPGA Fast Path (CPU bypass) Packet In FE FPGA — Session Hit NAT Rewrite + QoS + Forward CPU bypass — FPGA 직접 전달 (라인레이트) Packet Out SSL Decryption 경로 (CPU-only, AES-NI) Client TLS FE FPGA SSL 태깅 CPU (AES-NI) TLS Decrypt + DPI Single-Pass App-ID/IPS/AV CPU (AES-NI) TLS Re-Encrypt Server PA-5440 — 트래픽 유형별 처리량 비교 FW: 75 Gbps FPGA fast path Threat: 38 Gbps App-ID + IPS + AV SSL Decrypt: 12 Gbps CPU AES-NI only IPSec VPN: 36 Gbps CPU crypto SSL Decryption은 전용 HW 가속 없이 CPU(AES-NI)에 의존 → FW의 1/6 수준으로 감소 Single-Pass: 한 번의 패킷 스캔으로 모든 보안 기능 동시 실행 → Multi-Pass 대비 지연 최소화

Check Point SecureXL / Maestro

Check Point는 순수 소프트웨어 기반(Inline 커널 가속) 아키텍처를 사용합니다. 전용 ASIC/FPGA 없이 범용 x86 CPU만으로 모든 처리를 수행하며, 커널 레벨 inline 가속(SecureXL)으로 성능을 확보합니다. SSL/IPSec 암·복호화도 CPU에서 수행(lookaside 코프로세서 없음)하므로, HTTPS Inspection 성능이 상대적으로 제한됩니다:

SecureXL 처리 경로 상세

SecureXL은 3가지 처리 경로(Accelerated Path, Medium Path, Firewall Path)로 패킷을 분류합니다:

경로처리 위치대상 트래픽성능 영향
Accelerated Path커널 (SecureXL)Accept Template에 등록된 ESTABLISHED 세션최고 성능
Medium Path커널 (SecureXL + SXL 엔진)NAT, VPN 적용 필요한 세션Accelerated의 60~80%
Firewall Path유저스페이스 (fwd daemon)NEW 연결, IPS/DLP/App Control 검사가장 느림

Accept Template은 Linux conntrack의 ESTABLISHED + flowtable 개념과 유사합니다. conntrack이 세션 상태를 추적하고, Accept Template이 검사가 완료된 세션의 5-tuple을 커널 가속 테이블에 등록합니다. Drop Template은 이미 DROP 판정이 난 소스 IP/포트를 캐시하여, 동일한 악성 트래픽이 재전송(Retransmission)될 때 CPU까지 가지 않고 즉시 DROP합니다.

CoreXL / SND 아키텍처

Check Point의 멀티코어 아키텍처는 Linux의 RSS/RPS와 유사하지만 보안에 최적화되어 있습니다:

# Check Point 진단 명령 (Gaia OS)
fwaccel stat                            # SecureXL 가속 통계
fwaccel stats -s                        # 경로별 패킷/바이트 통계
fwaccel conns                           # Accept Template 연결 수
fw ctl multik stat                      # CoreXL 인스턴스별 통계
cpview                                  # 실시간 성능 모니터 (TUI)

# SecureXL 비활성화/활성화 (성능 비교 테스트)
fwaccel off     # 가속 비활성화 → 전체 Firewall Path
fwaccel on      # 가속 재활성화

# 특정 세션의 처리 경로 확인
fw ctl zdebug + drop    # 디버그 로그
Check Point 참고 문서:

Check Point HTTPS Inspection 아키텍처

Check Point는 Fortinet(SP5 전용 칩)이나 전용 크립토 ASIC 없이 순수 소프트웨어 기반의 HTTPS Inspection을 수행합니다. CoreXL의 멀티코어 병렬 처리와 SecureXL의 가속 경로를 조합하여 성능을 최적화합니다.

HTTPS Inspection 단계처리 위치가속 방법
TLS 핸드셰이크CoreXL FW 인스턴스 (CPU)OpenSSL AES-NI, 멀티코어 분산
인증서 동적 생성CoreXL FW 인스턴스 (CPU)인증서 캐시 (동일 서버 재사용)
TLS 레코드 복호화CoreXL FW 인스턴스 (CPU)AES-NI + SSL 세션 재사용
DPI/IPS 검사CoreXL FW 인스턴스 + SandBlastCoreXL 병렬 처리
TLS 재암호화CoreXL FW 인스턴스 (CPU)AES-NI

SecureXL과 HTTPS Inspection의 관계: HTTPS Inspection이 활성화되면 해당 세션은 Firewall Path(가장 느린 경로)에서 처리됩니다. Accelerated Path로 승격될 수 없으므로, HTTPS Inspection 비율이 높을수록 SecureXL 가속 효과가 감소합니다.

# Check Point HTTPS Inspection 진단
fwaccel stat
# Accelerated Conns: 1,200,000
# HTTPS Inspect Conns: 45,000 (Firewall Path)
# → HTTPS Inspection 세션은 Accelerated Path 불가

# HTTPS Inspection 통계
cpstat -f https_inspection fw
# Total inspected connections: 45,000
# Bypassed connections: 5,000 (bypass 규칙 적용)
# Certificate cache hit ratio: 85%

# CoreXL 인스턴스별 SSL 부하 분포
fw ctl multik stat
# 각 CoreXL 인스턴스의 CPU 사용률 확인
# HTTPS Inspection 활성 시 불균형 주의

# HTTPS Inspection 바이패스 규칙 (성능 최적화)
# SmartConsole → Security Policies → HTTPS Inspection
# 금융/의료 사이트, Windows Update 등 → Bypass 권장
Check Point Maestro와 HTTPS Inspection 확장: 단일 게이트웨이의 HTTPS Inspection 처리량이 부족한 경우, Maestro HyperScale로 여러 게이트웨이를 클러스터링하여 수평 확장할 수 있습니다. Maestro Orchestrator가 SSL 세션을 게이트웨이 간에 분배하되, 동일 TLS 세션의 모든 패킷은 같은 게이트웨이로 고정(session affinity)됩니다.
Check Point — SecureXL / CoreXL / Maestro HyperScale 아키텍처 패킷 처리 3-Path 분류 Packet In SND Secure Network Distributor RSS + 경로 분류 Accept Template Hit Accelerated Path (SecureXL) 커널 레벨 direct forward — CPU bypass 라인레이트 전달 Packet Out Template Miss Medium Path SecureXL 부분 처리 + CoreXL 정책 검사 HTTPS/복합 Firewall Path (Full Inspection) CoreXL FW Instance 전체 검사 (HTTPS Inspection 포함) CoreXL 멀티코어 분배 구조 SND Core 패킷 분배 CoreXL FW #0 CoreXL FW #1 CoreXL FW #N SecureXL 캐시 Accept Template Drop Template 설치 HTTPS Inspection SSL Decrypt → 검사 → Re-Encrypt 항상 Firewall Path 강제 SecureXL bypass 불가 Maestro HyperScale — 수평 확장 클러스터 Orchestrator 세션 분배 + Affinity 동일 TLS → 동일 GW Security GW #1 Security GW #2 Security GW #N 최대 52개 GW 클러스터링 Quantum 28000 — 경로별 처리량 FW: 64 Gbps SecureXL 가속 Threat: 15 Gbps CoreXL 전체 검사 SSL: 7 Gbps HTTPS Inspection HTTPS Inspection 시 SecureXL bypass 불가 → FW 대비 1/9 수준 SecureXL Accept Template 적중률이 높을수록 전체 성능 향상 — HTTPS 비율 증가 시 Firewall Path 부하 급증

Juniper Express Path

Juniper SRX 시리즈의 Express Path는 세션의 첫 패킷만 flow daemon이 처리하고, 이후 패킷은 NPU(Network Processing Unit)에서 직접 전달합니다. Inline NP + Lookaside SPC3 하이브리드 모델로, 패킷 전달은 NP가 데이터 경로에서 inline 처리하고, IPSec/SSL 암호화는 별도 SPC3 카드에 위임(lookaside)합니다:

Express Path 동작 원리

Juniper SRX의 패킷 처리 아키텍처:

  1. NP (Network Processor): 모든 패킷의 1차 수신. 세션 테이블에서 lookup
  2. Express Path 히트: 기존 세션 매칭 → NP에서 직접 forwarding + NAT rewrite (flowd bypass)
  3. Express Path 미스: 새 세션 → flowd(flow daemon)로 전달 → 정책 평가 + IPS/AppID
  4. 세션 설치: flowd가 정책 통과 시 세션을 NP Express Path 테이블에 등록
# Juniper SRX 진단 명령
show security flow statistics           # 플로우 통계 (Express Path 비율)
show security monitoring fpc 0          # FPC별 세션/처리량
show security flow session              # 세션 테이블
show security flow session summary      # 세션 요약 (활성/최대)

# Express Path 상태 확인
show pfe statistics traffic
# express-path-packets, slow-path-packets 비교

# Services Offload Engine 상태
show chassis fpc pic-status

SPC3 (Services Processing Card) 암호화 가속

Juniper SRX 5000 시리즈는 SPC3 카드를 통해 IPSec과 SSL 처리를 전용 하드웨어에서 가속합니다. SPC3는 NP(Network Processor)와 별도의 크립토 엔진을 내장하고 있어, 암·복호화 연산을 NP에서 분리하여 처리합니다.

SPC3 기능처리 방식처리 내용성능
IPSec 가속LookasideESP AES-GCM 암·복호화, SA 관리카드당 ~50 Gbps IPSec
SSL ProxyLookasideTLS 핸드셰이크 + 레코드 암·복호화카드당 ~10K SSL CPS
Express Path 통합Inline (NP)IPSec 복호화 후 inner 패킷 Express Path 등록EST 세션: NP 직접 전달
NATInline (NP)NAT rewrite + conntrackExpress Path 연계
# Juniper SRX SPC3 암호화 관련 진단
show security ipsec statistics
# ESP 암·복호화 패킷/바이트 통계

show security ipsec sa
# SA 목록 + 하드웨어 가속 여부

show services ssl proxy statistics
# SSL Proxy 세션 수, CPS, 처리량

show chassis fpc 0 pic 0
# SPC3 카드 상태 + 크립토 엔진 사용률

# SPC3 IPSec 오프로드 설정
set security ipsec vpn site-a {
    ike {
        gateway gw-site-a;
        ipsec-policy ipsec-pol;
    }
    establish-tunnels immediately;
}
# SPC3가 자동으로 IPSec 처리를 하드웨어에서 수행

SPC3 SSL Forward Proxy 핸드셰이크 처리

Juniper SRX의 SSL Forward Proxy는 SPC3 카드에서 TLS 핸드셰이크와 레코드 암·복호화를 전담합니다. flowd(Flow Daemon)는 평문 DPI만 수행하므로, 암호화 연산 부하가 CPU에 집중되지 않습니다.

TLS 핸드셰이크 단계처리 위치상세 동작
1. ClientHello 수신NP → SPC3NP가 TCP 443 패킷을 SPC3로 전달. SPC3가 SNI 추출 + 정책 매칭
2. 서버측 TLS 세션 수립SPC3 (Lookaside)SPC3가 실제 서버에 ClientHello 전송 → ServerHello/Certificate 수신. ECDHE/RSA 키 교환을 SPC3 크립토 엔진에서 수행
3. 서버 인증서 검증SPC3 + flowdSPC3가 인증서 체인 검증. OCSP/CRL 확인은 flowd 경유 (네트워크 I/O)
4. MITM 인증서 생성SPC3 (Lookaside)서버 인증서의 CN/SAN을 복제하여 SRX CA로 서명한 대체 인증서 생성. 인증서 캐시에 저장
5. 클라이언트측 TLS 세션 수립SPC3 (Lookaside)생성된 MITM 인증서로 클라이언트에 ServerHello 응답. 클라이언트와 별도 TLS 세션 수립
6. 데이터 복호화 (클라이언트→서버)SPC3 (Lookaside)클라이언트 TLS 세션의 레코드를 AES-GCM 복호화 → 평문을 flowd에 전달
7. DPI 검사flowd (CPU, Inline)평문에 대해 AppID + IPS + UTM 수행. Single-pass 아님 — 순차 처리
8. 재암호화 (서버 세션)SPC3 (Lookaside)검사 완료된 평문을 서버 TLS 세션으로 AES-GCM 재암호화 → NP로 전달
9. TLS 세션 재개 (Session Resumption)SPC3TLS Session ID / Ticket 캐시. 재연결 시 핸드셰이크 생략 → CPS 부담 경감
Juniper SSL Proxy 성능 특성:
  • SSL Proxy 세션은 Express Path 대상에서 제외됨 — 모든 패킷이 SPC3 → flowd → SPC3 경로를 통과해야 하므로
  • SPC3 카드당 ~10K SSL CPS (TLS 1.2 RSA-2048 기준). TLS 1.3 ECDHE는 ~15K CPS
  • TLS 1.3 vs 1.2: 1.3은 1-RTT 핸드셰이크로 지연 감소하지만, PFS 필수(ECDHE)로 SPC3 키 교환 부하는 유사
  • SPC3 카드 추가 장착으로 SSL CPS를 선형 확장 가능 (SRX5800: 최대 SPC3 ×4)
  • 인증서 캐시 적중률이 높을수록 MITM 인증서 생성 부하 감소 (일반적으로 80~90% 적중)
Juniper SRX — SPC3 SSL Forward Proxy TLS 핸드셰이크 흐름 Client SPC3 Crypto flowd (CPU) Server ① ClientHello (SNI: example.com) ② SPC3 → 서버에 ClientHello 전달 ③ ServerHello + Certificate + KeyExchange ④ ECDHE 키 교환 (HW 가속) ⑤ Finished — 서버측 TLS 세션 수립 완료 ⑥ MITM 인증서 생성 SRX CA 서명 (캐시 확인) ⑦ ServerHello + MITM Certificate ⑧ ECDHE KeyExchange + Finished ⑨ 클라이언트측 TLS 세션 수립 데이터 전송 단계 (TLS 레코드) ⑩ TLS 레코드 (암호화) AES-GCM 복호화 (HW) ⑪ 평문 전달 ⑫ AppID + IPS + UTM ⑬ 검사 완료 AES-GCM 재암호화 (HW) ⑭ TLS 레코드 (서버 세션으로 재암호화) SPC3 크립토 엔진이 핸드셰이크(ECDHE) + 레코드(AES-GCM) 모두 HW 가속 — flowd는 평문 DPI만 담당
Juniper 참고 문서:
Juniper SRX — Express Path + SPC3 아키텍처 Express Path — 세션 히트/미스 분기 Packet In NP (NPU) Session Table Lookup Express Path 판정 Session Hit Express Path — NP 직접 전달 flowd bypass, 라인레이트 forwarding CPU bypass Packet Out Session Miss flowd Flow Daemon 정책 평가 IPS / AppID / UTM 허용 세션 설치 → Express Path 등록 SPC3 카드 — IPSec / SSL Proxy 처리 ESP In ESP NP (인입) SPC3 Crypto Engine AES-GCM Decrypt + ESP Decap 평문 Express Path 내부 전달 SPC3 Crypto AES-GCM Encrypt + ESP Encap ESP Out SSL Proxy 경로 (SPC3 + flowd) Client TLS NP SPC3 SSL Proxy TLS Decrypt flowd (DPI) AppID + IPS + UTM SPC3 SSL Proxy TLS Re-Encrypt Server SRX5800 + SPC3 — 처리 경로별 성능 Express Path: 2 Tbps NP 직접 forwarding flowd: 모델별 차이 정책+DPI CPU 처리 IPSec: ~50 Gbps/SPC3 SPC3 crypto engine SSL Proxy: SPC3+CPU TLS 복호화 부하 Express Path Hit 세션은 NP에서 라인레이트 처리 — flowd/SPC3 경유 시 처리량 감소 SPC3 카드 추가 장착으로 IPSec/SSL 처리량 선형 확장 가능

Linux 커널 기반 NGFW

Linux 커널과 오픈소스 도구를 조합하여 NGFW를 구축하는 접근법입니다. Inline SmartNIC + Lookaside SW 하이브리드 모델로, EST 세션은 SmartNIC eSwitch가 inline 처리(라인레이트)하고, DPI는 NFQUEUE를 통해 유저스페이스 Suricata에 위임(lookaside)합니다. 암호화는 NIC inline crypto 또는 QAT lookaside를 선택할 수 있습니다:

Linux NGFW 스택 구성

Linux 커널 기반 NGFW를 상용 수준으로 구축하기 위한 전체 스택:

계층구성 요소처리 방식역할대안
HW Fast PatheSwitch FDB (mlx5/ice)InlineEST 세션 라인레이트 전달OVS-DPDK TC offload
SW Fast Pathnf_flowtableInline (커널)HW 미지원 EST 세션 가속VPP session table
Stateful FWnftables + nf_conntrackInline (커널)ACL, NAT, 세션 추적iptables (레거시)
DPI / IPSSuricata (NFQUEUE mode)Lookaside시그니처 기반 탐지/차단nDPI, Snort 3
App-IDnDPI 라이브러리LookasideL7 프로토콜 분류Suricata App-Layer
SSL 검사mitmproxy / Suricata TLSLookasideSSL/TLS 프록시SSLsplit
DDoS Pre-filterXDP BPFInlineL3/L4 사전 필터tc-bpf
QoSTC qdisc (HTB/fq_codel)Inline (커널)대역폭 제어, 우선순위(Priority)CAKE
VPNStrongSwan (xfrm) + WireGuardInline (NIC) / Lookaside (QAT)사이트 간/원격 접속 VPNLibreswan
HAconntrackd + Keepalived제어 플레인세션 동기화 + VIP failoverPacemaker
관리nftables API + Prometheus제어 플레인정책 관리 + 모니터링Firewalld

VPP 기반 NGFW 데이터 플레인

FD.io VPP를 사용하면 커널 Netfilter 대신 유저스페이스에서 패킷 처리하여 더 높은 성능을 달성합니다:

# VPP 기반 NGFW 설정 예시
# /etc/vpp/startup.conf
dpdk {
  dev 0000:03:00.0 { name eth0 }
  dev 0000:03:00.1 { name eth1 }
}

# VPP CLI에서 ACL + session 설정
vppctl acl-plugin acl add permit+reflect \
  src 10.0.0.0/8 dst 0.0.0.0/0 proto tcp
vppctl set acl-plugin interface eth0 input acl 0

# 새 세션만 TAP으로 전달 (DPI)
vppctl create tap id 0
vppctl set interface state tap0 up

Linux NGFW SSL/TLS 검사 아키텍처

Linux 기반 NGFW에서 SSL/TLS 검사는 여러 오픈소스 컴포넌트를 조합하여 구현합니다. 상용 NGFW와 달리 단일 통합 솔루션이 아닌 계층별 독립 도구의 조합이며, 각 계층에서 inline/lookaside HW 가속을 선택적으로 적용할 수 있습니다.

TLS 처리 단계구현 도구처리 방식HW 가속
TLS 핸드셰이크 (ECDHE/RSA)mitmproxy / SSLsplit / Squid SSL BumpLookaside (유저스페이스 프록시)QAT (Intel QuickAssist) — 비대칭키 가속
MITM 인증서 생성OpenSSL (CA 서명)CPUQAT RSA 서명 가속
TLS 레코드 복호화 (AES-GCM)kTLS + NIC offload / QATInline (NIC) 또는 Lookaside (QAT)NIC inline crypto (ConnectX-7), QAT
DPI / IPS 검사Suricata (NFQUEUE)Lookaside (유저스페이스)AF_XDP, 멀티스레드
TLS 재암호화kTLS TX offload / QATInline (NIC) 또는 Lookaside (QAT)NIC inline crypto, QAT
Session ResumptionOpenSSL Session Cache / RedisCPU + 메모리-

SSL 검사 아키텍처 선택지

Linux NGFW에서 SSL/TLS 트래픽을 검사하는 대표적인 3가지 아키텍처입니다:

아키텍처구조장점단점처리량
NFQUEUE + mitmproxynftables → NFQUEUE → mitmproxy(TLS 프록시) → Suricata(DPI)구현 단순, Python 확장성능 낮음, CPS 제한~1-3 Gbps
Squid SSL Bump + ICAP투명 프록시 Squid → SSL Bump → ICAP → Suricata프록시 캐시, URL 필터링 통합TCP 프록시 오버헤드~3-8 Gbps
kTLS + QAT + SuricatakTLS NIC offload + QAT 핸드셰이크 → 커널 평문 → NFQUEUE DPIHW 가속, 최고 성능구성 복잡, NIC/QAT 의존~10-20 Gbps
Linux SSL 검사의 한계와 상용 대비 차이:
  • CPS 병목: 상용 NGFW(SP5, SPC3)는 전용 ASIC으로 50K~200K CPS를 달성하지만, Linux는 CPU+QAT로 ~10K~30K CPS 수준
  • 통합도: 상용은 핸드셰이크→복호화→DPI→재암호화가 단일 파이프라인이지만, Linux는 프록시(mitmproxy/Squid)와 DPI(Suricata)가 별도 프로세스
  • TLS 1.3 ECH: SNI가 암호화되면 mitmproxy/Squid의 SNI 기반 정책 적용이 불가 → IP/DNS 기반 우회 필요
  • 세션 오프로드 불가: SSL 검사 세션은 flowtable/eSwitch HW offload 대상에서 제외됨 (모든 패킷이 프록시를 통과해야 하므로)
Linux NGFW — SSL/TLS 검사 파이프라인 (3가지 아키텍처) ① NFQUEUE + mitmproxy (단순 구성, ~1-3 Gbps) Client nftables NFQUEUE → 유저스페이스 mitmproxy TLS Decrypt → DPI → Re-Encrypt Suricata 평문 IPS/IDS Server ② Squid SSL Bump + ICAP (프록시 통합, ~3-8 Gbps) Client TPROXY 투명 리다이렉트 Squid (SSL Bump) TLS Decrypt + MITM 인증서 + URL 필터 + 캐시 ICAP Suricata ICAP 서버 (DPI) Server ③ kTLS + QAT + Suricata (최고 성능, ~10-20 Gbps) Client QAT TLS 핸드셰이크 HW 가속 kTLS (NIC RX) AES-GCM HW 복호화 평문 nf_conntrack Suricata DPI NFQUEUE 평문 검사 kTLS (NIC TX) AES-GCM HW 재암호화 Server TLS 핸드셰이크 단계별 HW 가속 매핑 단계 CPU (SW) QAT 가속 NIC Inline ECDHE 키 교환 ~10K ops/s/core ~100-200K ops/s 미지원 RSA CA 서명 ~5K ops/s/core ~50-100K ops/s 미지원 AES-GCM 레코드 2-8 Gbps/core 100-200 Gbps 라인레이트 Session Ticket OpenSSL 캐시 미지원 미지원 QAT: 핸드셰이크(비대칭키) 가속 핵심 | NIC kTLS: 레코드(대칭키) 인라인 가속 핵심
Linux NGFW 참고 문서:
Linux 커널 기반 NGFW — 전체 스택 아키텍처 HW Layer Kernel Layer Userspace SmartNIC HW (eSwitch FDB + Inline Crypto) eSwitch FDB CT Offload IPSec Inline kTLS NIC QAT Accel EST 세션 HW offload → 라인레이트 200Gbps+ (ConnectX-7, BlueField-3) Linux Kernel — 네트워크 스택 XDP 초기 필터링 TC flower HW offload 규칙 nf_flowtable SW Fast Path (conntrack) Hit SW Fast Forward CPU 전달 Miss nftables 정책 평가 + conntrack NFQUEUE → 유저스페이스 xfrm (IPSec) + NIC inline crypto kTLS NIC offload + QAT flowtable Hit → SW fast path | Miss → nftables Slow Path → NFQUEUE DPI Userspace DPI — Suricata (NFQUEUE inline) IPS/IDS App-Layer Protocol File/TLS Logging VPP (대안) DPDK 기반 유저스페이스 FW Netfilter 대체 Linux NGFW — 경로별 처리량 (ConnectX-7 / BlueField-3 기준) HW Offload: 200 Gbps eSwitch FDB 라인레이트 SW Fast Path: 40 Gbps nf_flowtable CPU DPI: 10-20 Gbps NFQUEUE + Suricata IPSec: NIC inline xfrm + HW crypto kTLS: NIC+QAT SSL offload EST 세션은 eSwitch HW offload로 라인레이트 처리 — 새 세션만 커널/유저스페이스 DPI 경유 SmartNIC CT offload + nf_flowtable + Suricata = 상용 NGFW 수준의 오픈소스 스택

벤더별 SSL/TLS 핸드셰이크 처리 비교

모든 NGFW의 SSL/TLS Inspection은 MITM(Man-in-the-Middle) TLS Proxy 방식입니다. 클라이언트와 서버 사이에 두 개의 독립된 TLS 세션을 수립하고, NGFW가 중간에서 복호화 → DPI → 재암호화를 수행합니다. 벤더 간 차이는 각 TLS 핸드셰이크 단계의 처리 위치(CPU vs 전용 HW)처리 방식(inline vs lookaside)에 있습니다.

TLS 핸드셰이크 단계별 벤더 비교

TLS 핸드셰이크 단계FortinetPalo AltoCheck PointJuniperLinux
ClientHello 수신 + SNI 추출NP7 → CPU 분류FE FPGA → CPU 분류SND → CoreXL 분류NP → SPC3 분류nftables → 프록시 분류
서버측 TLS 세션 수립SP5 (HW)CPU (AES-NI)CPU (OpenSSL)SPC3 (HW)CPU / QAT 가속
ECDHE 키 교환SP5 ASIC — CPS 10~20× 향상CPU 멀티스레드 — ~15K CPSCPU AES-NI — 코어 수 의존SPC3 크립토 엔진 — ~15K CPS/카드CPU ~10K/core / QAT ~200K
RSA CA 서명 (MITM 인증서)SP5 ASIC — HW RSA 가속CPU — RSA 연산CPU — 인증서 캐시로 보완SPC3 — HW RSA 가속CPU / QAT RSA 가속
인증서 캐시 / Session ResumptionSP5 내부 캐시CPU 메모리 캐시CoreXL 인스턴스 캐시SPC3 인증서 캐시OpenSSL Session Cache
클라이언트측 TLS 세션 수립SP5 (HW)CPU (AES-NI)CPU (OpenSSL)SPC3 (HW)CPU / QAT
AES-GCM 레코드 복호화SP5 ASIC — 5~10× CPU 대비CPU AES-NI — ~4Gbps/coreCPU AES-NISPC3 — HW AES 가속kTLS NIC RX — 라인레이트
DPI / IPS 검사 (평문)CPU + CP9 (Lookaside)CPU SP3 Single-PassCoreXL FW Instanceflowd (CPU)Suricata (NFQUEUE)
AES-GCM 레코드 재암호화SP5 ASICCPU AES-NICPU AES-NISPC3kTLS NIC TX — 라인레이트
세션 오프로드 가능 여부불가 (SP5 전구간 통과 필수)불가 (CPU 전구간 통과 필수)불가 (Firewall Path 강제)불가 (SPC3 전구간 통과 필수)불가 (프록시 전구간 통과 필수)

SSL/TLS 처리 성능 비교

지표Fortinet 7081FPA-5440CP Quantum 28000Juniper SRX5800Linux (ConnectX-7 + QAT)
FW (비암호화)700 Gbps75 Gbps64 Gbps~2 Tbps (EP)200 Gbps (HW offload)
SSL Inspection 처리량35 Gbps12 Gbps7 GbpsSPC3 카드 수 의존10~20 Gbps (kTLS+QAT)
SSL CPS50K~200K (SP5)~15K (CPU)모델별 차이~10K/SPC3 카드~10-30K (QAT)
FW 대비 SSL 감소율1/201/61/9모델별1/10~1/20
핸드셰이크 HW 가속SP5 (전용 ASIC)없음 (CPU only)없음 (CPU only)SPC3 (전용 카드)QAT (선택)
레코드 HW 가속SP5 (전용 ASIC)없음 (AES-NI only)없음 (AES-NI only)SPC3 (전용 카드)NIC kTLS (선택)
TLS 1.3 지원FortiOS 7.0+PAN-OS 10.0+R81.20+Junos 21.4+OpenSSL 1.1.1+
공통 원칙: 모든 벤더에서 SSL/TLS Inspection 세션은 HW 세션 오프로드(Fast Path) 대상에서 제외됩니다. 매 패킷마다 복호화 → 검사 → 재암호화가 필요하므로 ASIC/FPGA bypass가 불가능합니다. 따라서 SSL Inspection 활성화 비율이 높을수록 전체 NGFW 처리량이 급감합니다. 이를 완화하는 전략은: (1) SSL Inspection 바이패스 정책 (신뢰 사이트, Windows Update, CDN 등 제외), (2) Session Resumption (핸드셰이크 비용 절감), (3) HW 가속 확장 (SP5/SPC3 추가, QAT 카드 증설)입니다.
NGFW TLS MITM Proxy — 핸드셰이크 단계별 HW 가속 비교 TLS MITM Proxy 공통 구조 (모든 벤더 동일) Client TLS① TLS Decrypt 클라이언트측 세션 평문 DPI / IPS / App-ID 평문에 대한 보안 검사 평문 TLS Encrypt 서버측 세션 TLS② Server TLS① = Client↔NGFW 세션 (MITM 인증서) | TLS② = NGFW↔Server 세션 (진짜 인증서) 벤더별 TLS 핸드셰이크 처리 엔진 단계 Fortinet Palo Alto Check Point Juniper Linux ECDHE 키 교환 SP5 ASIC CPU only CPU only SPC3 HW CPU / QAT RSA CA 서명 SP5 ASIC CPU only CPU + 캐시 SPC3 HW CPU / QAT AES-GCM 복호화 SP5 ASIC CPU AES-NI CPU AES-NI SPC3 HW kTLS NIC DPI / IPS 검사 CPU + CP9 SP3 Single-Pass CoreXL FW flowd CPU Suricata AES-GCM 재암호화 SP5 ASIC CPU AES-NI CPU AES-NI SPC3 HW kTLS NIC 세션 오프로드 불가 불가 불가 불가 불가 범례 전용 HW ASIC 가속 전용 HW 카드 가속 CPU (AES-NI / SW) CPU only (HW 없음) 아키텍처 고유 최적화 TLS 1.2 vs 1.3 핸드셰이크 차이와 NGFW 영향 TLS 1.2 — 2-RTT 핸드셰이크 ClientHello → ServerHello+Cert → KeyExchange → Finished NGFW: SNI 평문 노출 → 정책 적용 가능, 2-RTT 지연 TLS 1.3 — 1-RTT (+ 0-RTT 가능) ClientHello+KeyShare → ServerHello+Cert+Finished (1-RTT) NGFW: PFS 필수(ECDHE 매회), ECH 시 SNI 암호화 → 정책 적용 난이도↑ TLS 1.3은 핸드셰이크 RTT 감소 → CPS 소폭 향상 | ECH 활성화 시 SNI 기반 복호화 정책 적용 불가
상용 NGFW 아키텍처 비교 Fortinet NP7 ASIC SP5 Crypto CP9 DPI CPU (FW) 전용 ASIC 기반 Palo Alto FE FPGA NPC Card CPU (Single-Pass App-ID/IPS) FPGA + CPU 병렬 Check Point SecureXL CoreXL Maestro HyperScale 순수 SW 가속 Linux NGFW eSwitch HW flowtable NFQUEUE nftables SmartNIC + 커널 아래 테이블에서 상세 비교 →
특성Fortinet (NP7)Palo Alto (FPGA)Check PointJuniper SRXLinux SmartNIC
Fast Path 방식ASIC session tableFPGA forwarding engineSecureXL Accept TemplateExpress Path NPUeSwitch FDB + flowtable
Fast Path 처리량200Gbps+모델 의존 (100Gbps)SW 기반 (제한적)NPU 의존NIC 라인레이트
DPI 방식CPU + CP9 보조CPU (Single-Pass)CPU (CoreXL)CPU (flowd)NFQUEUE + Suricata
IPSec 가속NP7 내장FPGA/CPUSWServices EngineNIC inline crypto
SSL/TLS 가속SP5 전용 칩CPUCPUCPUkTLS + CPU
NAT 오프로드NP7 HWFPGA HWSecureXL SWNPUflowtable/eSwitch
세션 테이블 크기수천만수백만수백만수백만NIC 의존 (수만~수십만 HW)
수평 확장HA clusterHA clusterMaestroChassis cluster커널 네임스페이스(Namespace)/VRF
커스터마이즈제한적 (벤더 종속)제한적중간제한적완전 자유
라이선스 비용높음매우 높음높음높음하드웨어 비용만

상용 NGFW 암호화 처리 비교

암·복호화 트래픽 관점에서 각 벤더의 아키텍처를 비교합니다. SSL/TLS Inspection과 IPSec VPN 처리는 NGFW 성능에서 가장 큰 차이를 만드는 영역입니다.

암호화 특성Fortinet (NP7+SP5)Palo Alto (FPGA+CPU)Check Point (SW)Juniper SRX (SPC3)Linux (SmartNIC+QAT)
SSL Inspection 가속 방식SP5 전용 ASICCPU (AES-NI)CPU (CoreXL + AES-NI)SPC3 크립토 엔진kTLS NIC + Intel QAT
TLS 핸드셰이크 가속SP5 HW (RSA/ECDHE)CPU 멀티코어CPU 멀티코어SPC3 HWQAT/NITROX ASIC
TLS 레코드 암·복호화SP5 HW (AES-GCM)CPU (AES-NI)CPU (AES-NI)SPC3 HWkTLS NIC inline
SSL Inspection 처리량35 Gbps (7081F)12 Gbps (PA-5440)7 Gbps (28000)SPC3 카드 수 의존3~8 Gbps (kTLS+CPU)
SSL CPS~200K (SP5)~15K (CPU)~10K (CoreXL)~10K (SPC3)~100K (QAT)
IPSec 가속 방식NP7 내장 cryptoFPGA + CPUCPU (AES-NI)SPC3 전용 엔진NIC inline crypto
IPSec 처리량200 Gbps (NP7)모델 의존SW 기반 (제한적)~50 Gbps/SPC3NIC 라인레이트
지원 cipher suiteAES-GCM, ChaCha20AES-GCM, ChaCha20AES-GCM, ChaCha20AES-GCMAES-GCM (NIC 의존)
TLS 1.3 지원지원지원 (초기 지원)지원 (R81.20+)지원 (22.x+)지원 (커널 5.3+)
FIPS 140-2/3인증인증인증인증QAT FIPS 모드 가능
EST 세션 crypto offloadNP7 (IPSec), SP5 (SSL)제한적불가 (Firewall Path)SPC3 (IPSec)NIC full offload (IPSec)
벤더별 암호화 아키텍처 핵심 차이:
  • Fortinet: 전용 ASIC(SP5)으로 SSL 처리 → 최고의 SSL Inspection 성능. 단, 벤더 칩에 종속
  • Palo Alto: 범용 CPU + SP3 파이프라인 → 유연한 cipher 지원, 빠른 TLS 표준 대응. 단, SSL 처리량 제한적
  • Check Point: 순수 SW → Maestro로 수평 확장 가능. 단, 단일 장비 SSL 성능 가장 낮음
  • Juniper: SPC3 카드로 모듈식 확장 → 필요한 만큼 카드 추가. IPSec에 강점
  • Linux: QAT(핸드셰이크) + kTLS NIC(레코드) + IPSec full offload 조합 → 가장 유연하지만 통합 복잡
상용 NGFW — 암호화 처리 아키텍처 비교 (SSL Inspection 관점) Fortinet SP5: TLS Handshake HW SP5: AES-GCM HW NP7: IPSec Full HW CPU: DPI/App-ID만 SSL: 35 Gbps Palo Alto CPU: TLS Handshake CPU: AES-GCM (AES-NI) FPGA: Session FWD CPU: DPI (Single-Pass) SSL: 12 Gbps Check Point CPU: TLS Handshake CPU: AES-GCM (AES-NI) CPU: SecureXL+CoreXL CPU: DPI (Firewall Path) SSL: 7 Gbps Linux SmartNIC QAT: TLS Handshake HW kTLS NIC: AES-GCM HW NIC: IPSec Full Offload CPU: DPI (Suricata) SSL: 3~8 Gbps Juniper SRX SPC3: TLS Handshake SPC3: AES-GCM HW SPC3: IPSec HW CPU: DPI (flowd) SSL: SPC3 의존 암호화 오프로드 전략의 핵심 인사이트 전용 ASIC (Fortinet SP5) → 최고 SSL 성능, 최저 유연성 | 범용 CPU (Palo Alto/CP) → 최고 유연성, 최저 SSL 성능 모듈식 카드 (Juniper SPC3) → 필요 시 확장 | SmartNIC+QAT (Linux) → 구성요소 자유 조합, 통합 복잡도 높음 공통점: 모든 벤더에서 SSL Inspection 활성화 시 FW 처리량의 1/5~1/20로 감소 → 암호화 오프로드가 NGFW 성능의 핵심

상용 vs Linux NGFW 선택 기준

어떤 접근을 선택해야 하는가?
  • 상용 NGFW 선택: 규제 준수 인증(CC, FIPS) 필수, 벤더 기술 지원 필요, IT 인력 제한, 빠른 도입 필요
  • Linux NGFW 선택: 커스텀 파이프라인 필요, 대규모(100G+) 환경, 특수 프로토콜/DPI 요구, 벤더 종속 탈피, 비용 최적화
  • 하이브리드: 상용 NGFW의 관리 플레인 + Linux/SmartNIC의 데이터 플레인 (일부 벤더가 이 모델 채택 중)

성능 비교 벤치마크 (참고 수치)

다음은 공개된 데이터시트와 독립 벤치마크(NSS Labs, RFC 9411 기반)에서 추출한 참고 수치입니다. 실제 환경에서는 정책 복잡도, 트래픽 믹스, DPI 시그니처 수에 따라 크게 달라집니다:

메트릭Fortinet 7081F (NP7)PA-5440CP 28000 (Maestro)Linux + CX-7 (200G)
FW 처리량 (L4)700 Gbps75 Gbps64 Gbps200 Gbps (HW offload)
NGFW 처리량 (DPI+IPS)60 Gbps30 Gbps15 Gbps10~20 Gbps (Suricata)
Threat Protection40 Gbps22 Gbps12 Gbps5~15 Gbps
SSL Inspection35 Gbps (SP5)12 Gbps7 Gbps3~8 Gbps (kTLS)
CPS1.5M450K300K200K~500K
동시 세션45M16M10Mconntrack_max 설정 의존

Linux NGFW의 NGFW 처리량은 Suricata DPI에 의해 제한되지만, FW 처리량(L4 stateful)에서는 SmartNIC HW offload로 상용 제품에 필적하는 성능을 달성합니다. 핵심은 오프로드 비율을 높여 DPI 부하를 최소화하는 것입니다.

벤치마크 수치 출처와 주의사항:
  • Fortinet 7081F: FortiGate 7000 Series Data Sheet 기준. FW 처리량 700Gbps는 NP7 ASIC 다중 장착 시 합산 값
  • PA-5440: PA-5400 Series Data Sheet 기준. App-ID + IPS + logging 활성화 시 30Gbps
  • CP 28000: Quantum Gateway 모델 비교 기준. Maestro 클러스터 시 수평 확장 가능
  • Linux + CX-7: NVIDIA ConnectX-7 Product Brief 기준 NIC 라인레이트. NGFW 처리량은 Suricata 멀티코어 벤치마크 참고
  • 모든 벤더 수치는 최적 조건(단순 트래픽 믹스, 최소 정책)에서의 데이터시트 값이며, 실제 환경에서는 RFC 9411 방법론에 따라 독립적으로 측정해야 합니다

커널 NGFW 빌딩 블록

Linux 커널에서 NGFW를 구축할 때 사용하는 주요 서브시스템과 NGFW 기능 간의 매핑입니다. 각 서브시스템은 독립적으로 발전해 왔지만, NGFW에서는 이들을 하나의 통합 파이프라인으로 결합해야 합니다. 이 절에서는 각 서브시스템의 역할과 연동 포인트를 정리합니다.

커널 서브시스템 선택의 핵심 원칙:
  • XDP: 가장 빠른 경로 (NIC 드라이버 직후). DDoS pre-filter, 명백한 악성 패킷 DROP
  • TC flower + eSwitch: HW Fast Path. ESTABLISHED 세션의 라인레이트 전달
  • nf_flowtable: SW Fast Path. HW 미지원 세션의 커널 내 가속
  • nftables + conntrack: Slow Path. 새 세션의 정책 평가, 상태 추적
  • NFQUEUE: 유저스페이스 DPI 연동. Suricata/nDPI로 패킷 전달
  • xfrm: IPSec 처리. HW crypto offload 가능
  • TC qdisc: QoS. 대역폭 제어, 우선순위 큐잉
NGFW 기능 ↔ 커널 서브시스템 매핑 NGFW 기능 Stateful ACL NAT (SNAT/DNAT) 세션 오프로드 DPI / IPS DDoS Pre-filter HW Fast Path IPSec VPN QoS / Traffic Shaping 커널 서브시스템 nftables + conntrack nf_nat nf_flowtable NFQUEUE + Suricata XDP / BPF TC flower + eSwitch xfrm (IPSec) TC qdisc (HTB/TBF) 실선: 1:1 매핑 | 점선: 추가 연관 (eSwitch가 ACL과 오프로드 모두 담당)
NGFW 기능커널 서브시스템HW 오프로드관련 페이지(Page)
Stateful ACL (L3/L4)nftables + nf_conntrackTC flower ct_state → eSwitchNetfilter
NAT (SNAT/DNAT)nf_natflowtable NAT offload / eSwitch NAT actionNAT
세션 오프로드 (Fast Path)nf_flowtableNF_FLOWTABLE_HW_OFFLOAD → NIC flow tableFlowtable
DPI / IPSNFQUEUE + 유저스페이스 DPI미오프로드 (CPU 처리)NFQUEUE & DPI
DDoS Pre-filterXDP BPF 프로그램XDP HW offload (지원 NIC)BPF/XDP
HW Fast PathTC flower + mlx5/ice eSwitcheSwitch FDB rule 삽입eSwitch
IPSec VPNxfrmNIC inline crypto offloadIPSec & xfrm
QoS / Traffic ShapingTC qdisc (HTB, TBF, fq_codel)TC flower + skbedit → HW QoS queueTC
ALG 프로토콜nf_conntrack_helper미오프로드 (CPU 필수)conntrack 헬퍼
네트워크 격리network namespace / VRFeSwitch VF representor네트워크 네임스페이스

드라이버 오프로드 계약 (ndo_setup_tc)

NIC 드라이버가 TC flower offload를 지원하기 위해 구현해야 하는 인터페이스입니다. NGFW 파이프라인의 HW offload는 이 계약에 의존합니다. (Network Device 드라이버 참고)

/* include/linux/netdevice.h */
struct net_device_ops {
    /* TC flower offload 진입점 */
    int (*ndo_setup_tc)(struct net_device *dev,
                        enum tc_setup_type type,
                        void *type_data);
};

/* 드라이버가 처리해야 하는 TC 타입 */
enum tc_setup_type {
    TC_SETUP_QDISC_MQPRIO,   /* MQPRIO QoS 큐 설정 */
    TC_SETUP_CLSFLOWER,       /* TC flower 분류기 규칙 */
    TC_SETUP_FT,              /* flowtable offload */
    TC_SETUP_BLOCK,           /* 블록 바인딩 (CT offload) */
};

/* CLSFLOWER 콜백에서 처리하는 명령 */
enum tc_fl_command {
    TC_CLSFLOWER_REPLACE,    /* 규칙 추가/교체 */
    TC_CLSFLOWER_DESTROY,    /* 규칙 삭제 */
    TC_CLSFLOWER_STATS,      /* HW 카운터 읽기 */
};
코드 설명
  • 4-6행 ndo_setup_tc는 TC 서브시스템이 NIC 드라이버에 오프로드 규칙을 전달하는 단일 진입점(Entry Point)입니다. type 파라미터로 어떤 종류의 오프로드인지 구분합니다.
  • 10-14행 TC_SETUP_FT는 flowtable offload 전용 타입으로, nf_flow_offload_hw_add()가 이 타입으로 드라이버를 호출합니다. TC_SETUP_BLOCK은 conntrack action offload에 사용됩니다.
  • 18행 TC_CLSFLOWER_STATS는 HW에서 처리된 패킷/바이트 카운터를 읽어옵니다. GC가 주기적으로 이 명령을 호출하여 타임아웃을 갱신합니다.

nf_flowtable 내부 구조

/* include/net/netfilter/nf_flow_table.h */
struct nf_flowtable {
    struct list_head   list;        /* flowtable 전역 리스트 */
    struct rhashtable  rhashtable;  /* 5-tuple 해시 테이블 */
    int                priority;    /* Netfilter 훅 우선순위 */
    unsigned int       flags;       /* NF_FLOWTABLE_HW_OFFLOAD 등 */
    struct nf_flowtable_type *type;
    struct delayed_work gc_work;    /* GC 워크큐 */
    struct flow_block  flow_block;  /* HW offload 블록 */
    struct mutex       flow_block_lock;
    possible_net_t     net;
};

/* rhashtable 파라미터: 자동 크기 조절 */
static const struct rhashtable_params nf_flow_offload_rhash_params = {
    .head_offset     = offsetof(struct flow_offload_tuple_rhash, node),
    .key_offset      = offsetof(struct flow_offload_tuple_rhash, tuple),
    .key_len         = sizeof(struct flow_offload_tuple),
    .automatic_shrinking = true,  /* 엔트리 감소 시 자동 축소 */
};

flowtable은 rhashtable(Resizable Hash Table)을 사용합니다. 엔트리 수에 따라 버킷이 자동으로 확장/축소되며, RCU 기반 읽기로 lock-free lookup을 보장합니다. 이는 NGFW에서 높은 CPS 환경에서도 Fast Path lookup의 일관된 성능을 유지하는 핵심입니다.

핵심 커널 API 흐름

/* NGFW 파이프라인의 커널 API 호출 흐름 (개념도) */

/* 1. 패킷 수신 → Netfilter PREROUTING 훅 */
nf_hook(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb);

/* 2. conntrack: 세션 추적 */
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ctinfo == IP_CT_NEW) {
    /* 새 세션 → Slow Path: 전체 규칙 평가 */
    nft_do_chain(chain, skb);  /* nftables 규칙 평가 */
    nf_queue(skb, queue_num);  /* NFQUEUE → DPI 엔진 */
}

/* 3. flowtable: ESTABLISHED 세션 Fast Path */
if (ctinfo == IP_CT_ESTABLISHED) {
    struct flow_offload *flow = flow_offload_lookup(ft, skb);
    if (flow) {
        /* Fast Path: conntrack bypass → 직접 전달 */
        nf_flow_offload_ip_hook(skb);  /* NAT rewrite + forward */
        return NF_STOLEN;  /* Netfilter 훅 체인 종료 */
    }
}

/* 4. HW offload 등록 */
flow_offload_add(ft, flow);
if (ft->flags & NF_FLOWTABLE_HW_OFFLOAD)
    nf_flow_offload_hw_add(net, flow, ct);  /* eSwitch FDB rule 설치 */
코드 설명
  • 3행 (nf_hook PREROUTING) 패킷이 처음 도착하면 PREROUTING 훅에서 모든 등록된 콜백(Callback)이 실행됩니다. conntrack, nftables, flowtable이 이 훅에 등록되어 있습니다.
  • 6행 (nf_ct_get) skb에 연결된 conntrack 엔트리를 가져옵니다. ctinfo는 현재 패킷의 방향(ORIGINAL/REPLY)과 상태(NEW/ESTABLISHED)를 나타냅니다.
  • 7-10행 (IP_CT_NEW) 새로운 세션의 첫 패킷입니다. nftables 체인 전체를 평가하고, NFQUEUE로 DPI 엔진에 전달합니다.
  • 13-19행 (IP_CT_ESTABLISHED) 이미 수립된 세션의 패킷입니다. flowtable에서 플로우를 찾으면 NAT rewrite + forward를 직접 수행하고 NF_STOLEN으로 Netfilter 체인을 종료합니다.
  • 22-24행 (HW offload) flowtable에 등록하고, HW offload 플래그가 있으면 NIC eSwitch에도 FDB 규칙을 설치합니다. 이후 동일 플로우의 패킷은 NIC에서 직접 처리됩니다.

NFQUEUE 연동 API

DPI 엔진이 NFQUEUE에서 패킷을 수신하고 verdict를 반환하는 과정의 유저스페이스 API입니다:

/* libnetfilter_queue를 사용한 DPI 엔진 기본 구조 */
#include <libnetfilter_queue/libnetfilter_queue.h>

static int nfq_callback(struct nfq_q_handle *qh,
                        struct nfgenmsg *nfmsg,
                        struct nfq_data *nfa,
                        void *data)
{
    struct nfqnl_msg_packet_hdr *ph;
    unsigned char *payload;
    int payload_len;
    uint32_t id;

    ph = nfq_get_msg_packet_hdr(nfa);
    id = ntohl(ph->packet_id);
    payload_len = nfq_get_payload(nfa, &payload);

    /* DPI 분석 수행 */
    int verdict = analyze_packet(payload, payload_len);

    /* verdict 반환: NF_ACCEPT 또는 NF_DROP */
    if (verdict == DPI_ALLOW)
        return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
    else
        return nfq_set_verdict(qh, id, NF_DROP, 0, NULL);
}

/* 메인 루프: NFQUEUE 수신 + DPI 콜백 */
int main(void)
{
    struct nfq_handle *h = nfq_open();
    struct nfq_q_handle *qh = nfq_create_queue(h, 0,
                                                 &nfq_callback, NULL);

    /* 배치 verdict 활성화 (성능 향상) */
    nfq_set_queue_flags(qh, NFQA_CFG_F_GSO, NFQA_CFG_F_GSO);

    /* 소켓에서 패킷 수신 루프 */
    int fd = nfq_fd(h);
    char buf[65536];
    int rv;
    while ((rv = recv(fd, buf, sizeof(buf), 0)) > 0)
        nfq_handle_packet(h, buf, rv);

    return 0;
}

오프로드 구현 패턴

Suricata NFQUEUE 통합 설정

Suricata를 NGFW의 DPI/IPS 엔진으로 사용할 때의 최적화된 설정입니다:

# /etc/suricata/suricata.yaml (NGFW 최적화)

# NFQUEUE 모드 설정
nfq:
  mode: repeat          # verdict 후 재주입 (NFQUEUE → nftables 계속)
  repeat-mark: 1        # 재주입된 패킷 마킹 (중복 큐잉 방지)
  repeat-mask: 1
  bypass: yes           # Suricata 과부하 시 패킷 bypass (가용성 우선)
  fail-open: yes        # Suricata 장애 시 패킷 통과 (HA 환경)
  batchcount: 20        # 배치 verdict (성능 향상)

# 멀티 스레드 설정 (CPU 코어 4~16개 환경)
threading:
  set-cpu-affinity: yes
  cpu-affinity:
    - management-cpu-set:
        cpu: [ 0 ]
    - receive-cpu-set:
        cpu: [ 1, 2, 3, 4 ]    # NFQUEUE 수신 스레드
    - worker-cpu-set:
        cpu: [ 5, 6, 7, 8, 9, 10, 11, 12 ]  # 분석 워커

# App-Layer 프로토콜 분석 (NGFW App-ID)
app-layer:
  protocols:
    tls:
      enabled: yes
      detection-ports:
        dp: 443, 8443
      ja3-fingerprints: yes   # JA3/JA3S 핑거프린트 (TLS 분류)
    http:
      enabled: yes
      server-body-limit: 1mb  # DLP를 위한 바디 검사 한계
    dns:
      enabled: yes
    smb:
      enabled: yes
    ssh:
      enabled: yes
      hassh: yes              # HASSH 핑거프린트

# 플로우 타임아웃 (flowtable과 동기화)
flow-timeouts:
  default:
    new: 30
    established: 300          # nf_flowtable_tcp_timeout과 일치
    closed: 10
    bypassed: 300             # bypass된 세션 (오프로드됨)
  tcp:
    new: 60
    established: 600
    closed: 60

# bypass 설정 (오프로드 연동)
stream:
  bypass: yes                 # 분류 완료 후 스트림 바이패스
  max-sessions: 1000000       # 최대 동시 세션
코드 설명
  • 5행 (mode: repeat) repeat 모드에서 Suricata는 verdict(ACCEPT/DROP) 후 패킷을 Netfilter에 재주입합니다. 이를 통해 nftables의 나머지 규칙(flowtable 등록 등)이 계속 실행됩니다.
  • 9행 (fail-open: yes) Suricata 프로세스가 크래시하거나 응답하지 않을 때 패킷을 자동으로 통과시킵니다. NGFW에서 가용성이 보안보다 중요한 경우 필수입니다.
  • 10행 (batchcount: 20) NFQUEUE에서 20개 패킷을 모아서 한 번에 verdict를 전송합니다. syscall 횟수를 줄여 ~30% 성능 향상이 가능합니다.
  • 34행 (ja3-fingerprints) JA3 핑거프린트는 TLS Client Hello의 특성으로 클라이언트 애플리케이션을 식별합니다. SNI 없이도 App-ID가 가능합니다.
  • 55행 (stream: bypass) Suricata가 세션 분류를 완료하면 이후 패킷의 스트림 재조립을 건너뜁니다. nftables의 flowtable 오프로드와 함께 사용하면 DPI 완료 세션이 Fast Path로 전환됩니다.

nftables NGFW 설정

완전한 nftables 규칙셋으로 NGFW 데이터 플레인을 구성하는 예시입니다. flowtable으로 ESTABLISHED 세션을 오프로드하고, NEW 세션은 NFQUEUE로 DPI 검사를 수행합니다.

#!/usr/sbin/nft -f
# NGFW nftables 규칙셋 (flowtable + NFQUEUE DPI)

table inet ngfw {
    # flowtable 정의 (HW offload 활성화)
    flowtable ft {
        hook ingress priority 0
        devices = { eth0, eth1 }
        flags offload  # NF_FLOWTABLE_HW_OFFLOAD
    }

    # forward chain: NGFW 핵심 파이프라인
    chain forward {
        type filter hook forward priority 0; policy drop;

        # 1. INVALID 패킷 즉시 DROP
        ct state invalid drop

        # 2. ESTABLISHED/RELATED → flowtable offload
        ct state established,related flow add @ft accept

        # 3. NEW 세션 → 기본 ACL 통과 후 NFQUEUE로 DPI
        ct state new ip protocol tcp \
            tcp dport { 80, 443, 8080, 8443 } \
            queue num 0-3 fanout  # 4개 DPI 워커로 분산

        ct state new ip protocol udp \
            udp dport { 53, 443 } \
            queue num 0-3 fanout

        # 4. 허용된 ICMP
        ct state new icmp type { echo-request, echo-reply } accept

        # 5. 나머지 NEW → DROP (기본 정책)
    }

    # input chain: 관리 인터페이스 보호
    chain input {
        type filter hook input priority 0; policy drop;
        ct state established,related accept
        iifname "lo" accept
        tcp dport 22 accept  # SSH 관리
    }
}
코드 설명
  • 6-10행 flowtable ft를 정의합니다. flags offload로 HW offload를 활성화하면, SmartNIC이 지원하는 경우 eSwitch FDB 규칙이 자동 설치됩니다.
  • 17행 INVALID 상태 패킷은 즉시 DROP합니다. conntrack이 유효하지 않다고 판단한 패킷(시퀀스 번호 불일치 등)입니다.
  • 20행 핵심 오프로드 규칙: ESTABLISHED/RELATED 세션을 flowtable에 등록하고 accept합니다. 이후 패킷은 Fast Path로 처리됩니다.
  • 23-25행 새로운 TCP 연결(특정 포트)을 NFQUEUE 0~3번 큐로 fanout 분산합니다. 각 큐에 Suricata 워커가 연결되어 DPI를 수행합니다.
  • 27-29행 DNS(53)와 QUIC(443/UDP) 트래픽도 DPI로 전달합니다.

TC flower ACL 오프로드

eSwitch switchdev 모드에서 TC flower를 사용하여 ACL 규칙을 하드웨어에 직접 설치합니다. 이 방식은 nftables의 SW 경로와 병행하여, NEW 패킷은 CPU(nftables → NFQUEUE → DPI)에서 처리하고 ESTABLISHED 패킷은 eSwitch HW에서 직접 전달합니다.

eSwitch TC flower vs nftables flowtable 비교:
  • TC flower 직접 규칙: 관리자가 명시적으로 CT 매칭 규칙을 설치. 세밀한 제어 가능하지만 관리 복잡도 증가
  • nftables flowtable + HW offload: flow add @ft로 자동 등록. 간편하지만 커널이 자동 결정
  • 권장 조합: nftables flowtable으로 기본 오프로드 + TC flower로 특수 규칙(IP 차단, QoS 등) 추가
# 1. eSwitch switchdev 모드 전환
devlink dev eswitch set pci/0000:03:00.0 mode switchdev

# 2. VF representor에서 hw-tc-offload 활성화
ethtool -K eth0_rep0 hw-tc-offload on

# 3. conntrack zone 설정 + 추적 시작
tc filter add dev eth0_rep0 ingress prio 1 \
  protocol ip flower \
  ct_state -trk \
  action ct zone 1

# 4. EST+TRK → NAT + forward (HW offload)
tc filter add dev eth0_rep0 ingress prio 2 \
  protocol ip flower \
  ct_state +trk+est \
  action ct zone 1 nat \
  action mirred egress redirect dev eth1_rep0

# 5. NEW+TRK → pass to CPU (Slow Path)
tc filter add dev eth0_rep0 ingress prio 3 \
  protocol ip flower \
  ct_state +trk+new \
  action pass

# 6. 특정 IP 대역 차단 (HW에서 DROP)
tc filter add dev eth0_rep0 ingress prio 0 \
  protocol ip flower \
  src_ip 192.168.100.0/24 \
  action drop

DPI 오프로드 바이패스 패턴

DPI 엔진이 세션을 분류하면 이후 패킷은 NFQUEUE를 bypass해야 합니다. eBPF map을 활용한 캐시 패턴입니다:

eBPF DPI 결과 캐시 (완전한 구현)

/* dpi_cache.bpf.c — eBPF DPI 결과 캐시 프로그램 */
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>

/* 5-tuple 플로우 키 */
struct flow_key {
    __be32 src_ip;
    __be32 dst_ip;
    __be16 src_port;
    __be16 dst_port;
    __u8   protocol;
    __u8   pad[3];
};

/* DPI 결과 값 */
struct dpi_result {
    __u32 verdict;      /* 0=ACCEPT, 1=DROP, 2=CONTINUE */
    __u32 app_id;       /* 애플리케이션 ID (DPI 엔진이 설정) */
    __u64 timestamp;    /* 마지막 갱신 (nsec) */
    __u64 bytes;        /* 바이트 카운터 (샘플링용) */
};

/* LRU 해시 맵: 자동으로 가장 오래된 엔트리 퇴출 */
struct {
    __uint(type, BPF_MAP_TYPE_LRU_HASH);
    __uint(max_entries, 500000);
    __type(key, struct flow_key);
    __type(value, struct dpi_result);
} dpi_cache SEC(".maps");

/* 통계 맵 */
struct {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __uint(max_entries, 4);
    __type(key, __u32);
    __type(value, __u64);
} stats SEC(".maps");
/* stats[0]=cache_hit, stats[1]=cache_miss,
   stats[2]=bypass_accept, stats[3]=bypass_drop */

static __always_inline int
extract_flow_key(struct __sk_buff *skb, struct flow_key *key)
{
    void *data = (void *)(long)skb->data;
    void *data_end = (void *)(long)skb->data_end;
    struct iphdr *iph = data + sizeof(struct ethhdr);

    if ((void *)(iph + 1) > data_end)
        return -1;

    key->src_ip = iph->saddr;
    key->dst_ip = iph->daddr;
    key->protocol = iph->protocol;

    if (iph->protocol == IPPROTO_TCP) {
        struct tcphdr *tcph = (void *)iph + (iph->ihl * 4);
        if ((void *)(tcph + 1) > data_end) return -1;
        key->src_port = tcph->source;
        key->dst_port = tcph->dest;
    } else if (iph->protocol == IPPROTO_UDP) {
        struct udphdr *udph = (void *)iph + (iph->ihl * 4);
        if ((void *)(udph + 1) > data_end) return -1;
        key->src_port = udph->source;
        key->dst_port = udph->dest;
    }
    return 0;
}

SEC("netfilter")
int dpi_bypass(struct bpf_nf_ctx *ctx)
{
    struct flow_key key = {};
    __u32 idx;
    __u64 *counter;

    if (extract_flow_key(ctx->skb, &key) < 0)
        return NF_ACCEPT;

    struct dpi_result *result = bpf_map_lookup_elem(&dpi_cache, &key);
    if (result) {
        /* 캐시 히트 */
        idx = 0; counter = bpf_map_lookup_elem(&stats, &idx);
        if (counter) (*counter)++;

        /* 바이트 카운터 갱신 (샘플링 판단용) */
        __sync_fetch_and_add(&result->bytes, ctx->skb->len);

        /* 10MB 초과 시 캐시 무효화 → 재검사 */
        if (result->bytes > 10485760) {
            bpf_map_delete_elem(&dpi_cache, &key);
            return NF_ACCEPT;  /* NFQUEUE로 전달 */
        }

        if (result->verdict == 0) {
            idx = 2; counter = bpf_map_lookup_elem(&stats, &idx);
            if (counter) (*counter)++;
            return NF_ACCEPT;   /* DPI ALLOW → bypass */
        } else if (result->verdict == 1) {
            idx = 3; counter = bpf_map_lookup_elem(&stats, &idx);
            if (counter) (*counter)++;
            return NF_DROP;     /* DPI DROP → 즉시 차단 */
        }
    }
    /* 캐시 미스 → NFQUEUE로 전달 (DPI 검사) */
    idx = 1; counter = bpf_map_lookup_elem(&stats, &idx);
    if (counter) (*counter)++;
    return NF_ACCEPT;
}

char _license[] SEC("license") = "GPL";
코드 설명
  • 11-18행 (flow_key) 5-tuple 플로우 키 구조체. pad[3]은 구조체를 8바이트 정렬하여 해시 성능을 최적화합니다.
  • 21-26행 (dpi_result) DPI 결과에 바이트 카운터를 추가하여 주기적 샘플링 임계치를 판단합니다. app_id는 모니터링/로깅에 활용됩니다.
  • 29-33행 (LRU_HASH) LRU 해시 맵은 max_entries에 도달하면 가장 오래된 엔트리를 자동 퇴출합니다. 50만 엔트리로 대부분의 활성 세션을 커버합니다.
  • 36-41행 (PERCPU_ARRAY) per-CPU 카운터로 캐시 히트/미스 통계를 lock-free로 수집합니다. bpftool map dump으로 확인 가능합니다.
  • 85-89행 (바이트 임계치) 10MB 초과 시 캐시 엔트리를 삭제하여 DPI 재검사를 강제합니다. 이는 §9의 주기적 샘플링을 eBPF 수준에서 구현한 것입니다.

DPI 엔진에서 eBPF 맵 업데이트

Suricata의 output 플러그인에서 verdict를 eBPF 맵에 기록합니다:

/* Suricata output 플러그인 (유저스페이스): verdict를 eBPF 맵에 기록 */
#include <bpf/libbpf.h>
#include <bpf/bpf.h>

int map_fd;  /* bpf_obj_get()으로 pinned map 열기 */

void update_dpi_cache(struct Packet *p, int verdict)
{
    struct flow_key key = {
        .src_ip   = p->src.addr_data32[0],
        .dst_ip   = p->dst.addr_data32[0],
        .src_port = p->sp,
        .dst_port = p->dp,
        .protocol = p->proto,
    };
    struct dpi_result result = {
        .verdict   = (verdict == VERDICT_PASS) ? 0 : 1,
        .app_id    = p->flow->alproto,
        .timestamp = get_timestamp_ns(),
        .bytes     = 0,
    };

    bpf_map_update_elem(map_fd, &key, &result, BPF_ANY);

    /* 역방향 플로우도 등록 (양방향 캐시) */
    struct flow_key rev_key = {
        .src_ip = key.dst_ip, .dst_ip = key.src_ip,
        .src_port = key.dst_port, .dst_port = key.src_port,
        .protocol = key.protocol,
    };
    bpf_map_update_elem(map_fd, &rev_key, &result, BPF_ANY);
}
# eBPF 프로그램 로드 및 nftables 연동
# 1. 컴파일
clang -O2 -target bpf -c dpi_cache.bpf.c -o dpi_cache.bpf.o

# 2. 로드 및 맵 핀닝
bpftool prog load dpi_cache.bpf.o /sys/fs/bpf/dpi_bypass \
  type netfilter

# 3. nftables에서 eBPF 프로그램 연결
# (nftables 커널 5.18+에서 BPF verdict 지원)
nft add rule inet ngfw forward \
  ct state new \
  meta mark != 0xff \
  queue num 0-3 fanout  # BPF 캐시 미스만 NFQUEUE로 전달

# 4. 캐시 통계 확인
bpftool map dump pinned /sys/fs/bpf/dpi_bypass/stats
# key: 0  value (per-cpu): [12345, 12340, ...]  ← cache_hit
# key: 1  value (per-cpu): [567, 570, ...]      ← cache_miss

NGFW 시스템 서비스 구성

Linux NGFW를 프로덕션에 배포하기 위한 systemd 서비스 구성입니다:

# /etc/systemd/system/ngfw-nftables.service
[Unit]
Description=NGFW nftables Rules
Before=suricata.service
After=network-pre.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/nft -f /etc/nftables-ngfw.conf
ExecReload=/usr/sbin/nft -f /etc/nftables-ngfw.conf
ExecStop=/usr/sbin/nft flush ruleset

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/ngfw-eswitch.service
[Unit]
Description=NGFW eSwitch TC flower Rules
After=ngfw-nftables.service
Requires=ngfw-nftables.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/usr/bin/devlink dev eswitch set pci/0000:03:00.0 mode switchdev
ExecStartPre=/usr/bin/sleep 2
ExecStartPre=/usr/sbin/ethtool -K eth0_rep0 hw-tc-offload on
ExecStart=/usr/local/bin/ngfw-tc-rules.sh
ExecStop=/usr/sbin/tc filter del dev eth0_rep0 ingress

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/ngfw-tuning.service
[Unit]
Description=NGFW Kernel Tuning
Before=ngfw-nftables.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c '\
  sysctl -w net.netfilter.nf_conntrack_max=2000000; \
  sysctl -w net.netfilter.nf_conntrack_buckets=500000; \
  sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=300; \
  sysctl -w net.netfilter.nf_flowtable_tcp_timeout=300; \
  sysctl -w net.core.optmem_max=81920; \
  sysctl -w net.core.netdev_budget=600; \
  sysctl -w net.core.netdev_max_backlog=10000; \
  sysctl -w net.ipv4.ip_forward=1; \
  ethtool -C eth0 rx-usecs 50 rx-frames 64 adaptive-rx on; \
  ethtool -G eth0 rx 4096 tx 4096; \
  /usr/local/bin/set_irq_affinity.sh 0-3 eth0 \
'

[Install]
WantedBy=multi-user.target
# 서비스 활성화 및 시작 순서
systemctl enable ngfw-tuning ngfw-nftables ngfw-eswitch
systemctl enable suricata conntrackd

# 시작 순서: tuning → nftables → eswitch → suricata → conntrackd
systemctl start ngfw-tuning
systemctl start ngfw-nftables
systemctl start ngfw-eswitch
systemctl start suricata
systemctl start conntrackd

# 상태 확인
systemctl status ngfw-nftables ngfw-eswitch suricata conntrackd

멀티 테이블 파이프라인

TC chain을 사용하여 다단계 매칭 파이프라인을 구성합니다:

# chain 0: conntrack 추적 및 분기
tc filter add dev eth0_rep0 ingress chain 0 prio 1 \
  protocol ip flower ct_state -trk \
  action ct zone 1 pipe \
  action goto chain 1

# chain 1: 상태 기반 분기
tc filter add dev eth0_rep0 ingress chain 1 prio 1 \
  protocol ip flower ct_state +trk+est \
  action goto chain 2  # ESTABLISHED → Fast Path chain

tc filter add dev eth0_rep0 ingress chain 1 prio 2 \
  protocol ip flower ct_state +trk+new \
  action pass  # NEW → CPU (Slow Path)

# chain 2: Fast Path (NAT + forward)
tc filter add dev eth0_rep0 ingress chain 2 prio 1 \
  protocol ip flower \
  action ct zone 1 nat \
  action mirred egress redirect dev eth1_rep0

XDP DDoS Pre-filter 패턴

NGFW의 가장 앞단에서 XDP를 사용하여 DDoS/스캔 트래픽을 CPU 부하 없이 처리합니다. 이 패턴은 conntrack 테이블 포화를 방지하는 핵심 방어선입니다.

/* xdp_ddos_filter.c — NGFW XDP DDoS Pre-filter */
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>

/* 차단 IP 세트 (관리 도구에서 동적 업데이트) */
struct {
    __uint(type, BPF_MAP_TYPE_LPM_TRIE);
    __uint(max_entries, 100000);
    __uint(map_flags, BPF_F_NO_PREALLOC);
    __type(key, struct lpm_key);
    __type(value, __u32);
} blocklist SEC(".maps");

/* SYN flood 속도 제한 (per-source IP) */
struct {
    __uint(type, BPF_MAP_TYPE_LRU_HASH);
    __uint(max_entries, 1000000);
    __type(key, __be32);      /* source IP */
    __type(value, __u64);     /* timestamp + count */
} syn_rate SEC(".maps");

SEC("xdp")
int xdp_ddos_filter(struct xdp_md *ctx)
{
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;

    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > data_end) return XDP_DROP;
    if (eth->h_proto != __constant_htons(ETH_P_IP)) return XDP_PASS;

    struct iphdr *iph = (void *)(eth + 1);
    if ((void *)(iph + 1) > data_end) return XDP_DROP;

    /* 1. IP 차단 리스트 확인 (LPM Trie: CIDR 매칭) */
    struct lpm_key key = { .prefixlen = 32, .addr = iph->saddr };
    if (bpf_map_lookup_elem(&blocklist, &key))
        return XDP_DROP;  /* 차단 IP → 즉시 DROP (최소 지연) */

    /* 2. SYN flood 감지 (TCP SYN 패킷만) */
    if (iph->protocol == IPPROTO_TCP) {
        struct tcphdr *tcph = (void *)iph + (iph->ihl * 4);
        if ((void *)(tcph + 1) > data_end) return XDP_DROP;

        if (tcph->syn && !tcph->ack) {
            /* SYN 속도 제한: 소스 IP당 초당 100 SYN */
            __u64 *rate = bpf_map_lookup_elem(&syn_rate, &iph->saddr);
            __u64 now = bpf_ktime_get_ns();
            if (rate) {
                __u64 last = *rate & 0xFFFFFFFF00000000ULL;
                __u32 count = *rate & 0xFFFFFFFF;
                if (now - last < 1000000000ULL) { /* 1초 이내 */
                    if (count > 100)
                        return XDP_DROP; /* 속도 초과 → DROP */
                    *rate = last | (count + 1);
                } else {
                    *rate = (now & 0xFFFFFFFF00000000ULL) | 1;
                }
            } else {
                __u64 val = (now & 0xFFFFFFFF00000000ULL) | 1;
                bpf_map_update_elem(&syn_rate, &iph->saddr, &val, BPF_ANY);
            }
        }
    }

    return XDP_PASS;  /* 정상 → 커널 네트워크 스택으로 전달 */
}

char _license[] SEC("license") = "GPL";
코드 설명
  • 9-14행 (LPM_TRIE) LPM(Longest Prefix Match) Trie는 CIDR 블록(예: 192.168.0.0/16)을 효율적으로 매칭합니다. IP 차단 리스트를 bpftool map으로 동적 업데이트할 수 있습니다.
  • 40-42행 차단 IP가 발견되면 XDP_DROP을 반환하여 NIC 드라이버 수준에서 즉시 패킷을 폐기합니다. skb 할당도 발생하지 않으므로 최소한의 CPU 비용만 소모합니다.
  • 47-66행 (SYN 속도 제한) 소스 IP당 초당 SYN 패킷 수를 추적합니다. 100 SYN/초를 초과하면 DROP합니다. 이를 통해 SYN flood가 conntrack 테이블에 도달하기 전에 차단합니다.
# XDP DDoS 필터 운영 명령
# 프로그램 로드
ip link set dev eth0 xdp obj xdp_ddos_filter.o sec xdp

# IP 차단 리스트 관리 (bpftool)
bpftool map update pinned /sys/fs/bpf/xdp_ddos/blocklist \
  key hex 20 00 00 00 c0 a8 64 00 \
  value hex 01 00 00 00  # 192.168.100.0/32 차단

# SYN flood 상위 공격자 확인
bpftool map dump pinned /sys/fs/bpf/xdp_ddos/syn_rate | \
  sort -t: -k2 -rn | head -20

# XDP 통계 확인
ip -s link show dev eth0 | grep -A5 xdp

conntrackd HA (세션 동기화)

Active-Standby NGFW 클러스터에서 failover 시 기존 세션을 유지하려면 conntrack 테이블을 실시간 동기화해야 합니다:

# /etc/conntrackd/conntrackd.conf (NGFW HA)
Sync {
    Mode FTFW {          # Fault Tolerant (ack 기반 신뢰성)
        DisableExternalCache Off
        CommitTimeout 1800
        PurgeTimeout 5
    }

    # 동기화 프로토콜
    Multicast {
        IPv4_address 225.0.0.50
        Group 3780
        IPv4_interface 192.168.100.1  # HA 전용 인터페이스
        Interface eth2
        SndSocketBuffer 1249280
        RcvSocketBuffer 1249280
        Checksum on
    }
}

General {
    Nice -20                  # 높은 우선순위
    HashSize 32768
    HashLimit 131072          # 최대 동기화 엔트리

    # 동기화 대상 필터 (flowtable 오프로드 세션 포함)
    Filter From Kernelspace {
        Protocol Accept {
            TCP
            UDP
        }
        Address Ignore {
            IPv4_address 127.0.0.1   # 로컬 제외
            IPv4_address 224.0.0.0/4 # 멀티캐스트 제외
        }
    }
}
flowtable과 conntrackd의 상호작용: flowtable에 오프로드된 세션은 conntrack 테이블에도 남아있으므로 conntrackd가 정상적으로 동기화합니다. 다만 HW offload된 세션의 패킷/바이트 카운터는 GC 주기(1초)마다만 SW에 반영되므로, failover 시점에 최대 1초분의 통계가 손실될 수 있습니다. HW FDB 규칙은 Standby 노드의 NIC에 새로 설치해야 합니다.
# HA failover 스크립트 (Keepalived notify 스크립트)
#!/bin/bash
# /usr/local/bin/ngfw-failover.sh

case "$1" in
  "MASTER")
    # Active 전환: flowtable HW offload 재등록
    conntrackd -c           # 외부 캐시 → 커널 동기화
    conntrackd -k           # 커널 conntrack 동기화 요청

    # eSwitch FDB 규칙 재설치 (기존 EST 세션)
    nft flush flowtable inet ngfw ft
    nft add flowtable inet ngfw ft \
      { hook ingress priority 0\; devices = { eth0, eth1 }\; flags offload\; }

    # 기존 conntrack의 EST 세션을 flowtable에 재등록
    # (자동으로 다음 패킷이 도착하면 flow add @ft에 의해 등록됨)
    ;;
  "BACKUP")
    # Standby 전환: HW offload 정리
    conntrackd -f           # 외부 캐시 플러시
    nft flush flowtable inet ngfw ft
    ;;
esac
nftables + flowtable + TC flower 연동 패킷 RX TC flower (eSwitch) ct_state +est → HW fwd ct_state +new → pass CPU HW Fast Path nftables (CPU) NEW → ACL 검사 EST → flow add @ft Slow Path NFQUEUE Suricata DPI/IPS flowtable SW/HW offload TX HW match → 직접 전달 miss/NEW QUEUE offload 등록 ALLOW → offload Fast Path (HW/SW) Slow Path 오프로드 등록

XDP HW 오프로드와 라인레이트 DDoS 방어

XDP(eXpress Data Path)는 리눅스 커널의 네트워크 스택 최하단에서 BPF 프로그램을 실행하여 패킷을 초기 단계에 처리하는 프레임워크입니다. 특히 HW 오프로드 모드에서는 BPF 프로그램이 NIC의 ASIC/FPGA에서 직접 실행되어, CPU를 전혀 사용하지 않고 라인 레이트(Line Rate)로 패킷을 필터링합니다. 이 절에서는 XDP의 3가지 동작 모드, HW 오프로드의 제약사항, 라인레이트 DDoS 필터 구현, 그리고 XDP offload + TC flower + flowtable 3계층 방어 아키텍처를 다룹니다.

XDP 오프로드 모드 비교

XDP는 BPF 프로그램이 실행되는 위치에 따라 세 가지 모드로 동작합니다. 각 모드는 성능, 호환성, 기능 제약 사이의 트레이드오프(Trade-off)가 다릅니다.

모드실행 위치SKB 생성100G NIC 기준 ppsCPU 사용NIC 요구사항커널 API 플래그
Generic (SKB)네트워크 스택 내부 (tc ingress 이후)O (SKB 할당)~1~3 Mpps높음없음 (모든 NIC)XDP_FLAGS_SKB_MODE
Native (Driver)NIC 드라이버 NAPI poll 내부 (SKB 전)X (xdp_buff 직접)~24~40 Mpps중간 (코어당)XDP 지원 드라이버XDP_FLAGS_DRV_MODE
Offload (HW)NIC ASIC/FPGA 내부X~148 Mpps (라인 레이트)없음 (zero CPU)XDP HW offload 지원 NICXDP_FLAGS_HW_MODE
pps 수치 해석: 100Gbps 이더넷에서 최소 크기(64B) 패킷의 이론적 최대치는 약 148.8Mpps입니다. Generic 모드는 이의 1~2%, Native 모드는 16~27%, Offload 모드만이 100%인 라인 레이트를 달성합니다. DDoS 공격은 최소 크기 패킷을 대량으로 전송하므로, 볼류메트릭(Volumetric) 공격 방어에는 Offload 모드가 필수적입니다.

XDP 프로그램의 모드별 로딩 방법은 다음과 같습니다.

# Generic 모드 — 모든 NIC에서 동작 (테스트 용도)
ip link set dev eth0 xdpgeneric obj xdp_filter.o sec xdp

# Native 모드 — 드라이버 레벨 (고성능, 대부분의 최신 NIC)
ip link set dev eth0 xdp obj xdp_filter.o sec xdp

# HW Offload 모드 — NIC ASIC에서 직접 실행 (라인 레이트)
ip link set dev eth0 xdpoffload obj xdp_filter.o sec xdp

# 현재 XDP 프로그램 확인
ip link show dev eth0
# 출력 예: ... xdpoffload prog/id 42 tag abc123...

# XDP 프로그램 제거
ip link set dev eth0 xdpoffload off

# 커널에서 XDP HW offload 지원 여부 확인
ethtool -i eth0 | grep driver
# Netronome: nfp
# NVIDIA:    mlx5_core
bpftool feature probe dev eth0 | grep xdp

XDP HW 오프로드 제약사항과 지원 NIC

XDP HW 오프로드는 BPF 프로그램을 NIC 내부의 프로세서(마이크로엔진, FPGA 등)에서 실행하므로, CPU 기반 실행과는 다른 엄격한 제약이 있습니다.

NIC칩셋HW Offload 지원명령어 제한지원 맵 타입특이사항
Netronome Agilio CXNFP-4000/6000완전 지원최대 4,000+ BPF 명령어HASH, ARRAY, LPM_TRIE가장 성숙한 XDP HW offload 지원
NVIDIA ConnectX-6+mlx5부분 지원제한적 (단순 필터)제한적XDP_DROP/XDP_PASS 중심, 복잡한 로직 미지원
Intel E810ice미지원N/AN/ANative XDP만 지원, HW offload 계획 없음
Broadcom BCM5760xbnxt미지원N/AN/ANative XDP 지원

HW 오프로드 모드에서의 주요 제약사항은 다음과 같습니다.

개발 전략: HW 오프로드용 BPF 프로그램은 먼저 Native 모드에서 개발·검증한 후, HW 모드 제약에 맞게 단순화합니다. bpftool prog load xdp_filter.o /sys/fs/bpf/xdp_filter dev eth0 type xdp offload_dev eth0 명령으로 로드를 시도하면, 검증기가 HW 미지원 기능을 즉시 알려줍니다.

라인레이트 DDoS 필터 구현

HW 오프로드 가능한 XDP 프로그램으로 라인 레이트 DDoS 방어 필터를 구현합니다. 핵심 전략은 세 가지입니다: (1) LPM Trie 기반 IP 블랙리스트, (2) SYN 검증, (3) 소스별 패킷 레이트 제한입니다.

/* xdp_ddos_filter.c — HW offload 가능 DDoS 필터 */
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>

/* LPM Trie 키: prefix + IPv4 주소 */
struct lpm_key {
    __u32 prefixlen;
    __u32 addr;
};

/* 소스 IP별 카운터 */
struct rate_info {
    __u64 packets;
    __u64 bytes;
    __u64 last_reset;   /* HW 모드에서는 userspace에서 리셋 */
};

/* IP 블랙리스트 — LPM Trie (CIDR 매칭) */
struct {
    __uint(type, BPF_MAP_TYPE_LPM_TRIE);
    __uint(max_entries, 100000);
    __type(key, struct lpm_key);
    __type(value, __u64);       /* drop counter */
    __uint(map_flags, BPF_F_NO_PREALLOC);
} ip_blocklist SEC(".maps");

/* 소스 IP별 레이트 카운터 */
struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 1000000);
    __type(key, __u32);          /* src IP */
    __type(value, struct rate_info);
} rate_counters SEC(".maps");

/* 글로벌 설정 (userspace에서 업데이트) */
struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(max_entries, 4);
    __type(key, __u32);
    __type(value, __u64);
} config SEC(".maps");

/* 설정 인덱스 */
#define CFG_RATE_LIMIT_PPS   0   /* 소스당 최대 pps */
#define CFG_RATE_LIMIT_BPS   1   /* 소스당 최대 bps */
#define CFG_SYN_VALIDATE     2   /* SYN 검증 활성화 여부 */
#define CFG_DROP_COUNTER     3   /* 전체 드롭 카운터 */

static __always_inline __u64 get_config(__u32 idx)
{
    __u32 key = idx;
    __u64 *val = bpf_map_lookup_elem(&config, &key);
    return val ? *val : 0;
}

SEC("xdp")
int xdp_ddos_filter(struct xdp_md *ctx)
{
    void *data     = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;

    /* 이더넷 헤더 파싱 */
    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > data_end)
        return XDP_PASS;

    /* IPv4만 처리 */
    if (eth->h_proto != bpf_htons(ETH_P_IP))
        return XDP_PASS;

    struct iphdr *ip = (void *)(eth + 1);
    if ((void *)(ip + 1) > data_end)
        return XDP_PASS;

    __u32 src_ip = ip->saddr;

    /* === 1단계: LPM Trie IP 블랙리스트 === */
    struct lpm_key lpm = {
        .prefixlen = 32,
        .addr      = src_ip,
    };
    __u64 *blocked = bpf_map_lookup_elem(&ip_blocklist, &lpm);
    if (blocked) {
        __sync_fetch_and_add(blocked, 1);
        return XDP_DROP;
    }

    /* === 2단계: 소스별 레이트 제한 === */
    __u64 max_pps = get_config(CFG_RATE_LIMIT_PPS);
    if (max_pps > 0) {
        struct rate_info *info;
        info = bpf_map_lookup_elem(&rate_counters, &src_ip);
        if (info) {
            __u64 cur = __sync_fetch_and_add(&info->packets, 1);
            __sync_fetch_and_add(&info->bytes,
                                  data_end - data);
            if (cur > max_pps)
                return XDP_DROP;
        } else {
            struct rate_info new_info = {
                .packets    = 1,
                .bytes      = data_end - data,
                .last_reset = 0,
            };
            bpf_map_update_elem(&rate_counters, &src_ip,
                                &new_info, BPF_NOEXIST);
        }
    }

    /* === 3단계: TCP SYN 검증 === */
    if (ip->protocol == IPPROTO_TCP) {
        struct tcphdr *tcp = (void *)ip + (ip->ihl * 4);
        if ((void *)(tcp + 1) > data_end)
            return XDP_DROP;

        __u64 syn_check = get_config(CFG_SYN_VALIDATE);
        if (syn_check && tcp->syn && !tcp->ack) {
            /*
             * SYN 패킷 레이트 제한:
             * HW 모드에서는 SYN cookie 계산이 불가능하므로,
             * 단순 레이트 기반 SYN flood 완화를 적용합니다.
             * 소스 IP당 SYN 레이트가 임계치 초과 시 DROP.
             */
            struct rate_info *info;
            info = bpf_map_lookup_elem(&rate_counters, &src_ip);
            if (info && info->packets > (max_pps / 10))
                return XDP_DROP;
        }
    }

    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";
# BPF 프로그램 컴파일 (HW offload 호환)
clang -O2 -g -target bpf \
      -D__TARGET_ARCH_x86 \
      -c xdp_ddos_filter.c \
      -o xdp_ddos_filter.o

# HW offload 모드로 로드 (Netronome Agilio CX 예시)
ip link set dev eth0 xdpoffload obj xdp_ddos_filter.o sec xdp

# 로드 확인
bpftool prog show dev eth0
# 출력 예:
# 42: xdp  tag abc123def456  dev eth0  offloaded
#     loaded_at 2026-03-26T10:00:00+0900  uid 0
#     xlated 384B  jited 0B  memlock 4096B
#     map_ids 10,11,12

# IP 블랙리스트에 CIDR 추가 (userspace에서 맵 업데이트)
bpftool map update id 10 \
    key hex 20 00 00 00 c0 a8 01 00 \
    value hex 00 00 00 00 00 00 00 00
# → 192.168.1.0/32 차단

# 대역 차단 (/24)
bpftool map update id 10 \
    key hex 18 00 00 00 0a 00 01 00 \
    value hex 00 00 00 00 00 00 00 00
# → 10.0.1.0/24 차단

# 레이트 제한 설정 (소스당 10000 pps)
bpftool map update id 12 \
    key hex 00 00 00 00 \
    value hex 10 27 00 00 00 00 00 00

# SYN 검증 활성화
bpftool map update id 12 \
    key hex 02 00 00 00 \
    value hex 01 00 00 00 00 00 00 00

# 레이트 카운터 주기적 리셋 (cron 또는 userspace 데몬)
# HW 모드에서는 bpf_ktime_get_ns()를 사용할 수 없으므로
# userspace에서 주기적으로 카운터를 리셋해야 합니다
while true; do
    bpftool map dump id 11 | \
        awk '/key:/{k=$2} /packets:/{if($2>0) print k}' | \
        while read key; do
            bpftool map delete id 11 key hex $key
        done
    sleep 1
done

# 드롭 통계 확인
bpftool map dump id 10   # IP별 드롭 카운터
bpftool map dump id 12   # 글로벌 설정 및 통계
HW 오프로드 주의점: 위 코드에서 __sync_fetch_and_add()(원자적 카운터 증가)는 Netronome NFP에서 지원되지만, 모든 HW 오프로드 NIC에서 보장되지는 않습니다. 또한 BPF_F_NO_PREALLOC 플래그가 붙은 LPM Trie는 HW 맵으로 변환될 때 사전 할당(Pre-allocation)될 수 있어, max_entries를 실제 사용량에 맞게 설정해야 NIC 메모리를 초과하지 않습니다.

XDP offload + TC flower + flowtable 3계층 아키텍처

NGFW에서 최적의 DDoS 방어와 세션 오프로드를 달성하려면, XDP HW offload, TC flower eSwitch, nf_flowtable 세 가지 메커니즘을 계층적으로 조합해야 합니다. 각 계층은 서로 다른 유형의 트래픽을 담당하며, 상위 계층이 처리하지 못한 패킷만 하위 계층으로 전달됩니다.

계층처리 위치담당 역할처리량 (100G 기준)패킷 판단 기준
Layer 1: XDP HW OffloadNIC ASIC/FPGA볼류메트릭 DDoS 사전 필터100Gbps (라인 레이트)IP 블랙리스트, 레이트 제한, 프로토콜 이상
Layer 2: TC flower eSwitchNIC eSwitch FDB세션 레벨 ACL / NAT 오프로드40~80Gbps5-tuple 매칭, conntrack 상태, NAT 변환
Layer 3: nf_flowtable커널 소프트웨어확립된 세션 고속 포워딩10~20Gbpsconntrack ESTABLISHED, flowtable 등록
Slow Path커널 전체 스택전체 DPI/IPS/App-ID 검사1~5Gbps새 세션, 분류 미완료 패킷

3계층 아키텍처의 패킷 처리 흐름은 다음과 같습니다.

  1. Layer 1 — XDP HW Offload (라인 레이트 필터): NIC가 패킷을 수신하면, ASIC에 로드된 XDP BPF 프로그램이 먼저 실행됩니다. IP 블랙리스트 매칭(LPM_TRIE)과 소스별 레이트 제한을 수행하여, DDoS 공격 트래픽을 CPU에 도달하기 전에 차단합니다. 이 단계에서 볼류메트릭 공격의 대부분(90%+)이 제거됩니다.
  2. Layer 2 — TC flower eSwitch (세션 레벨 오프로드): XDP를 통과한 패킷은 eSwitch FDB(Forwarding Database)의 TC flower 규칙을 확인합니다. flowtable에 의해 설치된 HW 오프로드 규칙이 매칭되면, NIC 내부에서 NAT 변환과 MAC/VLAN 재작성을 수행하여 즉시 포워딩합니다.
  3. Layer 3 — nf_flowtable (SW 고속 경로): HW 오프로드가 불가능한 세션(예: GRE 터널, 소프트웨어 브릿지)이지만 conntrack ESTABLISHED 상태인 경우, 커널의 flowtable 소프트웨어 경로에서 Netfilter 훅을 우회하여 고속 포워딩합니다.
  4. Slow Path — 전체 검사: 위 세 계층 어디에도 해당하지 않는 패킷(새 세션, 미분류 트래픽)은 전체 Netfilter 훅 체인, conntrack, NFQUEUE DPI/IPS 검사를 거칩니다.
# === 3계층 구성 예시 ===

# --- Layer 1: XDP HW Offload (DDoS 사전 필터) ---
ip link set dev eth0 xdpoffload obj xdp_ddos_filter.o sec xdp

# --- Layer 2: TC flower + CT offload (세션 레벨) ---
# eSwitch 모드 활성화
devlink dev eswitch set pci/0000:03:00.0 mode switchdev

# CT offload 지원 TC flower 규칙 (nftables flowtable이 자동 생성)
# 수동 예시: 특정 서브넷 간 트래픽 HW 오프로드
tc filter add dev eth0 ingress protocol ip \
    flower ct_state +trk+est \
    ip_proto tcp \
    action ct zone 1 pipe \
    action mirred egress redirect dev eth1

# --- Layer 3: nf_flowtable (SW 고속 경로) ---
nft add table inet filter
nft add flowtable inet filter ft \
    '{ hook ingress priority 0; devices = { eth0, eth1 }; flags offload; }'
nft add chain inet filter forward \
    '{ type filter hook forward priority 0; }'
nft add rule inet filter forward \
    ct state established,related flow add @ft accept
nft add rule inet filter forward \
    ct state new accept

# flowtable offload 상태 확인
nft list flowtable inet filter ft
conntrack -L | grep OFFLOAD
# HW 오프로드 규칙 확인
tc filter show dev eth0 ingress | grep -A5 "ct_state"
계층 간 보완 관계: 각 계층은 독립적이 아니라 보완적으로 동작합니다. Layer 1(XDP)이 볼류메트릭 공격을 제거하면 Layer 2(TC flower)가 처리해야 할 패킷 수가 줄어들고, Layer 2가 확립된 세션을 오프로드하면 Layer 3(flowtable)과 Slow Path의 부하가 줄어듭니다. 이 계단식 필터링 구조가 NGFW의 전체 처리량을 극대화합니다.
XDP offload + TC flower + flowtable 3계층 방어 아키텍처 패킷 수신 Layer 1: XDP HW Offload NIC ASIC — IP 블랙리스트, 레이트 제한 100 Gbps DROP DDoS Layer 2: TC flower eSwitch eSwitch FDB — ACL, NAT, 세션 오프로드 40 Gbps HW Forward EST 세션 Layer 3: nf_flowtable 커널 SW — 확립된 세션 고속 포워딩 10 Gbps SW Forward EST (HW 불가) Slow Path: Full DPI/IPS Netfilter + conntrack + NFQUEUE + DPI 2 Gbps ACCEPT EST → offload 승격 NIC TX L1: XDP HW (100Gbps) L2: TC flower (40Gbps) L3: flowtable (10Gbps) Slow Path (2Gbps) offload 승격 각 계층이 트래픽을 계단식으로 필터링하여 하위 계층의 부하를 줄이는 구조

위 다이어그램은 3계층 방어 아키텍처의 패킷 흐름을 보여줍니다. 패킷이 수신되면 Layer 1(XDP HW Offload)에서 볼류메트릭 DDoS를 라인 레이트로 차단하고, 통과한 패킷은 Layer 2(TC flower eSwitch)에서 확립된 세션을 하드웨어 포워딩하며, HW 오프로드가 불가능한 세션은 Layer 3(nf_flowtable)에서 소프트웨어 고속 경로로 처리합니다. 어느 계층에도 해당하지 않는 새 세션만 Slow Path의 전체 DPI/IPS 검사를 거칩니다. Slow Path에서 ESTABLISHED로 전환된 세션은 flowtable을 통해 Layer 2로 승격(오프로드)됩니다.

계층 설계 시 주의점: Layer 1(XDP)의 블랙리스트와 Layer 2(TC flower)의 세션 테이블이 NIC 메모리를 공유하는 경우가 있습니다. 대규모 환경에서는 XDP 맵 엔트리 수와 TC flower 규칙 수의 합이 NIC의 TCAM/SRAM 용량을 초과하지 않도록 관리해야 합니다. Netronome NFP의 경우 약 2M 엔트리, NVIDIA ConnectX-6의 경우 약 16M FDB 엔트리를 지원합니다.

보안 vs 오프로드 트레이드오프

트레이드오프 모델

NGFW에서 가장 중요한 설계 결정은 어느 수준의 보안 검사를 활성화하고, 어느 지점에서 오프로드할 것인가입니다. 이 결정이 전체 시스템의 처리량을 결정합니다.

보안 수준 vs 오프로드 비율 vs 처리량 보안 수준 → L4 ACL +IPS +App-ID +SSL Insp. +Full DPI+DLP 0% 50% 100% 오프로드율 95% 80% 75% 40% 20% ~95G ~76G ~72G ~42G ~24G 오프로드 비율 실효 처리량 (100G NIC)

보안 기능을 추가할수록 오프로드 가능한 트래픽 비율이 줄어듭니다. 대략적인 모델:

오프로드 비율 측정

# conntrack 전체 세션 수
conntrack -C

# flowtable 오프로드된 세션 수
conntrack -L -p tcp --state ESTABLISHED | wc -l

# flowtable 통계 (nftables)
nft list flowtable inet ngfw ft

# ethtool HW offload 카운터
ethtool -S eth0 | grep offload

# 오프로드 비율 계산
# ratio = (flowtable_sessions / total_established) * 100
보안 기능오프로드 영향오프로드 비율비고
L3/L4 Stateful ACL영향 없음~95%HW ct_state 매칭
IPS (시그니처 검사)첫 패킷만 영향~80%ALLOW 후 오프로드
App-ID (L7 분류)초기 3~10 패킷~75%분류 완료 후 오프로드
SSL Inspection전체 세션 영향~40%복호화 세션은 CPU
URL FilteringHTTP/DNS만 영향~70%첫 요청 검사 후 오프로드
DLP (Data Loss Prevention)전체 페이로드 검사~30%대부분 CPU 처리
주기적 재검사 (Sampling)오프로드 해제 주기~60%바이트 임계치 기반

위협 회피 대응

공격자가 오프로드 메커니즘을 악용하여 검사를 회피할 수 있는 시나리오와 대응:

회피 기법설명대응
첫 패킷 위장정상 프로토콜로 시작 후 ESTABLISHED에서 악성 페이로드 전송주기적 샘플링 (N번째 패킷마다 DPI 재검사)
프로토콜 변경HTTP로 시작 후 터널링으로 프로토콜 변경바이트 카운터 감시, 임계치 초과 시 재분류
저속 공격 (Low & Slow)오프로드 유지하며 느린 속도로 데이터 유출세션 지속 시간 제한, 바이트 감사
단편화 공격IP fragment로 DPI 우회 시도단편화 패킷은 Exception Path에서 재조립 후 검사
세션 하이재킹오프로드된 세션의 5-tuple을 스푸핑하여 주입TCP 시퀀스 번호 검증 (SW 샘플링)
암호화 터널링정상 HTTPS 내부에 VPN 터널 생성바이트 패턴 분석, JA3 핑거프린트

주기적 샘플링 구현

오프로드된 세션에 대한 주기적 재검사(sampling)는 위협 회피를 방지하는 핵심 메커니즘입니다:

# nftables에서 바이트 기반 샘플링 구현
table inet ngfw_sampling {
    chain forward {
        type filter hook forward priority -50; policy accept;

        # 오프로드된 세션의 패킷이 N번째마다 CPU로 복귀
        # (flowtable timeout이 만료되면 자동으로 이 체인을 거침)

        # 10MB 이상 전송된 세션 → DPI 재검사
        ct state established \
            ct bytes gt 10485760 \
            ct mark != 0xfe \
            queue num 4 bypass  # 재검사용 별도 큐

        # 1시간 이상 지속된 세션 → 재분류
        ct state established \
            ct original packets gt 100000 \
            ct mark != 0xfe \
            queue num 4 bypass

        # 재검사 완료 마킹 (중복 방지)
        ct state established ct mark 0xfe accept
    }
}
샘플링과 성능의 균형: 샘플링 주기가 너무 짧으면(예: 1MB마다) Fast Path의 이점이 사라집니다. 권장 설정은 세션당 10~100MB 또는 5~60분 주기입니다. 고위험 Zone(Untrust → Trust)에서는 짧은 주기, 저위험 Zone(Trust → Trust)에서는 긴 주기 또는 비활성화합니다.

정책 설계 가이드

Zone-based 오프로드 정책 매트릭스

네트워크 Zone 간 트래픽 특성에 따라 오프로드 수준을 차별화합니다:

소스 Zone목적지 Zone검사 수준오프로드 정책예상 오프로드율
Trust (내부)Trust (내부)L4 ACL만즉시 HW offload95%+
TrustDMZL4 ACL + App-ID분류 후 SW offload80%
TrustUntrust (인터넷)Full DPI + IPSDPI 완료 후 offload60~70%
UntrustDMZ (서버)Full DPI + IPS + WAFDPI 완료 후 offload50~60%
UntrustTrustFull DPI + IPS + DLPDPI 완료 후 offload (제한적)40~50%
GuestUntrustURL Filter + IPSURL 검사 후 offload65%
IoTCloudApp-ID + 주기적 재검사조건부 offload (샘플링)70%

nftables Zone 구현 예시

# Zone-based NGFW nftables 설정
table inet ngfw_zones {
    # Zone별 flowtable (오프로드 수준 차별화)
    flowtable ft_trust {
        hook ingress priority 0
        devices = { eth0 }    # 내부 네트워크
        flags offload          # HW offload 활성화
    }

    flowtable ft_untrust {
        hook ingress priority 0
        devices = { eth1 }    # 인터넷 연결
        # flags offload 미설정 → SW offload만
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
        ct state invalid drop

        # Trust → Trust: 즉시 HW offload (DPI 건너뜀)
        iifname "eth0" oifname "eth0" \
            ct state established,related \
            flow add @ft_trust accept

        # Trust → Untrust: DPI 검사 후 SW offload
        iifname "eth0" oifname "eth1" \
            ct state established,related \
            flow add @ft_untrust accept

        # Untrust → DMZ: 반드시 DPI 검사
        iifname "eth1" oifname "eth2" \
            ct state new \
            queue num 0-3 fanout

        # Untrust → DMZ: DPI 완료 후에만 offload
        iifname "eth1" oifname "eth2" \
            ct state established ct mark 0xff \
            flow add @ft_untrust accept
    }
}

오프로드 비율 정량 모델

NGFW의 전체 처리량은 Fast Path와 Slow Path의 가중 합으로 모델링됩니다:

처리량 공식: Total_Throughput = (Offload_Ratio × Fast_Path_BW) + ((1 - Offload_Ratio) × Slow_Path_BW)

예시: 오프로드 70%, Fast Path 100Gbps, Slow Path 5Gbps인 경우:
Total = (0.70 × 100) + (0.30 × 5) = 70 + 1.5 = 71.5 Gbps

오프로드 비율이 10% 증가하면(70% → 80%):
Total = (0.80 × 100) + (0.20 × 5) = 80 + 1.0 = 81.0 Gbps (+13%)

이 모델에서 Slow Path 처리량(DPI 성능)보다 오프로드 비율을 높이는 것이 전체 성능에 훨씬 큰 영향을 미칩니다. 오프로드 비율 1% 향상은 Slow Path 성능 20% 향상과 동등한 효과를 가집니다.

보안 수준별 성능 영향 시뮬레이션

보안 프로파일활성 기능오프로드율100G NIC 실효 처리량CPS 영향
MinimalL4 Stateful ACL95%~95 Gbps200K+ CPS
Standard+ IPS + App-ID75%~76 Gbps100K CPS
Enhanced+ SSL Inspection45%~47 Gbps30K CPS
Maximum+ DLP + AV + 주기적 재검사20%~24 Gbps10K CPS

성능 튜닝과 벤치마크

RFC 9411 메트릭

NGFW 성능 측정에 사용되는 주요 메트릭 (RFC 9411 — Benchmarking Methodology for Network Security Device Performance):

IRQ Affinity / NUMA 최적화

NGFW에서 CPU 코어 할당은 성능에 결정적입니다. NIC IRQ, Netfilter, DPI 엔진을 올바른 NUMA 노드와 코어에 배치해야 합니다:

# NUMA 토폴로지 확인
lscpu | grep -E "NUMA|Socket|Core"
# NUMA node0 CPU(s): 0-7    (NIC PCI 슬롯과 같은 노드)
# NUMA node1 CPU(s): 8-15

# NIC의 NUMA 노드 확인
cat /sys/class/net/eth0/device/numa_node
# 0  ← NIC이 NUMA 노드 0에 연결

# IRQ Affinity: NIC IRQ를 같은 NUMA 노드 코어에 바인딩
# eth0의 IRQ 번호 확인
grep eth0 /proc/interrupts | awk '{print $1}' | tr -d ':'
# IRQ 42, 43, 44, 45 (4개 큐)

# 각 IRQ를 NUMA node0 코어에 1:1 바인딩
echo 1 > /proc/irq/42/smp_affinity   # CPU 0
echo 2 > /proc/irq/43/smp_affinity   # CPU 1
echo 4 > /proc/irq/44/smp_affinity   # CPU 2
echo 8 > /proc/irq/45/smp_affinity   # CPU 3

# 또는: mlx5/ice 드라이버의 set_irq_affinity 스크립트
/usr/sbin/set_irq_affinity_cpulist.sh 0-3 eth0

NGFW 코어 배치 가이드

역할코어 할당NUMA 요구이유
NIC IRQ (NAPI poll)0~3NIC과 같은 노드DMA 버퍼가 로컬 메모리에 위치
XDP pre-filter0~3 (IRQ와 동일)NIC과 같은 노드XDP는 NAPI 컨텍스트에서 실행
conntrack / nftables0~3 (softirq)NIC과 같은 노드skb가 생성된 코어에서 처리
Suricata DPI 워커4~11NIC과 같은 노드 우선NFQUEUE 패킷 접근 locality
conntrackd (HA)12어느 노드든netlink 이벤트 수신
관리 (SSH, 모니터링)13~15어느 노드든데이터 플레인과 분리

CPS/처리량/지연 최적화

# ===== 1. conntrack 최적화 =====
sysctl -w net.netfilter.nf_conntrack_max=2000000
sysctl -w net.netfilter.nf_conntrack_buckets=500000
# 해시 충돌 최소화: buckets ≥ max/4

# conntrack 타임아웃 단축 (빠른 리소스 회수)
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=300
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_close_wait=30

# ===== 2. flowtable 최적화 =====
sysctl -w net.netfilter.nf_flowtable_tcp_timeout=300
sysctl -w net.netfilter.nf_flowtable_udp_timeout=30

# ===== 3. NFQUEUE 최적화 =====
sysctl -w net.core.optmem_max=81920
# NFQUEUE 소켓 버퍼 증가 → 버스트 트래픽 대응
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216

# ===== 4. NIC RSS/ethtool 최적화 =====
# RSS 큐를 IRQ affinity 코어 수에 맞춤
ethtool -L eth0 combined 4

# Interrupt Coalescing (배치 처리로 IRQ 빈도 감소)
ethtool -C eth0 rx-usecs 50 rx-frames 64 \
  tx-usecs 50 tx-frames 64 adaptive-rx on

# Ring Buffer 크기 증가 (버스트 흡수)
ethtool -G eth0 rx 4096 tx 4096

# HW offload 기능 활성화
ethtool -K eth0 hw-tc-offload on
ethtool -K eth0 ntuple on

# ===== 5. XDP DDoS pre-filter =====
ip link set dev eth0 xdp obj xdp_ddos_filter.o sec xdp

# ===== 6. eSwitch 최적화 =====
devlink dev eswitch set pci/0000:03:00.0 mode switchdev
devlink dev eswitch set pci/0000:03:00.0 inline-mode transport

# ===== 7. 커널 파라미터 =====
sysctl -w net.core.netdev_budget=600
sysctl -w net.core.netdev_max_backlog=10000
sysctl -w net.ipv4.ip_forward=1

# NAPI busy_poll (지연 최소화)
sysctl -w net.core.busy_read=50
sysctl -w net.core.busy_poll=50

ethtool Interrupt Coalescing 상세

NGFW에서 Interrupt Coalescing은 처리량과 지연 사이의 균형을 결정합니다:

설정rx-usecsrx-frames적합 시나리오영향
Low Latency108VoIP, 금융 트래픽IRQ 빈도 높음, CPU 사용률 증가
Balanced5064일반 NGFW적절한 지연/처리량 균형
High Throughput100128대용량 파일 전송 위주지연 증가, 처리량 최대화
Adaptiveadaptive-rx on-트래픽 변동이 큰 환경NIC이 트래픽에 따라 자동 조절
단계별 처리량 상한선 (Ceiling) 및 병목 0 Gbps 25 Gbps 50 Gbps 75 Gbps 100 Gbps 100G NIC RX 80G XDP 40G conntrack 40G flowtable 10G NFQUEUE 5G DPI/IPS BOTTLENECK 100G TX DPI가 병목 → ESTABLISHED 세션을 Fast Path로 오프로드하여 DPI 부하 최소화

벤치마크 방법론 (RFC 9411)

NGFW 성능을 올바르게 측정하기 위한 RFC 9411 기반 방법론입니다:

테스트 유형측정 대상트래픽 프로파일도구
CPS 측정초당 새 TCP 연결1-packet HTTP 요청 (MSS 크기)TRex, iperf3 --parallel
처리량 (Throughput)Mbps/GbpsESTABLISHED 대량 UDP/TCP 스트림TRex, DPDK pktgen
Latency 측정패킷 지연고정 크기 패킷 스트림moongen, TRex
NGFW 처리량DPI 활성 시 처리량HTTP/HTTPS 혼합 실제 트래픽TRex ASTF (app-layer)
SSL 처리량SSL 인스펙션 시 처리량TLS 1.2/1.3 혼합TRex + nginx SSL 백엔드
혼합 부하CPS + 처리량 동시실제 트래픽 PCAP 재생TRex 리플레이 모드
# TRex를 사용한 NGFW 벤치마크 예시

# 1. CPS 측정 (TCP SYN flood → 세션 수립률 측정)
./t-rex-64 -f cap2/http_simple.yaml \
  --duration 60 --multiplier 100000 \
  --latency 1000

# 2. 처리량 측정 (기존 세션에 대량 트래픽)
./t-rex-64 -f cap2/imix_64_594_1518.yaml \
  --duration 120 --multiplier 1 \
  --astf  # Application-layer TRex

# 3. 결과에서 Fast Path / Slow Path 분리 확인
# TRex 실행 중 DUT에서:
conntrack -C                          # 전체 세션 수
conntrack -L --status OFFLOAD | wc -l # 오프로드 세션
ethtool -S eth0 | grep tx_packets_phy # HW 처리 패킷
메트릭HW Fast PathSW Fast PathSlow Path (DPI)
처리량 (64B 패킷)148.8 Mpps (100GbE)10~20 Mpps1~3 Mpps
처리량 (1518B 패킷)8.1 Mpps (100GbE)3~5 Mpps0.5~1 Mpps
지연 (Latency)<5 us10~50 us100~500 us
CPS (초당 새 연결)N/A (오프로드만)N/A50K~200K/core
동시 세션NIC 의존 (1M~)conntrack_maxconntrack_max
CPU 코어 사용01~2 코어4~16 코어

패킷 크기별 성능 특성

NGFW 성능은 패킷 크기에 크게 의존합니다. 작은 패킷은 PPS(초당 패킷)에 의해, 큰 패킷은 BPS(초당 비트)에 의해 제한됩니다:

패킷 크기HW offload PPSHW offload BPSSW flowtable PPSDPI (Slow Path) PPS주요 트래픽
64B148.8 Mpps76.2 Gbps15 Mpps2 MppsTCP ACK, SYN
128B84.5 Mpps86.5 Gbps12 Mpps1.5 MppsVoIP (G.711)
256B45.3 Mpps92.8 Gbps8 Mpps1 MppsDNS 응답
512B23.5 Mpps96.3 Gbps5 Mpps0.8 Mpps웹 요청
1024B12.0 Mpps98.3 Gbps3.5 Mpps0.6 Mpps파일 전송
1518B (MTU)8.1 Mpps98.4 Gbps3 Mpps0.5 Mpps대용량 전송
IMIX (혼합)~30 Mpps~80 Gbps~8 Mpps~1 Mpps실제 트래픽

IMIX(Internet Mix)는 실제 인터넷 트래픽을 모사한 혼합 패킷 크기 분포입니다 (7:4:1 비율로 64B:594B:1518B). NGFW 벤치마크에서는 IMIX 또는 HTTP 애플리케이션 트래픽을 사용하는 것이 실제 환경에 가장 가깝습니다.

성능 최적화 체크리스트

NGFW 성능 최적화 우선순위 (효과 순):
  1. 오프로드 비율 극대화 — flowtable + HW offload로 EST 세션 비율 70%+ 달성 (가장 큰 효과)
  2. NFQUEUE 최적화 — fanout 분산 + batchcount + fail-open으로 DPI 병목 해소
  3. IRQ/NUMA 최적화 — NIC IRQ를 같은 NUMA 노드 코어에 바인딩
  4. conntrack 튜닝 — 해시 버킷 최적화 + 타임아웃 단축으로 테이블 효율 향상
  5. Interrupt Coalescing — ethtool -C로 IRQ 빈도 최적화
  6. XDP pre-filter — DDoS/스캔 트래픽을 가장 빠른 경로에서 DROP
  7. DPI 시그니처 최적화 — 불필요한 시그니처 비활성화로 Suricata 부하 감소

진단과 모니터링

모니터링 아키텍처

NGFW의 각 구성 요소에서 메트릭을 수집하여 중앙 모니터링 시스템으로 전달하는 아키텍처입니다:

NGFW 모니터링 아키텍처 데이터 소스 ethtool -S (NIC HW) conntrack -L (세션) nft list (flowtable) tc -s filter (TC flower) Suricata stats.log bpftrace (커널 이벤트) 메트릭 수집기 node_exporter + textfile collector ngfw-metrics.sh (1초 주기 크론) Prometheus TSDB 저장 Alertmanager 임계치 알림 Grafana 대시보드 알림 조건: conntrack > 80%, NFQUEUE drops > 0 offload ratio < 50%, CPS > threshold

핵심 알림 규칙

알림조건심각도대응
conntrack 포화entries/max > 0.8Warningnf_conntrack_max 증가 또는 타임아웃 단축
conntrack 가득 참entries/max > 0.95Critical즉시 타임아웃 단축 + early_drop 활성화
NFQUEUE 드롭drops/s > 0WarningSuricata 워커 증가 또는 batchcount 조정
오프로드 비율 저하ratio < 0.5Warningflowtable 설정 확인, ALG 세션 분석
HW offload 실패devlink trap 증가InfoNIC 펌웨어(Firmware)/드라이버 업데이트 확인
DPI 엔진 과부하Suricata kernel_drops > 0Critical워커 스레드(Thread) 추가, 규칙 최적화

flowtable 진단

# flowtable 오프로드 상태 확인
nft list flowtable inet ngfw ft

# conntrack 테이블에서 offloaded 세션 확인
conntrack -L --status OFFLOAD

# conntrack 이벤트 실시간 모니터
conntrack -E -e NEW,DESTROY

# TC flower 오프로드 규칙 통계
tc -s filter show dev eth0_rep0 ingress

# eSwitch FDB 규칙 확인
tc -s filter show dev eth0_rep0 ingress chain 0

# ethtool 오프로드 카운터
ethtool -S eth0 | grep -E '(offload|flower|ct)'

# devlink 트랩 (오프로드 실패 원인)
devlink trap show pci/0000:03:00.0

bpftrace / perf 진단

# flowtable offload 이벤트 추적
bpftrace -e 'kprobe:nf_flow_offload_add { printf("flow offload add: %s\n", comm); }'

# conntrack NEW 이벤트 빈도 측정 (CPS 추정)
bpftrace -e 'kprobe:__nf_conntrack_alloc { @cps = count(); }
             interval:s:1 { printf("CPS: %d\n", @cps); clear(@cps); }'

# NFQUEUE 지연 측정
perf probe -a 'nf_queue_entry_get_refs'
perf stat -e probe:nf_queue_entry_get_refs -a sleep 10

# Netfilter 훅 처리 시간 분포
bpftrace -e 'kprobe:nf_hook_slow { @start[tid] = nsecs; }
             kretprobe:nf_hook_slow /@start[tid]/ {
               @latency_us = hist((nsecs - @start[tid]) / 1000);
               delete(@start[tid]);
             }'

Prometheus 메트릭 수집

NGFW의 성능을 지속적으로 모니터링하기 위한 주요 메트릭과 수집 방법입니다:

#!/bin/bash
# /usr/local/bin/ngfw-metrics.sh
# node_exporter textfile collector용 메트릭 생성

METRICS_DIR="/var/lib/node_exporter/textfile_collector"

{
  # conntrack 메트릭
  ct_count=$(conntrack -C 2>/dev/null || echo 0)
  ct_max=$(sysctl -n net.netfilter.nf_conntrack_max)
  echo "ngfw_conntrack_entries $ct_count"
  echo "ngfw_conntrack_max $ct_max"
  echo "ngfw_conntrack_utilization $(echo "scale=4; $ct_count/$ct_max" | bc)"

  # flowtable 오프로드 세션 수
  offloaded=$(conntrack -L --status OFFLOAD 2>/dev/null | wc -l)
  echo "ngfw_flowtable_offloaded_sessions $offloaded"

  # 오프로드 비율
  established=$(conntrack -L -p tcp --state ESTABLISHED 2>/dev/null | wc -l)
  if [ "$established" -gt 0 ]; then
    ratio=$(echo "scale=4; $offloaded/$established" | bc)
    echo "ngfw_offload_ratio $ratio"
  fi

  # NIC HW offload 카운터 (mlx5)
  for stat in tx_packets_phy rx_packets_phy \
              rx_vport_rdma_unicast_packets \
              tx_vport_rdma_unicast_packets; do
    val=$(ethtool -S eth0 2>/dev/null | grep "$stat" | awk '{print $2}')
    [ -n "$val" ] && echo "ngfw_nic_${stat} $val"
  done

  # TC flower 규칙 수
  tc_rules=$(tc -s filter show dev eth0_rep0 ingress 2>/dev/null | grep -c "filter")
  echo "ngfw_tc_flower_rules $tc_rules"

  # NFQUEUE 드롭 (과부하 지표)
  nfq_drops=$(cat /proc/net/netfilter/nfnetlink_queue 2>/dev/null | \
    awk '{sum+=$5} END {print sum+0}')
  echo "ngfw_nfqueue_drops $nfq_drops"

} > "$METRICS_DIR/ngfw.prom.$$"
mv "$METRICS_DIR/ngfw.prom.$$" "$METRICS_DIR/ngfw.prom"

실시간 성능 대시보드 스크립트

#!/bin/bash
# /usr/local/bin/ngfw-dashboard.sh — 실시간 NGFW 상태
watch -n 1 '
echo "===== NGFW Status ====="
echo ""
echo "--- Conntrack ---"
printf "  Entries:    %s / %s\n" $(conntrack -C) $(sysctl -n net.netfilter.nf_conntrack_max)
printf "  Offloaded:  %s\n" $(conntrack -L --status OFFLOAD 2>/dev/null | wc -l)
echo ""
echo "--- Flowtable ---"
nft list flowtable inet ngfw ft 2>/dev/null | tail -5
echo ""
echo "--- TC flower (HW rules) ---"
tc -s filter show dev eth0_rep0 ingress 2>/dev/null | \
  grep -E "(filter|action|Sent)" | head -20
echo ""
echo "--- NIC Offload Stats ---"
ethtool -S eth0 2>/dev/null | grep -E "(offload|flower|ct)" | head -10
echo ""
echo "--- NFQUEUE ---"
cat /proc/net/netfilter/nfnetlink_queue 2>/dev/null
'

트러블슈팅 체크리스트

오프로드가 작동하지 않을 때 점검 사항:
  1. eSwitch 모드 확인: devlink dev eswitch showmode switchdev인가?
  2. hw-tc-offload 활성화: ethtool -k eth0 | grep hw-tc-offloadon인가?
  3. flowtable flags offload: nftables flowtable에 flags offload가 설정되었는가?
  4. NIC 드라이버 지원: mlx5/ice 등 TC flower ct offload를 지원하는 드라이버인가?
  5. conntrack 상태: conntrack -L --status OFFLOAD에 엔트리가 있는가?
  6. devlink trap 확인: HW offload 실패 이유가 trap으로 보고되는가?
  7. 커널 버전: flowtable HW offload는 커널 5.13+, CT offload는 5.7+ 필요
  8. 펌웨어 버전: NIC 펌웨어가 CT offload를 지원하는 버전인가?

자주 발생하는 문제와 해결

증상원인해결 방법
오프로드 비율이 0% flowtable에 flags offload 미설정 nft list flowtable에서 flags 확인 → offload 추가
HW offload는 되지만 NAT가 안 됨 TC flower에서 ct nat action 누락 TC 규칙에 action ct zone 1 nat 추가
conntrack 테이블이 빠르게 가득 참 DDoS/스캔으로 인한 NEW 세션 폭주 XDP pre-filter 활성화 + conntrack 타임아웃 단축
NFQUEUE에서 패킷 드롭 Suricata 처리 속도 부족 워커 스레드 증가, batchcount 최적화, bypass 활성화
flowtable 세션이 빠르게 만료 nf_flowtable_tcp_timeout이 너무 짧음 300초 이상으로 증가 (conntrack EST 타임아웃과 동기화)
특정 세션이 오프로드되지 않음 ALG helper가 할당된 세션 conntrack -L | grep helper로 확인 → 정상 동작 (ALG는 오프로드 불가)
eSwitch 전환 후 네트워크 끊김 switchdev 모드 전환 시 VF 재설정 필요 VF representor 재생성 + IP 재설정
TC flower 규칙이 HW에 설치되지 않음 NIC가 해당 매칭 조건 미지원 dmesg | grep tc로 에러 확인 → SW 폴백 또는 규칙 단순화

디버깅용 커널 트레이싱

# flowtable 이벤트 전체 추적 (디버깅 시에만 사용)
# 주의: 프로덕션에서는 성능 영향 있음

# 1. ftrace로 flowtable 함수 추적
echo 'nf_flow_offload*' > /sys/kernel/debug/tracing/set_ftrace_filter
echo function > /sys/kernel/debug/tracing/current_tracer
echo 1 > /sys/kernel/debug/tracing/tracing_on
cat /sys/kernel/debug/tracing/trace_pipe | head -100
echo 0 > /sys/kernel/debug/tracing/tracing_on

# 2. perf로 Netfilter 훅 프로파일링
perf top -g -e cycles:k --filter='nf_*'

# 3. bpftrace: flowtable HW offload 성공/실패 추적
bpftrace -e '
kprobe:nf_flow_offload_hw_add {
    printf("HW add: ct=%p\n", arg2);
}
kretprobe:nf_flow_offload_hw_add /retval != 0/ {
    printf("HW add FAILED: err=%d\n", retval);
}
kprobe:nf_flow_offload_hw_del {
    printf("HW del: flow=%p\n", arg1);
}'

# 4. conntrack 이벤트와 flowtable 이벤트 상관관계 추적
bpftrace -e '
kprobe:nf_conntrack_in {
    @ct_in = count();
}
kprobe:nf_flow_offload_ip_hook {
    @flow_hit = count();
}
interval:s:5 {
    printf("conntrack_in: %d, flow_hit: %d, ratio: ",
           @ct_in, @flow_hit);
    printf("%d%%\n",
           @flow_hit * 100 / (@ct_in + @flow_hit + 1));
    clear(@ct_in); clear(@flow_hit);
}'

커널 설정

커널 버전 요구사항

NGFW HW offload의 각 기능에 필요한 최소 커널 버전입니다:

기능최소 커널권장 커널관련 커밋/패치(Patch)
nf_flowtable 기본4.165.13+nf_flow_table 모듈 도입
flowtable HW offload5.136.1+NF_FLOWTABLE_HW_OFFLOAD 플래그
TC flower ct action5.75.13+NET_ACT_CT 모듈
mlx5 CT offload5.75.15+MLX5_TC_CT 설정
ice eSwitch switchdev5.156.1+ICE_SWITCHDEV 설정
nftables BPF verdict5.186.1+BPF netfilter 프로그램 타입
xfrm packet offload6.16.6+XFRM_OFFLOAD 확장
flowtable VLAN offload5.176.1+VLAN push/pop 지원
conntrack zone offload5.105.15+CT zone HW 지원
권장 커널: NGFW HW offload의 안정적 운영을 위해 커널 6.1 LTS 이상을 권장합니다. 이 버전에서 flowtable HW offload, TC flower CT, IPSec packet offload가 모두 안정화되었습니다.

필수 CONFIG_* 옵션

# Netfilter / conntrack
CONFIG_NF_CONNTRACK=y
CONFIG_NF_TABLES=y
CONFIG_NF_TABLES_INET=y
CONFIG_NFT_FLOW_OFFLOAD=y        # flowtable offload 지원
CONFIG_NF_FLOW_TABLE=y            # nf_flowtable 코어
CONFIG_NF_FLOW_TABLE_INET=y
CONFIG_NETFILTER_NETLINK_QUEUE=y  # NFQUEUE

# HW offload (eSwitch/TC)
CONFIG_NET_SWITCHDEV=y            # switchdev 프레임워크
CONFIG_NET_CLS_FLOWER=y           # TC flower classifier
CONFIG_NET_ACT_CT=y               # TC conntrack action
CONFIG_NET_ACT_MIRRED=y           # TC mirred (redirect)
CONFIG_NET_ACT_PEDIT=y            # TC packet edit
CONFIG_NET_ACT_TUNNEL_KEY=y       # TC tunnel encap/decap

# NIC 드라이버 (예: NVIDIA ConnectX)
CONFIG_MLX5_CORE=y
CONFIG_MLX5_ESWITCH=y
CONFIG_MLX5_TC_CT=y               # mlx5 CT offload

# XDP
CONFIG_XDP_SOCKETS=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y

# IPSec HW offload
CONFIG_XFRM=y
CONFIG_XFRM_OFFLOAD=y
CONFIG_INET_ESP_OFFLOAD=y

# conntrack 헬퍼 (ALG 프로토콜)
CONFIG_NF_CONNTRACK_FTP=m       # FTP ALG
CONFIG_NF_CONNTRACK_SIP=m       # SIP ALG
CONFIG_NF_CONNTRACK_H323=m      # H.323 ALG
CONFIG_NF_CONNTRACK_TFTP=m      # TFTP ALG
CONFIG_NF_CONNTRACK_PPTP=m      # PPTP ALG
CONFIG_NF_CT_NETLINK=y          # conntrackd 통신

# NAT 관련
CONFIG_NF_NAT=y
CONFIG_NF_NAT_MASQUERADE=y
CONFIG_NFT_NAT=y
CONFIG_NFT_MASQ=y

# NFQUEUE 관련
CONFIG_NETFILTER_NETLINK_QUEUE=y
CONFIG_NFT_QUEUE=y              # nft queue 표현식

# Intel E810 드라이버 (대안 NIC)
CONFIG_ICE=y
CONFIG_ICE_SWITCHDEV=y          # ice eSwitch 지원

# QoS 관련
CONFIG_NET_SCH_HTB=y            # HTB qdisc
CONFIG_NET_SCH_FQ_CODEL=y       # fq_codel (AQM)
CONFIG_NET_SCH_MQPRIO=y         # HW QoS 큐 매핑
CONFIG_NET_SCH_INGRESS=y        # TC ingress qdisc

모듈 로딩 순서와 검증

NGFW 관련 커널 모듈(Kernel Module)은 의존성 순서대로 로드해야 합니다. 다음은 systemd 서비스 이전에 실행할 모듈 로딩 스크립트입니다:

#!/bin/bash
# /usr/local/sbin/ngfw-modules-load.sh
# NGFW 커널 모듈 로딩 (의존성 순서)

set -e

# 1단계: 기본 Netfilter 프레임워크
modprobe nf_conntrack
modprobe nf_tables
modprobe nft_chain_nat
modprobe nft_ct              # nft ct 표현식

# 2단계: flowtable 오프로드
modprobe nf_flow_table
modprobe nf_flow_table_inet
modprobe nft_flow_offload    # nft flow offload 표현식

# 3단계: NFQUEUE (DPI 엔진 연동)
modprobe nfnetlink_queue
modprobe nft_queue           # nft queue 표현식

# 4단계: TC offload 프레임워크
modprobe act_ct              # TC conntrack action
modprobe act_mirred          # TC redirect action
modprobe act_pedit           # TC packet edit
modprobe cls_flower          # TC flower classifier

# 5단계: conntrack 헬퍼 (필요한 ALG만 선택 로드)
# modprobe nf_conntrack_ftp
# modprobe nf_conntrack_sip

# 6단계: IPSec offload (필요시)
# modprobe esp4_offload
# modprobe esp6_offload

echo "NGFW modules loaded successfully"
코드 설명
  • 7-10행 nf_conntracknf_tables가 모든 NGFW 기능의 기반입니다. nft_ct는 nftables에서 conntrack 상태를 매칭하는 표현식을 제공합니다.
  • 13-15행 nf_flow_table은 flowtable 코어 모듈이고, nft_flow_offload은 nftables에서 flow offload @ft 구문을 사용할 수 있게 합니다. 반드시 nf_conntrack 다음에 로드.
  • 18-19행 NFQUEUE는 Suricata 등 유저스페이스 DPI 엔진과의 통신을 담당합니다. nfnetlink_queue가 커널 측, libnetfilter_queue가 유저 측입니다.
  • 22-25행 TC flower는 eSwitch HW offload의 핵심입니다. act_ct가 TC에서 conntrack 조회를 가능하게 하고, act_mirred가 패킷 리다이렉트를 수행합니다.

모듈 로딩 후 다음 명령으로 검증합니다:

# 모듈 로딩 확인
lsmod | grep -E "nf_flow|nft_flow|nf_conntrack|cls_flower|act_ct"

# 기대 출력 예시:
# nft_flow_offload     20480  1
# nf_flow_table_inet   16384  1 nft_flow_offload
# nf_flow_table        36864  1 nf_flow_table_inet
# nf_conntrack        172032  5 nf_flow_table,nft_ct,...
# cls_flower           40960  0
# act_ct               20480  0

# dmesg에서 초기화 로그 확인
dmesg | grep -iE "flow.table|conntrack|switchdev"

# NIC eSwitch 상태 확인
devlink dev eswitch show pci/0000:03:00.0 2>/dev/null || echo "eSwitch not available"

# NIC hw-tc-offload 기능 확인
ethtool -k eth0 | grep hw-tc-offload

커널 부트 파라미터

# /etc/default/grub의 GRUB_CMDLINE_LINUX에 추가
# NGFW 최적화 커널 부트 파라미터

# IOMMU (SmartNIC SR-IOV/eSwitch 필수)
intel_iommu=on iommu=pt

# CPU 격리: 데이터 플레인 코어를 커널 스케줄러에서 분리
isolcpus=4-11                  # Suricata 전용 코어 격리
nohz_full=4-11                 # 격리 코어의 타이머 틱 제거
rcu_nocbs=4-11                 # RCU 콜백을 다른 코어에서 실행

# Hugepages (VPP/DPDK 사용 시)
default_hugepagesz=1G hugepagesz=1G hugepages=4

# NIC MMIO 매핑 최적화
pci=assign-busses              # PCI 버스 재할당

# 네트워크 스택 최적화
net.ifnames=0                  # 예측 가능한 인터페이스 이름 비활성화 (선택)

sysctl 튜닝 파라미터

파라미터기본값NGFW 권장값설명
nf_conntrack_max2621442000000최대 conntrack 엔트리 수
nf_conntrack_buckets65536500000conntrack 해시 테이블 버킷 수
nf_conntrack_tcp_timeout_established432000300TCP ESTABLISHED 타임아웃 (초)
nf_flowtable_tcp_timeout30300flowtable TCP 타임아웃
nf_flowtable_udp_timeout3030flowtable UDP 타임아웃
net.core.optmem_max2048081920NFQUEUE 소켓 옵션 메모리
net.core.netdev_budget300600NAPI poll 버짓
net.core.netdev_max_backlog100010000입력 큐 크기
net.ipv4.ip_forward01IP 포워딩 활성화
net.netfilter.nf_conntrack_helper00자동 헬퍼 비활성화 (보안)

운영 가이드

NGFW 초기 배포 절차

Linux 기반 NGFW를 처음부터 배포하는 단계별 가이드입니다:

단계작업명령/설정검증
1 커널 설정 확인 CONFIG_NF_FLOW_TABLE, CONFIG_MLX5_ESWITCH 등 확인 zcat /proc/config.gz | grep NF_FLOW
2 NIC 드라이버/펌웨어 mlx5/ice 드라이버 로드, 펌웨어 업데이트 ethtool -i eth0, devlink dev info
3 eSwitch switchdev 모드 devlink dev eswitch set pci/... mode switchdev devlink dev eswitch show
4 커널 파라미터 튜닝 sysctl 설정 (conntrack_max, flowtable timeout 등) sysctl net.netfilter.nf_conntrack_max
5 IRQ/NUMA 바인딩 NIC IRQ를 로컬 NUMA 코어에 바인딩 cat /proc/interrupts | grep eth0
6 nftables 규칙 설치 flowtable + forward chain + NFQUEUE 규칙 nft list ruleset
7 TC flower 규칙 ct_state 매칭 + HW forward 규칙 tc -s filter show dev eth0_rep0 ingress
8 Suricata DPI 설정 NFQUEUE 모드, 멀티스레드, App-Layer 설정 suricatasc -c uptime
9 conntrackd HA (선택) FTFW 모드, 멀티캐스트 동기화 conntrackd -s
10 모니터링 설정 Prometheus + Grafana + 알림 규칙 대시보드 접근 확인

일상 운영 명령 요약

# ===== 상태 확인 =====
# 전체 NGFW 상태 요약
echo "=== conntrack ===" && conntrack -C && \
echo "=== offloaded ===" && conntrack -L --status OFFLOAD 2>/dev/null | wc -l && \
echo "=== nft flowtable ===" && nft list flowtable inet ngfw ft 2>/dev/null && \
echo "=== suricata ===" && systemctl is-active suricata

# ===== 긴급 대응 =====
# DDoS 감지 시 XDP 긴급 필터 적용
ip link set dev eth0 xdp obj /usr/local/lib/xdp/emergency_block.o sec xdp

# conntrack 테이블 긴급 정리 (가득 참 상황)
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=60
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=5
conntrack -F  # 전체 플러시 (주의: 모든 세션 끊김)

# 특정 IP 긴급 차단
nft add element inet ngfw blocklist { 203.0.113.50 }

# ===== 정책 변경 =====
# 규칙 변경 시 기존 오프로드 세션 재평가
nft flush flowtable inet ngfw ft  # flowtable 초기화
# 이후 패킷이 도착하면 자동으로 새 규칙에 따라 재등록

# nftables 규칙 리로드 (서비스 무중단)
systemctl reload ngfw-nftables

# ===== 유지보수 =====
# Suricata 시그니처 업데이트
suricata-update
systemctl reload suricata

# NIC 펌웨어 업데이트 (다운타임 필요)
mlxfwmanager --online-activate

장애 복구 시나리오

장애 시나리오증상복구 절차
Suricata 크래시 NFQUEUE에 패킷 쌓임 → 지연 증가 fail-open: yes로 자동 bypass. systemctl restart suricata
conntrack 테이블 가득 새 연결 불가 (dmesg에 "nf_conntrack: table full") 타임아웃 단축 + nf_conntrack_max 증가. XDP DDoS 필터 확인
eSwitch HW 오류 HW offload 중단, SW 폴백으로 성능 저하 devlink trap show로 원인 확인. NIC 재설정 또는 펌웨어 업데이트
HA failover Active 노드 장애 → Standby 승격 conntrackd가 자동 동기화. flowtable은 다음 패킷부터 자동 재등록
메모리 부족 slab 할당 실패, conntrack alloc 실패 conntrack_max 감소, flowtable 타임아웃 단축, 불필요 규칙 정리

업그레이드/롤백(Rollback) 절차

NGFW 커널이나 NIC 펌웨어 업그레이드 시 무중단 또는 최소 중단을 위한 절차입니다:

구성요소업그레이드 방법중단 시간롤백 방법
Suricata 시그니처 suricata-update && systemctl reload suricata 0초 (graceful reload) suricata-update --force로 이전 버전 재적용
nftables 규칙 nft -f /etc/ngfw/ruleset-v2.nft (atomic replace) 0초 (원자적(Atomic) 교체) nft -f /etc/ngfw/ruleset-v1.nft 이전 규칙셋 복원
TC flower 규칙 새 규칙 추가 후 구 규칙 삭제 (순서 중요) 개별 규칙 <1ms 삭제한 규칙 재추가. HW 규칙은 NIC이 캐시 유지
NIC 펌웨어 mlxfwmanager --online-activate 10~30초 (NIC 리셋) 이전 펌웨어 이미지로 재플래시. HA 구성 시 failover 후 수행
커널 업그레이드 새 커널 설치 → GRUB 업데이트 → 재부팅 2~5분 (재부팅) GRUB에서 이전 커널 선택. grubby --set-default
eBPF/XDP 프로그램 ip link set dev eth0 xdp obj new_prog.o (atomic) 0초 (원자적 교체) ip link set dev eth0 xdp off로 제거 또는 이전 프로그램 로드
# ===== 안전한 커널 업그레이드 절차 (HA 구성) =====

# 1단계: Standby 노드에서 먼저 업그레이드
conntrackd -n  # Standby 역할 확인

# 2단계: 새 커널 설치
dnf install kernel-6.6.x  # 또는 dpkg -i linux-image-6.6.x

# 3단계: Standby 재부팅 (Active가 트래픽 처리 중)
reboot

# 4단계: 재부팅 후 검증
uname -r                    # 새 커널 버전 확인
lsmod | grep nf_flow_table  # 모듈 로딩 확인
conntrackd -s               # HA 동기화 상태 확인
suricatasc -c uptime        # Suricata 정상 기동 확인

# 5단계: Failover → 이 노드를 Active로 승격
conntrackd -c commit        # 캐시된 세션 커밋
conntrackd -k               # Active 역할 요청

# 6단계: 구 Active 노드도 동일 절차로 업그레이드

로그 관리와 감사

NGFW는 보안 장비이므로 로그 관리가 법적 요구사항일 수 있습니다. 주요 로그 소스와 관리 방안입니다:

로그 소스경로/방법포함 정보보존 기간 (권장)
nftables 로그 nft log → syslog 또는 nflog → ulogd2 차단/허용 verdict, 5-tuple, 카운터 90일+
conntrack 이벤트 conntrack -E 또는 conntrackd의 stats 로그 NEW/DESTROY 이벤트, 세션 지속 시간, 바이트 30일
Suricata EVE JSON /var/log/suricata/eve.json IPS alert, App-ID, DNS 쿼리, TLS 핸드셰이크, HTTP 메타데이터 90일+ (SIEM 전송)
flowtable 통계 nft list flowtable, ethtool -S 오프로드된 플로우 수, 바이트, 패킷 Prometheus에 시계열 저장
커널 메시지 dmesg, /var/log/kern.log conntrack table full, NIC 오류, OOM 30일
# /etc/rsyslog.d/ngfw.conf — NGFW 로그 분리 저장
# nftables LOG 타겟 로그
:msg, contains, "NGFW_" /var/log/ngfw/firewall.log
& stop

# conntrackd 로그
:programname, isequal, "conntrackd" /var/log/ngfw/conntrackd.log
& stop

# logrotate 설정
# /etc/logrotate.d/ngfw
# /var/log/ngfw/*.log {
#     daily
#     rotate 90
#     compress
#     delaycompress
#     missingok
#     notifempty
#     sharedscripts
#     postrotate
#         systemctl reload rsyslog
#     endscript
# }

용량 계획

NGFW 장비의 리소스 소요를 사전에 계획하기 위한 가이드입니다:

리소스계산 공식예시 (100K 동시 세션)
conntrack 메모리세션 수 × ~320 bytes/entry100K × 320B = ~32 MB
flowtable 메모리오프로드 세션 × ~256 bytes/entry70K × 256B = ~18 MB
conntrack 해시 버킷max_entries / 4 (권장)100K / 4 = 25K 버킷
NIC HW flow 엔트리NIC 의존 (CX-6: ~1M, E810: ~64K)70K (HW 한계 내)
Suricata 메모리기본 ~2GB + 시그니처 ~1GB + 세션 캐시~4 GB
DPI CPU 코어DPI 처리량 / 코어당 1~3 Gbps10 Gbps DPI → 4~10 코어

QUIC/TLS 1.3과 NGFW 오프로드

QUIC 프로토콜과 TLS 1.3의 Encrypted Client Hello(ECH)는 기존 NGFW의 DPI 기반 트래픽 분류 체계를 근본적으로 무력화합니다. 이 섹션에서는 QUIC/ECH 환경에서 NGFW 오프로드를 유지하기 위한 전략을 분석합니다.

QUIC 프로토콜이 NGFW에 미치는 영향

QUIC(RFC 9000)은 UDP 기반에 TLS 1.3 암호화를 내장한 전송 프로토콜입니다. 기존 TCP+TLS 스택과 비교하면 NGFW에 다음과 같은 도전을 제시합니다:

특성TCP + TLS 1.2/1.3QUICNGFW 영향
전송 프로토콜TCP (proto 6)UDP (proto 17)포트 기반 프로토콜 식별 불가 (UDP 443)
헤더 가시성TCP 헤더 평문, TLS record 헤더 평문Short Header: CID + 패킷 번호만 (암호화)DPI가 활용할 평문 메타데이터 극소
SNI 가시성Client Hello의 SNI 평문 (TLS 1.2/1.3)Initial Packet에만 SNI (ECH 시 암호화)URL Filtering 제한 또는 불가
세션 식별5-tuple 고정Connection ID (가변 길이)conntrack 5-tuple 키 무효화 가능
핸드셰이크TCP 3-way + TLS (2-3 RTT)1-RTT (0-RTT 재연결)NEW 세션 탐지 시점 불명확
연결 마이그레이션미지원 (새 TCP 연결 필요)지원 (CID 유지)flowtable 엔트리 갱신 불가
다중화(Multiplexing)연결당 하나의 스트림 (HTTP/2 제외)단일 연결에 다중 스트림하나의 conntrack 엔트리에 다중 논리 세션
오프로드 가능성높음 (EST 후 flowtable)제한적 (CID 추적 필요)CID 기반 오프로드 미지원
QUIC의 시장 점유율: 2025년 기준 전체 웹 트래픽의 약 30~40%가 QUIC을 사용합니다(Google, Meta, Cloudflare 서비스). Chrome은 기본적으로 QUIC을 활성화하며, HTTP/3는 QUIC 위에서 동작합니다. NGFW가 QUIC을 올바르게 처리하지 못하면 전체 트래픽의 상당 부분에 대해 보안 가시성을 잃게 됩니다.

QUIC 트래픽 탐지와 분류

QUIC 패킷은 첫 번째 바이트(Header Form bit)로 Long Header와 Short Header를 구분합니다. NGFW에서는 Initial Packet의 Long Header를 분석하여 QUIC 연결을 식별합니다.

패킷 유형Header Form첫 바이트 패턴가시 필드NGFW 활용
InitialLong (1)0b1100xxxx (0xC0~0xCF)Version, DCID, SCID, Token, LengthQUIC 탐지, 버전 확인, CID 추출
0-RTTLong (1)0b1101xxxx (0xD0~0xDF)Version, DCID, SCID, Length재연결 탐지
HandshakeLong (1)0b1110xxxx (0xE0~0xEF)Version, DCID, SCID, Length핸드셰이크 진행 확인
RetryLong (1)0b1111xxxx (0xF0~0xFF)Version, DCID, SCID, Retry TokenDoS 방어 확인
1-RTT (Short)Short (0)0b01xxxxxx (0x40~0x7F)DCID만 (나머지 암호화)CID로 기존 세션 매핑만 가능

nftables에서 QUIC 트래픽을 탐지하고 분류하는 규칙 예시입니다:

#!/usr/sbin/nft -f
# QUIC 트래픽 탐지 및 분류 nftables 규칙

table inet quic_detect {
    # QUIC Initial Packet 탐지 set (rate limiting용)
    set quic_new_conn {
        type ipv4_addr . inet_service
        flags dynamic,timeout
        timeout 30s
    }

    chain forward {
        type filter hook forward priority 0; policy accept;

        # UDP 443 트래픽 필터링
        udp dport 443 jump quic_classify

        # UDP 443 + UDP 80 (alt-svc 기반 QUIC 업그레이드)
        udp dport 80 @th,0,8 & 0x80 == 0x80 jump quic_classify
    }

    chain quic_classify {
        # Long Header 판별: 첫 번째 바이트 bit7 = 1
        @th,0,8 & 0x80 == 0x00 jump quic_short_header

        # QUIC v1 Initial Packet: first_byte & 0xF0 == 0xC0, version == 0x00000001
        @th,0,8 & 0xF0 == 0xC0 @th,8,32 == 0x00000001 \
            jump quic_initial

        # QUIC v2 Initial: version == 0x6b3343cf
        @th,0,8 & 0xF0 == 0xC0 @th,8,32 == 0x6b3343cf \
            jump quic_initial

        # 0-RTT Packet (재연결): first_byte & 0xF0 == 0xD0
        @th,0,8 & 0xF0 == 0xD0 \
            log prefix "QUIC-0RTT: " counter

        # Handshake Packet: first_byte & 0xF0 == 0xE0
        @th,0,8 & 0xF0 == 0xE0 counter accept
    }

    chain quic_initial {
        # 새 QUIC 연결 rate limiting (DDoS 방어)
        update @quic_new_conn { ip saddr . udp dport } \
            limit rate over 100/second burst 50 packets drop

        # 로깅 후 Slow Path로 전달 (DPI 검사)
        log prefix "QUIC-NEW: " counter accept
    }

    chain quic_short_header {
        # Short Header: 이미 확립된 QUIC 세션
        # conntrack EST 상태이면 flowtable으로 오프로드 가능
        ct state established flow add @ft counter accept
        ct state established counter accept
    }
}
코드 설명
  • 5-9행 QUIC 새 연결을 추적하는 동적 set입니다. 30초 타임아웃으로 자동 만료되며, DDoS rate limiting에 사용됩니다.
  • 15행 QUIC은 주로 UDP 443을 사용합니다. 이 규칙으로 잠재적 QUIC 트래픽을 필터링합니다.
  • 18행 @th,0,8은 transport header offset 0부터 8비트를 읽습니다. UDP 페이로드의 첫 바이트를 검사하여 Long Header 여부를 판별합니다.
  • 25-26행 Initial Packet은 0xC0~0xCF 범위이고, 바이트 1~4가 QUIC 버전입니다. v1(0x00000001)을 확인합니다.
  • 42-43행 새 QUIC 연결에 대해 source IP + port 조합으로 초당 100개까지 허용하고 초과분을 DROP합니다. QUIC flood 공격 방어입니다.
  • 50-51행 Short Header 패킷은 이미 QUIC 연결이 확립된 상태이므로 conntrack ESTABLISHED이면 flowtable 오프로드 대상입니다.

TLS 1.3 Encrypted Client Hello (ECH)

TLS 1.3의 ECH(RFC 9460 초안)는 Client Hello 메시지 내의 SNI(Server Name Indication)를 완전히 암호화합니다. ECH 이전에는 TLS 핸드셰이크의 Client Hello에서 SNI를 평문으로 읽어 URL Filtering과 트래픽 분류에 활용할 수 있었지만, ECH가 활성화되면 이 방법이 완전히 무력화됩니다.

기술ECH 이전ECH 이후대체 식별 방법
SNI 기반 URL FilteringClient Hello에서 SNI 평문 추출외부 SNI만 가시 (CDN 도메인)DNS 쿼리 모니터링, IP 평판 DB
인증서 기반 식별Server Hello의 인증서 평문TLS 1.3부터 인증서도 암호화OCSP stapling 분석, CT 로그
App-ID (DPI)SNI + ALPN + 인증서 조합ALPN만 부분 가시JA4 핑거프린트, 트래픽 패턴 분석
카테고리 필터링SNI → 도메인 → 카테고리 DB외부 SNI만으로는 정확도 저하DNS Response Policy Zone (RPZ)
SSL InspectionMITM 프록시로 복호화ECH 키 없이는 MITM 불가엔드포인트 에이전트, WARP 방식
JA3/JA4 핑거프린팅보조 식별 수단주요 식별 수단으로 격상JA4+ (JA4S, JA4H, JA4X 확장)
JA4 핑거프린트 구성: JA4는 TLS 핸드셰이크 특성을 t13d1516h2_8daaf6152771_e5627efa2ab1 형태의 해시로 요약합니다. 첫 부분은 프로토콜/버전/SNI유무/cipher수/extension수, 나머지는 cipher suite와 extension의 해시입니다. ECH로 SNI가 가려져도 브라우저·OS·앱별로 고유한 핑거프린트가 생성되어 식별이 가능합니다.

QUIC/ECH 환경의 NGFW 전략

QUIC과 ECH가 확산되는 환경에서 NGFW의 트래픽 가시성을 유지하기 위한 4가지 전략을 분석합니다:

전략 1: QUIC 차단/제어 (정책적 접근)

전략 2: 초기 핸드셰이크 기반 분류 후 오프로드

전략 3: DNS 기반 사전 분류 (DoH/DoT 제어)

전략 4: 엔드포인트 기반 (QUIC Client Hello 파싱)

다음은 nftables + Suricata를 조합하여 QUIC을 처리하는 종합 규칙 예시입니다:

#!/usr/sbin/nft -f
# QUIC/ECH 대응 NGFW nftables 규칙 (전략 1+2+3 조합)

table inet ngfw_quic {
    # 정책별 QUIC 처리 모드
    # 0: block (TCP fallback 유도)
    # 1: inspect (Initial만 DPI)
    # 2: allow (분류 후 오프로드)

    # DNS 기반 IP→카테고리 매핑 (외부 스크립트로 갱신)
    set dns_blocked_ips {
        type ipv4_addr
        flags interval
        # 예: DNS RPZ에서 차단 도메인의 IP를 자동 추가
    }

    set quic_allowed_dsts {
        type ipv4_addr
        flags interval
        # 예: 업무용 SaaS IP 대역 (QUIC 허용)
    }

    flowtable ft {
        hook ingress priority 0;
        devices = { eth0, eth1 };
        flags offload;
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # 1. conntrack EST 세션 → flowtable 오프로드
        ct state established,related flow add @ft counter accept

        # 2. DNS 기반 사전 차단 (전략 3)
        ip daddr @dns_blocked_ips counter drop

        # 3. QUIC 처리 (UDP 443)
        udp dport 443 jump quic_policy

        # 4. 일반 TCP/TLS → DPI (NFQUEUE)
        tcp dport 443 ct state new \
            queue num 0-3 fanout,bypass

        # 5. 기타 허용 규칙
        ct state established,related accept
    }

    chain quic_policy {
        # 허용된 목적지 → QUIC 허용 (오프로드 대상)
        ip daddr @quic_allowed_dsts accept

        # 나머지 QUIC → 정책에 따라 처리
        # 전략 1: 차단하여 TCP fallback 유도
        # icmp type port-unreachable 응답으로 빠른 fallback
        reject with icmpx port-unreachable

        # 전략 2를 사용할 경우 (위 reject 대신):
        # @th,0,8 & 0x80 == 0x80 queue num 4-5 fanout,bypass
        # @th,0,8 & 0x80 == 0x00 ct state established accept
    }
}
# Suricata QUIC 탐지 규칙 (suricata.rules에 추가)
# QUIC Initial Packet 탐지 (App-Layer)
alert quic $HOME_NET any -> $EXTERNAL_NET 443 \
  (msg:"QUIC Initial Packet detected"; \
   quic.version; content:"|00 00 00 01|"; \
   sid:3000001; rev:1;)

# QUIC 0-RTT 재연결 탐지 (Early Data 위험)
alert quic $HOME_NET any -> $EXTERNAL_NET 443 \
  (msg:"QUIC 0-RTT Early Data"; \
   quic.header.type; content:"|01|"; \
   sid:3000002; rev:1;)

# JA4 핑거프린트 기반 브라우저 식별 예시
alert tls $HOME_NET any -> $EXTERNAL_NET 443 \
  (msg:"TLS JA4 - Chrome Browser detected"; \
   ja4.hash; content:"t13d1516h2"; startswith; \
   sid:3000003; rev:1;)
QUIC vs TCP+TLS — NGFW 가시성 비교 TCP + TLS 1.3 TCP Header (평문) SrcPort | DstPort | Seq | Ack | Flags | Window 가시 TLS Record Header (평문) Content-Type | Version | Length 가시 Client Hello → SNI (평문) server_name = "example.com" | ALPN = "h2" 가시 Application Data (암호화) HTTP/2 요청/응답 → 암호화된 페이로드 불가 NGFW 활용 가능: 5-tuple 추적 ✓ | SNI 기반 분류 ✓ | conntrack EST 오프로드 ✓ 5-tuple 고정 → conntrack 추적 안정 10.0.0.1:45678 → 93.184.216.34:443 (TCP) QUIC (UDP + 내장 TLS) UDP Header (평문) SrcPort | DstPort(443) | Length | Checksum 최소 QUIC Long Header (Initial만) Form(1b) | Type | Version | DCID | SCID | Token 제한 QUIC Short Header (1-RTT) Form(0) | DCID만 (패킷번호+페이로드 암호화) 불가 CRYPTO Frame → ECH Client Hello SNI 암호화 | Outer SNI만 노출 (CDN 도메인) 불가 NGFW 한계: DPI 제한 ✗ | SNI 암호화 ✗ | CID 변경 시 세션 추적 ✗ 5-tuple 변경 가능 → conntrack 무효화 CID=0x1a2b (유지) | IP 10.0.0.1 → 10.0.0.5 (변경)

멀티 테넌트 NGFW 아키텍처

클라우드 환경과 MSSP(Managed Security Service Provider)에서는 단일 NGFW 인스턴스에서 다수의 테넌트(고객/VPC/네임스페이스)를 격리하여 운영해야 합니다. 이 섹션에서는 Linux 커널의 격리 메커니즘을 활용한 멀티 테넌트 NGFW 아키텍처를 분석합니다.

멀티 테넌시 격리 모델

Linux 커널에서 제공하는 네트워크 격리 기술을 NGFW 관점에서 비교합니다:

격리 방식격리 수준conntrack 격리flowtable 격리HW offload장점단점
네트워크 네임스페이스 완전 격리 (독립 네트워크 스택) 네임스페이스별 독립 conntrack 네임스페이스별 독립 flowtable VF를 네임스페이스에 이동 가능 가장 강력한 격리, 충돌 없음 리소스 오버헤드, 관리 복잡성
VRF (Virtual Routing & Forwarding) L3 라우팅 격리 공유 (zone으로 분리 필요) VRF별 설정 가능 TC flower에서 VRF 매칭 가능 라우팅 격리, 단일 스택 유지 L2 격리 불가, conntrack 추가 설정 필요
conntrack zone conntrack 테이블 격리 zone ID별 완전 격리 zone별 flowtable 분리 가능 TC flower ct zone 지원 경량, 기존 인프라 유지 nftables 규칙 복잡도 증가
eSwitch VF representor HW 수준 격리 VF별 conntrack zone 매핑 VF별 독립 flowtable VF당 독립 FDB 규칙 HW 격리, 최고 성능 VF 수 제한 (NIC 의존), SmartNIC 필요
nftables table/chain 분리 논리적 격리 (정책 분리) 공유 (mark/zone으로 구분) 공유 flowtable 공유 설정 단순, 유연한 정책 격리 보장 약함, 버그 시 누출

conntrack zone 기반 테넌트 격리

conntrack zone은 동일 커널 내에서 conntrack 테이블을 논리적으로 분리하는 가장 효율적인 방법입니다. 각 테넌트에 고유한 zone ID를 할당하면 동일한 5-tuple을 가진 세션도 충돌 없이 독립적으로 추적됩니다.

#!/usr/sbin/nft -f
# 멀티 테넌트 conntrack zone 설정
# 테넌트 A: zone 100, 테넌트 B: zone 200

table inet multi_tenant {
    # 테넌트별 독립 flowtable
    flowtable ft_tenant_a {
        hook ingress priority 0;
        devices = { eth0, eth1 };
        flags offload;
    }

    flowtable ft_tenant_b {
        hook ingress priority 0;
        devices = { eth0, eth2 };
        flags offload;
    }

    # 테넌트 분류 체인 (ingress에서 mark 설정)
    chain prerouting {
        type filter hook prerouting priority -150; policy accept;

        # 서브넷 기반 테넌트 분류
        ip saddr 10.100.0.0/16 meta mark set 100
        ip saddr 10.200.0.0/16 meta mark set 200

        # VLAN 기반 테넌트 분류 (대안)
        # vlan id 100 meta mark set 100
        # vlan id 200 meta mark set 200

        # mark → conntrack zone 매핑
        meta mark 100 ct zone set 100
        meta mark 200 ct zone set 200
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # 테넌트 A: zone 100의 EST 세션 → 전용 flowtable
        meta mark 100 ct zone 100 ct state established \
            flow add @ft_tenant_a counter accept

        # 테넌트 B: zone 200의 EST 세션 → 전용 flowtable
        meta mark 200 ct zone 200 ct state established \
            flow add @ft_tenant_b counter accept

        # 새 세션: 테넌트별 DPI 큐 분리
        meta mark 100 ct zone 100 ct state new \
            queue num 0-3 fanout,bypass

        meta mark 200 ct zone 200 ct state new \
            queue num 4-7 fanout,bypass

        # RELATED 세션 허용
        ct state related accept
    }
}
코드 설명
  • 7-16행 테넌트별 독립 flowtable을 생성합니다. 각 flowtable은 자체 devices를 가지며 독립적으로 HW offload됩니다.
  • 23-24행 소스 IP 서브넷으로 테넌트를 분류하여 nfmark를 설정합니다. VLAN, 인터페이스, DSCP 등 다양한 기준 사용 가능합니다.
  • 32-33행 ct zone set으로 패킷의 conntrack zone을 설정합니다. 같은 5-tuple이라도 zone이 다르면 별도 conntrack 엔트리가 생성됩니다.
  • 40-41행 테넌트 A의 ESTABLISHED 세션을 전용 flowtable ft_tenant_a에 오프로드합니다. zone 100 내에서만 매칭됩니다.
  • 49-53행 새 세션을 테넌트별 NFQUEUE 범위에 분리하여 전달합니다. Suricata 인스턴스를 테넌트별로 분리 운영할 수 있습니다.

TC flower에서도 conntrack zone을 지정하여 HW 수준의 테넌트 격리를 구현할 수 있습니다:

# TC flower: 테넌트별 conntrack zone + HW offload

# 테넌트 A (VF0, zone 100): untracked → ct zone 100 시작
tc filter add dev enp4s0f0v0 ingress prio 1 \
  protocol ip flower \
  ct_state -trk \
  action ct zone 100

# 테넌트 A: EST → HW forward to uplink
tc filter add dev enp4s0f0v0 ingress prio 2 \
  protocol ip flower \
  ct_state +trk+est \
  ct_zone 100 \
  action ct zone 100 \
  action mirred egress redirect dev enp4s0f0

# 테넌트 B (VF1, zone 200): untracked → ct zone 200 시작
tc filter add dev enp4s0f0v1 ingress prio 1 \
  protocol ip flower \
  ct_state -trk \
  action ct zone 200

# 테넌트 B: EST → HW forward to uplink
tc filter add dev enp4s0f0v1 ingress prio 2 \
  protocol ip flower \
  ct_state +trk+est \
  ct_zone 200 \
  action ct zone 200 \
  action mirred egress redirect dev enp4s0f0

# 테넌트별 conntrack 상태 확인
conntrack -L --zone 100  # 테넌트 A 세션
conntrack -L --zone 200  # 테넌트 B 세션

VRF + eSwitch VF 기반 격리

VRF(Virtual Routing and Forwarding)는 L3 라우팅을 테넌트별로 완전 격리합니다. eSwitch의 VF representor와 결합하면 HW 수준의 라우팅 + 방화벽 격리가 가능합니다.

#!/bin/bash
# VRF + eSwitch VF 기반 멀티 테넌트 설정

# 1. VRF 생성 (테넌트별)
ip link add vrf-tenant-a type vrf table 100
ip link set vrf-tenant-a up
ip link add vrf-tenant-b type vrf table 200
ip link set vrf-tenant-b up

# 2. VF representor를 VRF에 바인딩
ip link set enp4s0f0v0 master vrf-tenant-a
ip link set enp4s0f0v1 master vrf-tenant-b

# 3. 업링크 서브인터페이스를 VRF에 바인딩
ip link add link enp4s0f0 name enp4s0f0.100 type vlan id 100
ip link set enp4s0f0.100 master vrf-tenant-a
ip addr add 10.100.0.1/24 dev enp4s0f0.100

ip link add link enp4s0f0 name enp4s0f0.200 type vlan id 200
ip link set enp4s0f0.200 master vrf-tenant-b
ip addr add 10.200.0.1/24 dev enp4s0f0.200

# 4. VRF별 라우팅 테이블
ip route add default via 10.100.0.254 table 100
ip route add default via 10.200.0.254 table 200

# 5. sysctl: VRF별 forwarding 활성화
sysctl -w net.ipv4.conf.all.forwarding=1
sysctl -w net.ipv4.conf.vrf-tenant-a.forwarding=1
sysctl -w net.ipv4.conf.vrf-tenant-b.forwarding=1
#!/usr/sbin/nft -f
# VRF 기반 테넌트별 nftables 방화벽 + flowtable

table inet vrf_ngfw {
    flowtable ft_a {
        hook ingress priority 0;
        devices = { enp4s0f0v0, enp4s0f0.100 };
        flags offload;
    }

    flowtable ft_b {
        hook ingress priority 0;
        devices = { enp4s0f0v1, enp4s0f0.200 };
        flags offload;
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # VRF 인터페이스로 테넌트 구분
        iifname "enp4s0f0v0" jump tenant_a_rules
        iifname "enp4s0f0v1" jump tenant_b_rules

        # 반환 트래픽
        oifname "enp4s0f0v0" ct state established,related accept
        oifname "enp4s0f0v1" ct state established,related accept
    }

    chain tenant_a_rules {
        # 테넌트 A 보안 정책
        ct state established flow add @ft_a counter accept
        ct state new tcp dport { 80, 443 } accept
        ct state new udp dport 53 accept
        counter drop
    }

    chain tenant_b_rules {
        # 테넌트 B 보안 정책 (더 제한적)
        ct state established flow add @ft_b counter accept
        ct state new tcp dport 443 accept
        counter drop
    }
}

Kubernetes 환경의 NGFW

Kubernetes에서는 CNI(Container Network Interface) 플러그인이 Pod 간 네트워킹을 관리합니다. NGFW 기능을 K8s 환경에 통합하려면 CNI의 데이터 플레인과 flowtable offload의 호환성을 고려해야 합니다.

CNI 플러그인데이터 플레인NetworkPolicyconntrack offloadflowtable 호환비고
CiliumeBPF (tc-bpf + XDP)L3/L4/L7 (자체 구현)eBPF CT map (자체)미지원 (자체 fast path)커널 conntrack 우회, 자체 CT + LB
Calico (eBPF)eBPF (tc-bpf)L3/L4eBPF CT (자체)미지원 (자체 구현)kube-proxy 대체, eBPF conntrack
Calico (iptables)iptables/nftablesL3/L4커널 conntrack가능 (nftables 모드)nftables 모드에서 flowtable 연동 가능
OVN-KubernetesOVS + GeneveL3/L4 (OVS ACL)OVS conntrackOVS-DPDK TC offloadSmartNIC OVS offload 시 HW 가속
AntreaOVSL3/L4/L7 (일부)OVS conntrackOVS HW offloadOVS bridge offload 활용
kube-routeriptables + IPVSL3/L4커널 conntrack가능 (수동 설정)flowtable 수동 구성 필요
Cilium + Host Firewall: Cilium의 Host Firewall 기능은 eBPF 기반으로 노드 수준의 방화벽을 제공합니다. 이는 커널 conntrack 대신 eBPF CT map을 사용하므로 nftables flowtable과 직접 연동되지 않습니다. 그러나 Cilium의 eBPF datapath 자체가 이미 Fast Path 역할을 수행하여, 별도의 flowtable 없이도 높은 처리 성능을 달성합니다. Pod-to-external 트래픽에 대해 호스트의 nftables flowtable을 추가로 활성화하면 이중 가속이 가능합니다.
멀티 테넌트 NGFW — conntrack zone + VRF + eSwitch 격리 SmartNIC eSwitch VF0 (Tenant A) VF1 (Tenant B) PF Uplink HW FDB Rules zone 100: VF0↔PF zone 200: VF1↔PF HW Flow Counters per-tenant 통계 Linux Kernel conntrack zone 100 Tenant A 세션 테이블 flowtable ft_a (HW offload) conntrack zone 200 Tenant B 세션 테이블 flowtable ft_b (HW offload) VRF table 100 Tenant A 라우팅 VRF table 200 Tenant B 라우팅 nftables (per-tenant chains) tenant_a_rules | tenant_b_rules 독립 ACL + DPI 큐 분리 NFQUEUE (DPI) Q0-3: Tenant A Q4-7: Tenant B Userspace (per-tenant) Suricata (Tenant A) NFQUEUE 0-3 시그니처 Set A 정책: Web + Email Suricata (Tenant B) NFQUEUE 4-7 시그니처 Set B 정책: HTTPS only 관리 플레인 (Multi-Tenant Manager) 테넌트 프로비저닝 | 정책 배포 | 로그 분리 conntrack zone 할당 | VRF 생성 | flowtable 관리 API: REST / gRPC / Netconf 모니터링 (per-tenant) HW counter → Prometheus exporter conntrack -L --zone N → 세션 통계 Suricata eve.json → 테넌트별 로그 분리

Hairpin/Loopback 오프로드와 East-West 트래픽 보안

전통적인 방화벽은 외부↔내부(North-South) 트래픽에 집중하지만, 현대 데이터센터에서는 전체 트래픽의 약 80%가 서버 간 East-West 통신입니다. Hairpin 오프로드는 동일 NIC에 연결된 VM/컨테이너 간 트래픽을 외부 스위치 없이 NIC 내부에서 전달하면서도 NGFW 수준의 보안 검사를 하드웨어에서 수행하는 기술입니다.

Hairpin 개념과 데이터센터 East-West 보안

Hairpin(헤어핀) 또는 Loopback(루프백)이란 패킷이 NIC으로 들어온 뒤 외부 스위치를 거치지 않고 같은 NIC 내부에서 방향을 바꿔(U-turn) 다른 가상 포트로 나가는 전달 방식입니다. 마치 머리핀처럼 들어온 경로에서 되돌아가는 형태이므로 이렇게 부릅니다.

East-West 트래픽 보안의 중요성

데이터센터 트래픽 패턴이 East-West 중심으로 전환된 배경과 보안 위협을 정리합니다.

항목North-SouthEast-West
방향외부 인터넷 ↔ 내부 서버내부 서버 ↔ 내부 서버
트래픽 비율약 20%약 80%
전통 방화벽 커버리지완전 커버대부분 미검사(blind spot)
대표 위협외부 침입, DDoS측면 이동(Lateral Movement), 내부자 공격
대응 전략경계 방화벽, IPS마이크로세그멘테이션(Microsegmentation)

측면 이동(Lateral Movement)은 공격자가 초기 침입(예: 피싱, 취약점 악용)으로 하나의 VM에 접근한 뒤, 같은 네트워크 세그먼트의 다른 VM으로 이동하며 공격 범위를 넓히는 기법입니다. 전통 경계 방화벽은 이미 내부에 있는 공격자의 횡방향 이동을 탐지하지 못합니다.

실제 사례: 대부분의 대규모 침해 사고(SolarWinds, Colonial Pipeline 등)에서 공격자는 초기 진입점 확보 후 수주~수개월간 내부 네트워크를 측면 이동하며 목표 시스템에 접근했습니다. East-West 트래픽에 대한 보안 검사가 없었기 때문에 탐지가 지연되었습니다.

마이크로세그멘테이션은 각 VM/컨테이너를 개별 보안 영역으로 분리하여, 같은 호스트 내 VM 간 통신에도 방화벽 정책을 적용하는 접근법입니다. 이를 하드웨어 수준에서 구현하려면 동일 NIC의 VF/SF 간 트래픽을 NIC 내부에서 검사하고 전달하는 Hairpin 오프로드가 필수적입니다.

Hairpin이 중요한 이유

TC flower Hairpin 규칙 구현

Hairpin 오프로드의 핵심은 TC flower의 mirred 리다이렉트 액션eSwitch FDB Hairpin 엔트리입니다. 동일 NIC의 두 representor 포트 간에 mirred egress redirect를 설정하면, eSwitch가 이를 인식하여 하드웨어 Hairpin 큐를 생성합니다.

기본 Hairpin 규칙 설정

VF0과 VF1이 같은 물리 NIC(enp1s0f0)에 속할 때, 두 VF의 representor 포트 간 트래픽을 하드웨어에서 직접 전달하는 규칙입니다.

# VF representor 포트 확인
# VF0_rep = enp1s0f0_0, VF1_rep = enp1s0f0_1
ip link show dev enp1s0f0_0
ip link show dev enp1s0f0_1

# eSwitch 모드를 switchdev로 설정 (이미 설정된 경우 생략)
devlink dev eswitch set pci/0000:01:00.0 mode switchdev

# VF0 → VF1 방향 Hairpin 규칙 (skip_sw: HW만 처리)
tc qdisc add dev enp1s0f0_0 ingress
tc filter add dev enp1s0f0_0 ingress protocol ip \
    flower skip_sw \
    src_mac aa:bb:cc:dd:ee:00 \
    dst_mac aa:bb:cc:dd:ee:01 \
    action mirred egress redirect dev enp1s0f0_1

# VF1 → VF0 방향 Hairpin 규칙 (양방향 필요)
tc qdisc add dev enp1s0f0_1 ingress
tc filter add dev enp1s0f0_1 ingress protocol ip \
    flower skip_sw \
    src_mac aa:bb:cc:dd:ee:01 \
    dst_mac aa:bb:cc:dd:ee:00 \
    action mirred egress redirect dev enp1s0f0_0

mlx5 Hairpin 큐 페어(Queue Pair) 내부 동작

Mellanox/NVIDIA ConnectX 시리즈에서 Hairpin은 하드웨어 레벨의 큐 페어(QP) 연결로 구현됩니다. 두 VF의 RQ(Receive Queue)와 SQ(Send Queue)를 NIC 내부에서 직접 연결하여, 패킷이 호스트 메모리를 거치지 않고 NIC ASIC 내에서 전달됩니다.

구성 요소설명
Hairpin RQ소스 VF의 수신 큐. 패킷을 호스트 메모리 대신 Hairpin SQ로 직접 전달
Hairpin SQ대상 VF의 송신 큐. Hairpin RQ에서 받은 패킷을 대상 VF로 전송
FDB Hairpin EntryeSwitch FDB(Forwarding Database)에 설치된 Hairpin 전달 규칙
Modify HeaderHairpin 경로에서 MAC/IP/Port 헤더 변경(NAT 등) 수행
# Hairpin 큐 생성 확인 (mlx5 디버그)
# /sys/kernel/debug/mlx5/ 에서 hairpin 관련 정보 확인
cat /sys/kernel/debug/mlx5/0000:01:00.0/hairpin_queues 2>/dev/null

# eSwitch FDB 엔트리 확인
tc -s filter show dev enp1s0f0_0 ingress
# 출력 예시:
#   filter protocol ip pref 49152 flower chain 0
#     in_hw in_hw_count 1           ← HW에 설치됨
#     action order 1: mirred (Egress Redirect to device enp1s0f0_1) pipe
#     Sent 1523456 bytes 10234 pkt  ← HW에서 처리된 통계

5-tuple 기반 Hairpin ACL

MAC 주소뿐 아니라 5-tuple(src_ip, dst_ip, src_port, dst_port, protocol)로 세밀하게 Hairpin 정책을 적용할 수 있습니다.

# 특정 서비스 포트만 Hairpin 허용 (예: VM0 → VM1의 TCP/443)
tc filter add dev enp1s0f0_0 ingress protocol ip \
    flower skip_sw \
    ip_proto tcp \
    src_ip 10.0.0.10 dst_ip 10.0.0.11 \
    dst_port 443 \
    action mirred egress redirect dev enp1s0f0_1

# 나머지 트래픽은 차단 (implicit deny)
tc filter add dev enp1s0f0_0 ingress protocol ip \
    prio 99 flower skip_sw \
    action drop

Hairpin + conntrack 오프로드 조합

Hairpin 전달에 conntrack(CT) 오프로드를 결합하면, NIC 하드웨어 내부에서 스테이트풀 방화벽 + NAT + ACL을 모두 처리하는 완전한 East-West NGFW 파이프라인을 구현할 수 있습니다.

TC flower chain 기반 Hairpin + CT 파이프라인

TC flower의 chain 기능을 활용하여 Hairpin 경로에 다단계 보안 파이프라인을 구성합니다. chain 0에서 CT 액션을 호출하고, chain 1에서 CT 상태에 따라 전달/차단을 결정합니다.

# === Hairpin + CT + NAT 완전 오프로드 파이프라인 ===

# 1단계: chain 0 — conntrack zone 1에 패킷 등록
tc filter add dev enp1s0f0_0 ingress protocol ip \
    chain 0 flower skip_sw \
    ip_proto tcp \
    ct_state -trk \
    action ct zone 1 nat pipe \
    action goto chain 1

# 2단계: chain 1 — ESTABLISHED 상태 확인 후 Hairpin 전달
tc filter add dev enp1s0f0_0 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+est \
    action mirred egress redirect dev enp1s0f0_1

# 2-1단계: chain 1 — 새 연결(NEW)이면 특정 포트만 허용
tc filter add dev enp1s0f0_0 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+new \
    ip_proto tcp dst_port 443 \
    action ct commit zone 1 \
    action mirred egress redirect dev enp1s0f0_1

# 2-2단계: chain 1 — 허용되지 않은 새 연결은 차단
tc filter add dev enp1s0f0_0 ingress protocol ip \
    chain 1 prio 99 flower skip_sw \
    ct_state +trk+new \
    action drop

# 역방향 규칙 (VF1 → VF0)
tc filter add dev enp1s0f0_1 ingress protocol ip \
    chain 0 flower skip_sw \
    ip_proto tcp \
    ct_state -trk \
    action ct zone 1 nat pipe \
    action goto chain 1

tc filter add dev enp1s0f0_1 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+est \
    action mirred egress redirect dev enp1s0f0_0

Hairpin + NAT 오프로드

East-West 트래픽에도 NAT가 필요한 경우(예: 서비스 VIP → 실제 VM IP 변환)가 있습니다. CT 액션에 NAT 파라미터를 추가하면 하드웨어에서 NAT 변환까지 처리합니다.

# DNAT: VIP 10.0.0.100:443 → VM1 실제 IP 10.0.0.11:8443
tc filter add dev enp1s0f0_0 ingress protocol ip \
    chain 0 flower skip_sw \
    ip_proto tcp \
    dst_ip 10.0.0.100 dst_port 443 \
    ct_state -trk \
    action ct zone 1 nat commit \
        ct_mark 0x1 \
        nat dst addr 10.0.0.11 port 8443 pipe \
    action goto chain 1

tc filter add dev enp1s0f0_0 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+est ct_mark 0x1 \
    action mirred egress redirect dev enp1s0f0_1

성능 비교: Hairpin HW vs Software Bridge vs 외부 스위치

전달 경로레이턴시처리량(64B)CPU 사용률보안 검사
Hairpin HW (eSwitch)~50 ns최대 200 Gbps0%CT + NAT + ACL (HW)
Linux Bridge (SW)~5 μs~20 Gbps40~60%iptables/nftables (SW)
OVS DPDK~2 μs~40 Gbps100% (전용 코어)OVS flow rules (SW)
외부 스위치 루프~10 μs스위치 포트 속도0% (호스트)스위치 ACL만
성능 팁: Hairpin HW 오프로드는 패킷이 호스트 메모리에 전혀 도달하지 않으므로, PCIe 대역폭과 호스트 CPU를 완전히 절약합니다. 200 Gbps SmartNIC에서 East-West 트래픽 100 Gbps를 Hairpin으로 처리하면, 나머지 PCIe 대역폭은 North-South 트래픽 전용으로 활용할 수 있습니다.

Scalable Function(SF)과 마이크로세그멘테이션

Scalable Function(SF, 확장 가능 함수)은 NVIDIA ConnectX-6 Dx 이상에서 도입된 경량 서브 함수(Sub-function)입니다. VF(Virtual Function)보다 더 유연하게 생성·삭제할 수 있으며, 각 SF에 전용 representor 포트가 할당되어 개별 보안 정책을 적용할 수 있습니다.

SF vs VF 비교

항목VF (Virtual Function)SF (Scalable Function)
생성 방식sriov_numvfs (재부팅 필요 가능)devlink sf create (동적, 무중단)
최대 개수PCIe 제한 (보통 128~256개)수천 개 (ASIC 제한까지)
리소스 격리PCI 기능 단위NIC 내부 논리 분리
RepresentorVF당 1개SF당 1개
동적 생성/삭제제한적완전 동적 (Kubernetes 연동 적합)
eSwitch Hairpin지원지원
적합 환경고정 VM 환경Kubernetes Pod, 동적 워크로드

SF 생성 및 보안 정책 적용

# === SF 생성 (devlink) ===

# 1. SF 포트 생성
devlink port add pci/0000:01:00.0 flavour pcisf pfnum 0 sfnum 10
# 출력: pci/0000:01:00.0/32768: ... flavour pcisf ...

# 2. SF 활성화
devlink port function set pci/0000:01:00.0/32768 \
    hw_addr 00:11:22:33:44:10 state active

# 3. SF 디바이스 확인 (representor 자동 생성)
devlink port show pci/0000:01:00.0/32768
# representor: en3f0pf0sf10

# 4. 추가 SF 생성 (Pod별 1개)
devlink port add pci/0000:01:00.0 flavour pcisf pfnum 0 sfnum 11
devlink port function set pci/0000:01:00.0/32769 \
    hw_addr 00:11:22:33:44:11 state active
# representor: en3f0pf0sf11
# === SF 간 마이크로세그멘테이션 정책 ===

# SF10(웹서버 Pod) → SF11(DB Pod): TCP/5432만 허용
tc qdisc add dev en3f0pf0sf10 ingress
tc filter add dev en3f0pf0sf10 ingress protocol ip \
    chain 0 flower skip_sw \
    ip_proto tcp ct_state -trk \
    action ct zone 100 pipe \
    action goto chain 1

tc filter add dev en3f0pf0sf10 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+est \
    action mirred egress redirect dev en3f0pf0sf11

tc filter add dev en3f0pf0sf10 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+new \
    ip_proto tcp dst_port 5432 \
    action ct commit zone 100 \
    action mirred egress redirect dev en3f0pf0sf11

# 그 외 모든 트래픽 차단 (Zero Trust)
tc filter add dev en3f0pf0sf10 ingress protocol ip \
    chain 1 prio 99 flower skip_sw \
    action drop

# 역방향: SF11 → SF10 (TCP 응답 트래픽만 허용)
tc qdisc add dev en3f0pf0sf11 ingress
tc filter add dev en3f0pf0sf11 ingress protocol ip \
    chain 0 flower skip_sw \
    ip_proto tcp ct_state -trk \
    action ct zone 100 pipe \
    action goto chain 1

tc filter add dev en3f0pf0sf11 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+est \
    action mirred egress redirect dev en3f0pf0sf10

Kubernetes CNI 연동

Kubernetes 통합: NVIDIA Network Operator와 SR-IOV CNI 플러그인(Plugin)은 Pod 생성 시 자동으로 SF를 할당하고, Pod 삭제 시 SF를 회수합니다. 각 SF의 representor에 TC flower 규칙을 적용하면, Pod 단위의 하드웨어 기반 마이크로세그멘테이션이 구현됩니다. Cilium, Calico 등의 CNI와도 연동이 가능합니다.
# Kubernetes NetworkPolicy 예시 (Cilium + SmartNIC offload)
# 이 정책은 Cilium이 TC flower 규칙으로 변환하여 SF representor에 설치합니다

# Pod의 SF representor에 설치된 TC 규칙 확인
kubectl exec -n kube-system cilium-xxxx -- \
    tc -s filter show dev lxc_pod_web ingress

# SF 상태 모니터링
devlink port show | grep "pcisf"
devlink port function show pci/0000:01:00.0/32768

Hairpin 오프로드 아키텍처 다이어그램

아래 다이어그램은 동일 SmartNIC 내에서 Hairpin 오프로드를 통해 VM 간 트래픽을 하드웨어에서 보안 검사하고 전달하는 구조와, 비교를 위한 외부 스위치 경유 경로를 보여줍니다.

Hairpin 오프로드: NIC 내부 East-West 보안 파이프라인 호스트 서버 VM1 (웹서버) VF0 / SF10 VM2 (DB서버) VF1 / SF11 VF0_rep VF1_rep SmartNIC eSwitch (Hairpin 오프로드) CT Zone 1 conntrack NAT Rewrite DNAT/SNAT ACL Check 5-tuple 필터 FDB Hairpin HW Queue Pair 패킷 IN 패킷 OUT (Hairpin) Hairpin Fast Path: ~50 ns, CPU 사용률 0% DROP (정책 거부) 외부 스위치 경유 (비교) NIC TX → 물리 포트 ToR 스위치 (ACL만) NIC RX ← 물리 포트 외부 경유: ~10 μs 스위치 포트 대역폭 소비 CT/NAT 불가 (스위치 한계) Hairpin HW Fast Path 외부 스위치 경유 / DROP VM ↔ Representor 연결 동일 NIC 내 VM 간 트래픽을 eSwitch에서 CT+NAT+ACL 처리 후 Hairpin 전달
Hairpin 제한사항: Hairpin 오프로드는 같은 물리 NIC에 속한 VF/SF 간에서만 동작합니다. 서로 다른 NIC이나 서로 다른 호스트의 VM 간 트래픽은 일반적인 eSwitch 오프로드나 외부 스위치를 통해 전달해야 합니다. 또한 NIC 모델에 따라 Hairpin Queue Pair 개수에 하드웨어 제한이 있을 수 있습니다.

eBPF 기반 차세대 NGFW

eBPF(extended Berkeley Packet Filter)는 커널 내에서 안전하게 실행되는 프로그램을 통해 네트워크 패킷 처리를 프로그래밍할 수 있는 기술입니다. 전통적인 nftables/iptables 기반 방화벽을 넘어, eBPF는 더 유연하고 고성능인 NGFW 파이프라인을 구현할 수 있게 합니다.

eBPF NGFW의 장점과 한계

특성iptablesnftableseBPF (tc-bpf/XDP)BPF netfilter (6.4+)
성능 (패킷/초)낮음 (순차 체인)중간 (집합 기반)높음 (JIT 컴파일)높음 (JIT + 훅 직결)
유연성고정 매칭 (모듈 확장)표현식 기반 (유연)최고 (C 프로그램)높음 (BPF 프로그램)
HW offload미지원flowtable (TC flower)XDP HW offload (제한적)미지원 (SW only)
conntrack 연동nf_conntrack 직접nf_conntrack 직접자체 CT map 또는 kfuncnf_conntrack kfunc
flowtable 연동불가flow add @ft불가 (자체 fast path)가능 (kfunc)
동적 업데이트전체 체인 교체규칙 단위 추가/삭제맵 업데이트 (무중단)맵 업데이트 (무중단)
디버깅LOG 타겟log 액션bpftrace, bpf_printkbpftrace, bpf_printk
학습 곡선낮음중간높음 (C + BPF 지식)높음
안정성매우 높음 (수십 년)높음중간 (verifier 의존)아직 초기
eBPF vs nftables 선택 기준: 일반적인 L3/L4 방화벽 + flowtable offload가 목적이라면 nftables가 적합합니다. 커스텀 프로토콜 파싱, 머신러닝 기반 탐지, 복잡한 상태 머신이 필요하거나 Kubernetes 환경에서 수만 개의 Pod 정책을 관리해야 한다면 eBPF가 유리합니다. 실무에서는 nftables(기본 방화벽) + eBPF(XDP DDoS 필터, 커스텀 DPI)를 조합하는 하이브리드 접근이 가장 효과적입니다.

BPF netfilter 프로그램 (커널 6.4+)

Linux 커널 6.4에서 도입된 BPF_PROG_TYPE_NETFILTER는 Netfilter 훅 포인트에 BPF 프로그램을 직접 연결할 수 있게 합니다. 이를 통해 nftables 규칙 대신 BPF 프로그램으로 방화벽 로직을 구현할 수 있습니다.

/* BPF netfilter 프로그램 예시 — 세션 추적 + 오프로드 결정 */
/* 커널 6.4+ 필요, libbpf 사용 */

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <linux/netfilter.h>

/* conntrack kfunc 선언 (커널 6.4+) */
extern struct nf_conn *
bpf_xdp_ct_lookup(struct xdp_md *ctx,
                  struct bpf_sock_tuple *tuple, u32 len,
                  struct bpf_ct_opts *opts, u32 opts_len) __ksym;
extern void
bpf_ct_release(struct nf_conn *ct) __ksym;

/* 세션별 DPI 결과를 저장하는 BPF 맵 */
struct {
    __uint(type, BPF_MAP_TYPE_LRU_HASH);
    __uint(max_entries, 1000000);
    __type(key, struct flow_key);    /* 5-tuple */
    __type(value, struct flow_info);  /* DPI 결과 + 상태 */
} flow_map SEC(".maps");

/* DPI 완료 + ALLOW된 세션을 기록하는 맵 */
struct {
    __uint(type, BPF_MAP_TYPE_LRU_HASH);
    __uint(max_entries, 500000);
    __type(key, struct flow_key);
    __type(value, __u64);  /* 오프로드 타임스탬프 */
} offload_map SEC(".maps");

/* 통계 카운터 */
struct {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __uint(max_entries, 4);  /* 0:pass, 1:drop, 2:offload, 3:dpi */
    __type(key, __u32);
    __type(value, __u64);
} stats SEC(".maps");

struct flow_key {
    __be32 saddr;
    __be32 daddr;
    __be16 sport;
    __be16 dport;
    __u8   proto;
};

struct flow_info {
    __u32 app_id;        /* DPI 분류 결과 */
    __u32 verdict;       /* 0=pending, 1=allow, 2=deny */
    __u64 pkt_count;     /* 패킷 수 */
    __u64 byte_count;    /* 바이트 수 */
    __u64 last_seen;     /* 마지막 패킷 타임스탬프 */
};

SEC("netfilter")
int ngfw_filter(struct bpf_nf_ctx *ctx)
{
    struct sk_buff *skb = ctx->skb;
    struct flow_key key = {};
    struct flow_info *info;
    __u32 stat_key;

    /* 5-tuple 추출 */
    if (extract_flow_key(skb, &key) < 0)
        return NF_ACCEPT;

    /* flow_map에서 기존 세션 조회 */
    info = bpf_map_lookup_elem(&flow_map, &key);

    if (!info) {
        /* 새 세션: flow_map에 등록하고 DPI로 전달 */
        struct flow_info new_info = {
            .verdict = 0,  /* pending */
            .pkt_count = 1,
        };
        bpf_map_update_elem(&flow_map, &key, &new_info, BPF_ANY);
        stat_key = 3;  /* DPI로 전달 */
        update_stats(&stats, stat_key);
        return NF_ACCEPT;  /* Slow Path로 진행 */
    }

    /* DPI 결과에 따른 처리 */
    switch (info->verdict) {
    case 1:  /* ALLOW */
        info->pkt_count++;
        info->byte_count += skb->len;
        info->last_seen = bpf_ktime_get_ns();

        /* 10패킷 이상이면 오프로드 대상으로 마킹 */
        if (info->pkt_count > 10 &&
            !bpf_map_lookup_elem(&offload_map, &key)) {
            __u64 ts = bpf_ktime_get_ns();
            bpf_map_update_elem(&offload_map, &key, &ts, BPF_ANY);
            stat_key = 2;
            update_stats(&stats, stat_key);
        }

        stat_key = 0;
        update_stats(&stats, stat_key);
        return NF_ACCEPT;

    case 2:  /* DENY */
        stat_key = 1;
        update_stats(&stats, stat_key);
        return NF_DROP;

    default:  /* PENDING — 아직 DPI 진행 중 */
        info->pkt_count++;
        return NF_ACCEPT;
    }
}

char _license[] SEC("license") = "GPL";
코드 설명
  • 8-14행 커널 6.4+의 kfunc(kernel function) 인터페이스로 BPF 프로그램에서 커널 conntrack을 직접 조회할 수 있습니다. __ksym은 커널 심볼(Kernel Symbol) 참조를 나타냅니다.
  • 17-22행 BPF_MAP_TYPE_LRU_HASH는 100만 엔트리의 세션 테이블입니다. LRU 정책으로 가득 차면 가장 오래된 엔트리가 자동 제거됩니다.
  • 55행 SEC("netfilter")는 이 프로그램이 Netfilter 훅에 연결되는 BPF_PROG_TYPE_NETFILTER 타입임을 선언합니다.
  • 69-77행 새 세션을 flow_map에 등록하고 NF_ACCEPT를 반환하여 이후 nftables NFQUEUE → DPI 경로로 진행하게 합니다.
  • 84-91행 DPI가 ALLOW 판정을 내린 세션에서 10패킷 이상 처리되면 offload_map에 등록합니다. 유저스페이스 관리 데몬이 이 맵을 폴링(Polling)하여 실제 flowtable 오프로드를 수행합니다.

Cilium의 eBPF 방화벽 아키텍처

Cilium은 Kubernetes 환경에서 가장 널리 사용되는 eBPF 기반 CNI + 방화벽 솔루션입니다. 커널의 nf_conntrack과 nftables를 사용하지 않고, eBPF 맵으로 자체 conntrack과 정책 엔진(Policy Engine)을 구현합니다.

구성요소구현 방식BPF 맵 타입역할
CT map (conntrack)BPF_MAP_TYPE_LRU_HASHper-CPU LRU hash세션 추적, 상태 관리, NAT 매핑
Policy mapBPF_MAP_TYPE_HASHidentity → policy 매핑K8s NetworkPolicy 평가
NAT mapBPF_MAP_TYPE_LRU_HASH원본 → 변환 IP/portClusterIP, NodePort DNAT
Endpoints mapBPF_MAP_TYPE_HASHIP → endpoint identityPod 식별, 보안 ID 할당
Metrics mapBPF_MAP_TYPE_PERCPU_HASHreason → counterdrop/forward 사유별 통계
Events mapBPF_MAP_TYPE_PERF_EVENT_ARRAYring bufferHubble 이벤트 전달 (모니터링)

Cilium의 데이터 플레인 파이프라인은 다음과 같은 순서로 실행됩니다:

/* Cilium CT map 구조 (간소화) */
/* bpf/lib/conntrack.h 참고 */

struct ct_entry {
    __u64 rx_packets;        /* 수신 패킷 수 */
    __u64 rx_bytes;          /* 수신 바이트 */
    __u64 tx_packets;        /* 송신 패킷 수 */
    __u64 tx_bytes;          /* 송신 바이트 */
    __u32 lifetime;          /* 남은 수명 (초) */
    __u16 rx_closing:1;      /* FIN 수신 */
    __u16 tx_closing:1;      /* FIN 송신 */
    __u16 nat46:1;           /* NAT46 변환 */
    __u16 lb_loopback:1;     /* LB 루프백 */
    __u16 seen_non_syn:1;    /* SYN 이후 패킷 확인 */
    __u16 node_port:1;       /* NodePort 플래그 */
    __u8  rev_nat_index;     /* 역NAT 인덱스 */
    __u8  slave;             /* LB backend 슬롯 */
    __u16 ifindex;           /* 출력 인터페이스 */
    __u32 src_sec_id;        /* 소스 보안 identity */
};

/* CT GC (Garbage Collection) — 유저스페이스 에이전트 */
/* cilium-agent가 주기적으로 CT map을 순회하며 만료 엔트리 삭제 */
/* GC 주기: 기본 12초, conntrack-gc-interval 옵션으로 조절 */
/* GC 전략: */
/*   1. lifetime이 0인 엔트리 삭제 */
/*   2. TCP FIN/RST 후 grace period 만료 엔트리 삭제 */
/*   3. NAT map의 orphan 엔트리 정리 */
Cilium의 bpf_redirect_peer(): 이 BPF 헬퍼 함수는 veth 피어를 통해 패킷을 직접 전달하여 호스트 측 네트워크 스택의 ingress 경로를 완전히 우회합니다. 이는 nftables flowtable의 NF_STOLEN 반환과 유사한 효과를 제공하며, Pod-to-Pod 트래픽에서 ~30% 성능 향상을 달성합니다. 커널 5.10+에서 사용 가능합니다.

tc-bpf vs XDP vs BPF netfilter 비교

eBPF 기반 NGFW를 구현할 때 사용할 수 있는 3가지 BPF 프로그램 타입의 특성을 비교합니다:

특성XDP (eXpress Data Path)tc-bpf (Traffic Control)BPF netfilter (6.4+)
실행 시점NIC 드라이버 직후 (skb 생성 전)TC ingress/egress (skb 존재)Netfilter 훅 (conntrack 후)
성능최고 (~100Mpps)높음 (~40Mpps)nftables와 유사 (~20Mpps)
skb 접근제한적 (xdp_md만)전체 skb 접근전체 skb + nf_hook_state
conntrack 접근kfunc (6.4+)kfunc (6.4+)자동 (훅 위치에 따라)
NAT수동 rewrite수동 rewritenf_nat 통합 가능
redirectbpf_redirect(), bpf_redirect_map()bpf_redirect(), bpf_redirect_peer()NF_ACCEPT/DROP만
HW offload제한적 (Netronome 등)미지원미지원
NGFW 역할DDoS pre-filter, rate limitL3/L4 정책, CT, LB, redirectNetfilter 훅 대체, DPI 연동
대표 프로젝트Cloudflare Magic TransitCilium, Calico eBPF아직 초기 (실험적)

각 BPF 타입의 NGFW에서의 역할을 종합하면:

eBPF NGFW 파이프라인 (XDP → tc-bpf → BPF CT → Policy → Redirect) NIC RX 패킷 수신 XDP DDoS Pre-filter Rate Limiter XDP_DROP tc-bpf ingress 정책 identity lookup BPF CT map 세션 조회/생성 LRU Hash Policy map ALLOW/DENY identity 기반 NAT/LB DNAT rewrite backend 선택 TX redirect TC_ACT_SHOT BPF Maps (커널 메모리) XDP Blocklist LPM_TRIE: IP 차단 Rate: per-src 제한 CT map LRU_HASH: 1M entries 5-tuple → ct_entry Policy map HASH: identity 기반 src_id+dst_id → allow/deny NAT map LRU_HASH: DNAT 매핑 ClusterIP → PodIP Events/Metrics PERF_EVENT: Hubble PERCPU: 드롭 통계 Userspace Agent 맵 업데이트 (정책 변경) CT GC (만료 엔트리 정리) 이벤트 소비 (모니터링) cilium-agent | bpftool | prometheus-exporter

P4 프로그래머블 파이프라인 NGFW 오프로드

TC flower와 eSwitch 오프로드는 고정 함수(Fixed-Function) 파이프라인에서 미리 정의된 매치/액션을 수행합니다. 반면 P4(Programming Protocol-independent Packet Processors)는 NIC/스위치의 패킷 처리 파이프라인 자체를 프로그래밍할 수 있게 하여, 커스텀 프로토콜 파싱, 임의의 매치-액션 테이블, 스테이트풀 레지스터를 라인 레이트에서 실행합니다. 이 절에서는 P4 프로그래머블 파이프라인으로 NGFW 기능을 구현하는 방법을 살펴봅니다.

P4 파이프라인 개요와 NGFW 적용

P416은 패킷 처리 파이프라인을 정의하는 도메인 특화 언어(DSL)입니다. 네트워크 하드웨어의 데이터 플레인 동작을 소프트웨어처럼 프로그래밍하되, 컴파일 결과가 ASIC/FPGA에 직접 매핑되어 라인 레이트 처리를 보장합니다.

P4 파이프라인 핵심 구성 요소

구성 요소역할NGFW 적용
프로그래머블 파서(Parser)패킷 헤더를 바이트 단위로 추출, 상태 머신 기반 프로토콜 탐색커스텀 프로토콜(GTP, VXLAN-GPE, SRv6 등) 파싱, DPI 전처리
매치-액션 테이블(MAT)추출된 필드를 키로 테이블 조회, 매치 시 액션 실행5-tuple ACL, 커스텀 헤더 기반 필터링, 동적 블랙리스트
매치 타입exact(정확), ternary(와일드카드), LPM(최장 프리픽스), rangeexact: conntrack lookup, ternary: ACL, LPM: 라우팅
레지스터(Register)스테이트풀 메모리, 패킷 간 상태 유지커넥션 트래킹 상태 머신 (SYN→ESTABLISHED→FIN)
카운터/미터(Counter/Meter)패킷/바이트 카운트, 토큰 버킷 기반 속도 제한플로우별 통계, QoS 속도 제한
다이제스트(Digest)패킷 메타데이터를 CPU(컨트롤 플레인)로 전송새 플로우 알림, 이상 탐지 이벤트 전달
디파서(Deparser)수정된 헤더를 다시 조합하여 패킷 재구성NAT 변환 후 헤더 재조합, 터널 캡슐화

P4가 NGFW에 중요한 이유

P4 vs 고정 함수: TC flower + eSwitch 오프로드는 NIC 벤더가 하드웨어에 구현한 고정 매치-액션 기능만 사용할 수 있습니다. P4 프로그래머블 디바이스는 사용자가 파서와 테이블을 직접 정의하므로, 새로운 프로토콜이나 보안 정책을 하드웨어에 즉시 적용할 수 있습니다. 다만 P4 지원 하드웨어는 고정 함수 NIC보다 고가이며, 개발 복잡도가 높습니다.

P4 NGFW 5-tuple ACL + Stateful 방화벽 구현

P416으로 5-tuple ACL과 스테이트풀 커넥션 트래킹을 구현하는 코드를 살펴봅니다. 이 코드는 P416 표준 아키텍처(V1Model)를 기준으로 하며, 실제 ASIC에 배포할 때는 플랫폼별 아키텍처(TNA, PNA 등)로 포팅(Porting)합니다.

헤더 정의

/* P4_16 NGFW 헤더 정의 */
header ethernet_t {
    bit<48> dst_addr;
    bit<48> src_addr;
    bit<16> ether_type;
}

header ipv4_t {
    bit<4>  version;
    bit<4>  ihl;
    bit<8>  dscp_ecn;
    bit<16> total_len;
    bit<16> identification;
    bit<3>  flags;
    bit<13> frag_offset;
    bit<8>  ttl;
    bit<8>  protocol;
    bit<16> hdr_checksum;
    bit<32> src_addr;
    bit<32> dst_addr;
}

header tcp_t {
    bit<16> src_port;
    bit<16> dst_port;
    bit<32> seq_no;
    bit<32> ack_no;
    bit<4>  data_offset;
    bit<3>  res;
    bit<9>  flags;       /* NS,CWR,ECE,URG,ACK,PSH,RST,SYN,FIN */
    bit<16> window;
    bit<16> checksum;
    bit<16> urgent_ptr;
}

header udp_t {
    bit<16> src_port;
    bit<16> dst_port;
    bit<16> length;
    bit<16> checksum;
}

struct headers_t {
    ethernet_t ethernet;
    ipv4_t     ipv4;
    tcp_t      tcp;
    udp_t      udp;
}

struct metadata_t {
    bit<2>  ct_state;    /* 0=NEW, 1=ESTABLISHED, 2=RELATED, 3=INVALID */
    bit<1>  acl_permit;
    bit<32> flow_hash;
    bit<8>  meter_color; /* 0=GREEN, 1=YELLOW, 2=RED */
}

프로그래머블 파서

/* P4_16 프로그래머블 파서 */
parser NgfwParser(packet_in pkt,
                  out headers_t hdr,
                  inout metadata_t meta,
                  inout standard_metadata_t std_meta) {

    state start {
        pkt.extract(hdr.ethernet);
        transition select(hdr.ethernet.ether_type) {
            0x0800: parse_ipv4;
            default: accept;
        }
    }

    state parse_ipv4 {
        pkt.extract(hdr.ipv4);
        transition select(hdr.ipv4.protocol) {
            6:  parse_tcp;
            17: parse_udp;
            default: accept;
        }
    }

    state parse_tcp {
        pkt.extract(hdr.tcp);
        transition accept;
    }

    state parse_udp {
        pkt.extract(hdr.udp);
        transition accept;
    }
}

5-tuple ACL 테이블 + 스테이트풀 방화벽

/* 커넥션 트래킹 상태 상수 */
const bit<2> CT_NEW         = 0;
const bit<2> CT_ESTABLISHED = 1;
const bit<2> CT_RELATED     = 2;
const bit<2> CT_INVALID     = 3;

/* TCP 플래그 비트 위치 */
const bit<9> TCP_SYN = 0x002;
const bit<9> TCP_ACK = 0x010;
const bit<9> TCP_FIN = 0x001;
const bit<9> TCP_RST = 0x004;

control NgfwIngress(inout headers_t hdr,
                    inout metadata_t meta,
                    inout standard_metadata_t std_meta) {

    /* --- 레지스터: 커넥션 상태 테이블 (해시 기반) --- */
    register<bit<2>>(65536)  ct_state_reg;    /* 상태: NEW/EST/REL/INV */
    register<bit<32>>(65536) ct_timeout_reg;   /* 타임스탬프 기반 만료 */

    /* --- 카운터 --- */
    direct_counter(CounterType.packets_and_bytes) acl_counter;

    /* --- 미터: 플로우별 속도 제한 --- */
    meter(1024, MeterType.bytes) flow_meter;

    /* --- 5-tuple ACL 테이블 (ternary 매치) --- */
    action permit() {
        meta.acl_permit = 1;
    }

    action deny() {
        meta.acl_permit = 0;
        mark_to_drop(std_meta);
    }

    action permit_and_meter(bit<32> meter_idx) {
        meta.acl_permit = 1;
        flow_meter.execute_meter(meter_idx, meta.meter_color);
    }

    table acl_table {
        key = {
            hdr.ipv4.src_addr  : ternary;
            hdr.ipv4.dst_addr  : ternary;
            hdr.ipv4.protocol  : ternary;
            hdr.tcp.src_port   : ternary;  /* TCP/UDP 공용 */
            hdr.tcp.dst_port   : ternary;
        }
        actions = {
            permit;
            deny;
            permit_and_meter;
        }
        size = 16384;
        default_action = deny();
        counters = acl_counter;
    }

    /* --- 커넥션 트래킹 로직 --- */
    action compute_flow_hash() {
        hash(meta.flow_hash, HashAlgorithm.crc32,
             (bit<32>)0,
             { hdr.ipv4.src_addr, hdr.ipv4.dst_addr,
               hdr.ipv4.protocol, hdr.tcp.src_port, hdr.tcp.dst_port },
             (bit<32>)65535);
    }

    action ct_lookup() {
        bit<2> state;
        ct_state_reg.read(state, meta.flow_hash);
        meta.ct_state = state;
    }

    action ct_update_established() {
        ct_state_reg.write(meta.flow_hash, CT_ESTABLISHED);
        ct_timeout_reg.write(meta.flow_hash,
            (bit<32>)std_meta.ingress_global_timestamp);
    }

    action ct_create_new() {
        ct_state_reg.write(meta.flow_hash, CT_NEW);
        ct_timeout_reg.write(meta.flow_hash,
            (bit<32>)std_meta.ingress_global_timestamp);
    }

    /* --- 새 플로우 CPU 알림 (Digest) --- */
    action send_digest_to_cpu() {
        digest<headers_t>(1, { hdr.ethernet, hdr.ipv4, hdr.tcp, hdr.udp });
    }

    apply {
        if (!hdr.ipv4.isValid()) {
            return;
        }

        /* 1단계: 플로우 해시 계산 */
        compute_flow_hash();

        /* 2단계: CT 상태 조회 */
        ct_lookup();

        /* 3단계: TCP 상태 머신 */
        if (hdr.tcp.isValid()) {
            if (meta.ct_state == CT_NEW &&
                (hdr.tcp.flags & TCP_ACK) != 0) {
                /* SYN-ACK 응답 → ESTABLISHED */
                ct_update_established();
                meta.ct_state = CT_ESTABLISHED;
            } else if (meta.ct_state == CT_NEW &&
                       (hdr.tcp.flags & TCP_SYN) != 0) {
                /* SYN 패킷 → 새 플로우 등록, CPU 알림 */
                ct_create_new();
                send_digest_to_cpu();
            } else if ((hdr.tcp.flags & TCP_RST) != 0 ||
                       (hdr.tcp.flags & TCP_FIN) != 0) {
                /* RST/FIN → 상태 초기화 */
                ct_state_reg.write(meta.flow_hash, CT_NEW);
            }
        }

        /* 4단계: ESTABLISHED 세션은 ACL 건너뛰기 (Fast Path) */
        if (meta.ct_state == CT_ESTABLISHED) {
            meta.acl_permit = 1;
        } else {
            /* 5단계: 5-tuple ACL 테이블 조회 */
            acl_table.apply();
        }

        /* 6단계: 속도 제한 확인 */
        if (meta.meter_color == 2) { /* RED → 드롭 */
            mark_to_drop(std_meta);
            return;
        }

        /* 7단계: 허용/차단 */
        if (meta.acl_permit == 0) {
            mark_to_drop(std_meta);
        }
    }
}
실전 팁: 위 코드의 CT 구현은 레지스터 해시 충돌 문제가 있으므로, 프로덕션(Production) 환경에서는 d-left 해싱(d-left hashing) 또는 Cuckoo 해시 테이블을 P4 레지스터로 구현하여 충돌을 최소화합니다. Tofino는 최대 4개의 해시 함수를 병렬 실행할 수 있어 d-left 해싱에 적합합니다.

NAT 리라이트 테이블

/* NAT 변환 테이블 */
action do_dnat(bit<32> new_dst_addr, bit<16> new_dst_port) {
    hdr.ipv4.dst_addr = new_dst_addr;
    hdr.tcp.dst_port  = new_dst_port;
    /* 체크섬은 디파서에서 재계산 */
}

action do_snat(bit<32> new_src_addr, bit<16> new_src_port) {
    hdr.ipv4.src_addr = new_src_addr;
    hdr.tcp.src_port  = new_src_port;
}

table nat_table {
    key = {
        hdr.ipv4.dst_addr : exact;
        hdr.tcp.dst_port  : exact;
    }
    actions = {
        do_dnat;
        do_snat;
        NoAction;
    }
    size = 8192;
    default_action = NoAction();
}

/* 디파서: 수정된 헤더 재조합 */
control NgfwDeparser(packet_out pkt, in headers_t hdr) {
    apply {
        pkt.emit(hdr.ethernet);
        pkt.emit(hdr.ipv4);
        pkt.emit(hdr.tcp);
        pkt.emit(hdr.udp);
    }
}

플랫폼별 P4 NGFW 구현

P4 프로그램은 타깃 플랫폼의 아키텍처 모델에 맞게 컴파일됩니다. 각 플랫폼은 고유한 하드웨어 구조를 가지며, P4 NGFW 구현 시 플랫폼별 특성을 활용해야 최적 성능을 달성합니다.

(a) Intel Tofino

Tofino는 Intel(구 Barefoot Networks)의 P4 네이티브 ASIC으로, 데이터센터 스위치용으로 설계되었습니다.

항목Tofino 1Tofino 2
처리량6.5 Tbps12.8 Tbps
아키텍처TNA (Tofino Native Architecture)T2NA
MAU 스테이지12단계20단계
SRAM~80 MB~160 MB
TCAM~8 MB~16 MB
레지스터스테이지당 ALU 연산 지원확장된 ALU + 해시 함수
특수 기능Mirror, Resubmit, Clone+ Ghost thread, Dynamic hash
/* Tofino TNA 아키텍처용 NGFW 파이프라인 (개요) */
Pipeline(
    NgfwIngressParser(),   /* 프로그래머블 파서 */
    NgfwIngress(),         /* 인그레스: ACL + CT + NAT */
    NgfwIngressDeparser(), /* 인그레스 디파서 */
    NgfwEgressParser(),    /* 이그레스 파서 */
    NgfwEgress(),          /* 이그레스: QoS 미터 + 미러링 */
    NgfwEgressDeparser()   /* 최종 디파서 */
) pipe;

Switch(pipe) main;

/* Tofino 특화: Resubmit으로 다단계 CT 조회 구현 */
/* 1차 패스: 정방향 해시로 CT 조회 */
/* miss → resubmit → 2차 패스: 역방향 해시로 CT 조회 */

(b) AMD Pensando DSC

AMD Pensando DSC(Distributed Services Card)는 Elba ASIC 기반의 SmartNIC/DPU로, P4 프로그래머블 파이프라인과 내장 ARM 코어를 결합합니다.

# Pensando DSC P4 프로그램 배포
# penctl: Pensando 관리 CLI
penctl system tech-support   # 시스템 상태 확인
penctl p4 program load --name ngfw_pipeline --file ngfw.p4bin
penctl p4 table entry add --table acl_table \
    --key "10.0.0.0/8, *, 6, *, 443" \
    --action permit
penctl p4 table entry add --table acl_table \
    --key "*, *, *, *, *" \
    --action deny

(c) Intel IPU (Infrastructure Processing Unit)

Intel IPU(구 Mount Evans)는 IDPF(Infrastructure Data Path Function) 드라이버와 통합되는 인프라 오프로드 전용 프로세서입니다.

플랫폼 비교 종합

항목Intel TofinoAMD Pensando DSCIntel IPU
폼 팩터스위치 ASICSmartNIC (PCIe)IPU (PCIe)
처리량6.5~12.8 Tbps최대 200 Gbps최대 200 Gbps
P4 아키텍처TNA/T2NAPNA (Portable NIC Arch)P4-SDE
스테이트풀 지원레지스터 + ALU레지스터 + ARM 코어레지스터 + Xeon 코어
내장 CPU없음 (외부 CPU 필요)ARM A72 (16코어)Xeon-D (최대 24코어)
NGFW 적합성초고속 스위치 방화벽호스트 NIC 인라인 NGFW인프라 통합 NGFW
생태계SDE + P4StudioPensando SDKIntel P4-SDE + IPDK
주요 용도데이터센터 경계 방화벽서버 단위 마이크로세그멘테이션클라우드 인프라 보안

P4 vs TC flower vs eBPF 비교

NGFW 오프로드에 사용할 수 있는 세 가지 주요 기술(P4, TC flower, eBPF)의 특성을 비교합니다. 각 기술은 서로 다른 설계 철학과 트레이드오프를 가지며, 환경에 따라 적합한 선택이 달라집니다.

비교 항목P4TC flower + eSwitcheBPF (XDP/TC)
프로그래밍 수준데이터 플레인 전체 정의고정 매치-액션 조합커널 공간 바이트코드
라인 레이트 보장보장 (ASIC 매핑)보장 (HW 오프로드 시)불가 (CPU 실행)
커스텀 프로토콜 파싱완전 지원미지원 (사전 정의 필드만)제한적 지원 (바이트 접근)
스테이트풀 처리레지스터 (HW)conntrack 오프로드 (HW)BPF 맵 (SW)
최대 처리량Tbps급100~400 Gbps10~100 Gbps (CPU 의존)
학습 곡선높음 (P4 언어 + ASIC 이해)낮음 (tc 명령어)중간 (C 유사 + BPF 제약)
생태계 성숙도제한적 (전용 HW 필요)높음 (주요 NIC 벤더 지원)높음 (커널 내장, 활발한 커뮤니티)
벤더 종속성ASIC별 아키텍처 차이NIC 벤더별 지원 범위 상이없음 (커널 표준)
커널 통합별도 SDK (비커널)완전 통합 (TC subsystem)완전 통합 (BPF subsystem)
동적 업데이트테이블 엔트리 (P4Runtime)tc filter add/delBPF 맵 업데이트 + 프로그램 교체
적합 사용 사례초고속 커스텀 프로토콜 NGFW표준 L2-L4 오프로드 NGFW유연한 커널 공간 보안 처리
하이브리드(Hybrid) 접근: 실제 대규모 배포에서는 세 기술을 조합하여 사용하는 것이 일반적입니다. 예를 들어 P4로 라인 레이트 5-tuple ACL + 기본 CT를 처리하고, 매치되지 않는 패킷(exception)은 eBPF XDP로 전달하여 DPI를 수행하며, 확립된 세션은 TC flower로 eSwitch에 오프로드합니다.

P4 매치-액션 파이프라인 다이어그램

아래 다이어그램은 P4 프로그래머블 파이프라인에서 NGFW 패킷 처리 흐름을 보여줍니다. 각 매치-액션 테이블은 ASIC의 MAU 스테이지에 매핑되며, 라인 레이트로 실행됩니다.

P4 NGFW 매치-액션 파이프라인 (ASIC 라인 레이트) Packet In Wire → RX Parser ETH 추출 → IPv4 추출 → TCP/UDP 추출 MAU Stage 0 5-tuple ACL ternary match permit / deny MAU Stage 1-2 CT State register lookup SYN→EST 상태머신 MAU Stage 3 NAT Rewrite exact match DNAT / SNAT MAU Stage 4 QoS Meter token bucket GREEN/YELLOW/RED Deparser 헤더 재조합 Packet Out DROP (deny) DROP (RED) CPU (컨트롤 플레인) Digest: 새 플로우 알림 P4Runtime gRPC 테이블 엔트리 추가/삭제 범례: 라인 레이트 데이터 경로 DROP 경로 CPU 예외 경로 (Digest) MAU Stage N = ASIC 매치-액션 유닛 스테이지 (고정 레이턴시, 파이프라인 병렬 처리) 모든 테이블이 파이프라인으로 연결되어 패킷당 고정 시간(수십 ns)에 처리 완료
P4 한계: P4는 DPI(Deep Packet Inspection)를 직접 구현하기 어렵습니다. 파서는 헤더 구조 기반이므로 페이로드(Payload) 패턴 매칭에는 부적합합니다. DPI가 필요한 경우 P4에서 digest로 첫 패킷을 CPU에 전달하고, CPU에서 DPI 수행 후 결과에 따라 P4 테이블에 permit/deny 엔트리를 추가하는 하이브리드 구조를 사용합니다.

흔한 실수와 안티패턴

NGFW 오프로드를 구현할 때 자주 발생하는 실수와 안티패턴 10가지를 정리합니다. 각 실수에 대한 증상, 원인, 올바른 해결 방법을 포함합니다.

#실수증상올바른 방법
1flowtable에 flags offload 없이 HW offload 기대모든 세션이 SW fast path에서만 처리flags offload 명시 + NIC 지원 확인
2nf_conntrack_max 부족새 연결 불가, nf_conntrack: table full 로그예상 동시 세션의 1.5배로 설정
3NFQUEUE fail-open 미설정Suricata 장애 시 전체 트래픽 차단queue ... bypass 옵션 사용
4flowtable timeout > conntrack timeout유령 플로우 (이미 종료된 세션의 HW 규칙 잔존)flowtable timeout < conntrack timeout
5ALG 프로토콜(FTP/SIP)을 무조건 오프로드데이터 채널 생성 실패, 통화 끊김ALG 제어 채널은 오프로드 제외
6eSwitch switchdev 전환 시 VF 미재설정VF가 legacy 모드에서 멈춤, offload 불가VF unbind → switchdev 전환 → VF rebind
7IRQ affinity 미설정단일 코어 과부하, 다른 코어 유휴RX 큐별 IRQ를 별도 코어에 바인딩
8XDP + NFQUEUE 조합 시 순서 실수XDP에서 DROP한 패킷이 DPI에 미도달XDP는 pre-filter만, DPI 대상은 반드시 PASS
9conntrackd 동기화 없이 HA failoverfailover 시 모든 세션 손실conntrackd + VRRP/keepalived 동기화
10HW flow table 크기 초과 무시SW 폴백으로 성능 급락 (HW→SW 전환 시 지연)HW 테이블 사용률 모니터링 + 알림

실수 1: flowtable에 flags offload 누락

# ❌ 잘못된 설정: flags offload 누락
nft add flowtable inet filter ft \
  { hook ingress priority 0; devices = { eth0, eth1 }; }
# → SW fast path만 동작, HW offload 없음

# ✅ 올바른 설정
nft add flowtable inet filter ft \
  { hook ingress priority 0; devices = { eth0, eth1 }; \
    flags offload; }

# 검증: HW offload 확인
conntrack -L --status OFFLOAD 2>/dev/null | wc -l
# 0이면 HW offload 동작하지 않음

# NIC 지원 여부 확인
ethtool -k eth0 | grep hw-tc-offload
# hw-tc-offload: on → HW offload 가능

실수 2: nf_conntrack_max 부족

# 현재 conntrack 사용량 확인
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

# ❌ 기본값(65536)은 NGFW에 부족
# 증상: dmesg에 "nf_conntrack: table full, dropping packet" 출력
dmesg | grep "table full"

# ✅ 예상 동시 세션의 1.5배로 설정
# 예: 동시 세션 200K 예상 → 300K으로 설정
sysctl -w net.netfilter.nf_conntrack_max=300000

# 해시 테이블 크기도 함께 조정 (max / 4 권장)
# 부팅 시 모듈 파라미터로 설정 (런타임 변경 불가)
echo "options nf_conntrack hashsize=75000" > \
  /etc/modprobe.d/nf_conntrack.conf

# 메모리 계산: 300K × ~320 bytes = ~96 MB
# 영구 설정
echo "net.netfilter.nf_conntrack_max = 300000" >> /etc/sysctl.d/99-ngfw.conf

실수 3: NFQUEUE fail-open 미설정

# ❌ 잘못된 설정: bypass 없음
# Suricata가 죽으면 모든 트래픽이 DROP됨
nft add rule inet filter forward \
  ct state new queue num 0

# ✅ 올바른 설정: bypass 옵션으로 fail-open
nft add rule inet filter forward \
  ct state new queue num 0-3 fanout,bypass

# fanout: 여러 NFQUEUE에 분산 (Suricata 멀티스레드)
# bypass: NFQUEUE가 비어있으면 자동으로 ACCEPT

# 검증: Suricata 프로세스 상태 확인
ss -nlp | grep suricata
# Suricata가 NFQUEUE를 바인딩하고 있는지 확인

# Suricata 설정 (suricata.yaml)
# nfqueue:
#   mode: accept   ← fail-open (NFQUEUE 바인딩 해제 시 accept)
#   fail-open: yes

실수 4: flowtable timeout > conntrack timeout

# ❌ 위험: conntrack timeout이 먼저 만료되면
# conntrack 엔트리 삭제 → flowtable 엔트리 고아화
# → HW에 유령 규칙 잔존 → 보안 위험

# conntrack timeout 확인
sysctl net.netfilter.nf_conntrack_tcp_timeout_established
# 기본: 432000 (5일)

# ✅ flowtable timeout은 conntrack timeout보다 짧게
# flowtable 기본 timeout: 30초 (자동 갱신)
# 문제가 되는 경우: conntrack timeout을 짧게 줄인 경우
# 예: UDP conntrack timeout을 30초로 줄이면
sysctl -w net.netfilter.nf_conntrack_udp_timeout_stream=60
# flowtable aging은 이보다 짧은 주기로 동작해야 함

# HW flow 엔트리 상태 확인 (mlx5)
tc -s filter show dev eth0 ingress
# → 각 규칙의 packets/bytes 카운터 확인
# 카운터가 오래 정지된 규칙 = 유령 플로우 의심

실수 5: ALG 프로토콜 무조건 오프로드

# ❌ 잘못된 설정: 모든 EST 세션을 무조건 오프로드
nft add rule inet filter forward \
  ct state established flow add @ft

# ✅ 올바른 설정: ALG helper가 있는 세션은 제외
nft add rule inet filter forward \
  ct state established \
  ct helper "" \
  flow add @ft

# ct helper ""는 helper가 없는 세션만 매칭
# FTP, SIP, H.323 등 ALG 세션은 항상 Slow Path 유지

# 현재 ALG helper가 할당된 세션 확인
conntrack -L | grep helper
# 예: tcp  6 300 ESTABLISHED ... helper=ftp

실수 6: eSwitch switchdev 전환 시 VF 미재설정

# ❌ 잘못된 순서: VF가 바인딩된 상태에서 switchdev 전환
# 결과: 전환 실패 또는 VF가 legacy 모드에 잔류

# ✅ 올바른 순서
# 1. VF unbind (모든 VF)
for vf in /sys/bus/pci/devices/0000:04:00.0/virtfn*; do
    pci_addr=$(basename $(readlink $vf))
    echo $pci_addr > /sys/bus/pci/drivers/mlx5_core/unbind 2>/dev/null
done

# 2. switchdev 모드 전환
devlink dev eswitch set pci/0000:04:00.0 mode switchdev

# 3. VF rebind
for vf in /sys/bus/pci/devices/0000:04:00.0/virtfn*; do
    pci_addr=$(basename $(readlink $vf))
    echo $pci_addr > /sys/bus/pci/drivers/mlx5_core/bind 2>/dev/null
done

# 4. 검증
devlink dev eswitch show pci/0000:04:00.0
# mode switchdev inline-mode transport encap-mode basic

# VF representor 확인
ip link show | grep "enp4s0f0v"

실수 7: IRQ affinity 미설정

# 증상: mpstat으로 확인하면 CPU0만 100%, 나머지 idle
mpstat -P ALL 1

# 현재 IRQ 분포 확인
cat /proc/interrupts | grep eth0

# ✅ IRQ affinity 자동 설정 스크립트
# Mellanox NIC의 경우
if [ -x /usr/sbin/mlnx_affinity ]; then
    /usr/sbin/mlnx_affinity
fi

# 수동 설정: RX 큐별 IRQ를 별도 코어에 바인딩
# 예: 8개 RX 큐를 CPU 0-7에 각각 바인딩
for i in $(seq 0 7); do
    irq=$(grep "eth0-$i" /proc/interrupts | awk '{print $1}' | tr -d ':')
    echo $((1 << $i)) > /proc/irq/$irq/smp_affinity
done

# irqbalance 서비스 비활성화 (NGFW에서는 수동 제어 권장)
systemctl stop irqbalance
systemctl disable irqbalance

# RPS (Receive Packet Steering) 설정 (SW fallback)
echo "ff" > /sys/class/net/eth0/queues/rx-0/rps_cpus

실수 8: XDP + NFQUEUE 순서 실수

# ❌ 문제: XDP에서 DPI 대상까지 DROP
# XDP는 Netfilter 이전에 실행되므로
# XDP에서 DROP한 패킷은 NFQUEUE(DPI)에 도달 불가

# ✅ 올바른 설계:
# XDP: 명백한 공격만 차단 (rate limit, blocklist)
# Netfilter/NFQUEUE: DPI 대상 패킷 처리

# XDP에서 DPI 대상 트래픽은 반드시 XDP_PASS
# XDP 프로그램 내 분류 로직:
#   blocklist match → XDP_DROP
#   rate limit 초과 → XDP_DROP
#   그 외 모두 → XDP_PASS (Netfilter로 진행)

# XDP 프로그램 로드
ip link set dev eth0 xdpgeneric obj xdp_prefilter.o sec xdp

# XDP 통계 확인 (DROP된 패킷이 의도한 것인지 검증)
bpftool prog show
bpftool map dump name xdp_stats_map

실수 9: conntrackd 동기화 없이 HA failover

# ❌ conntrackd 없이 VRRP failover 시:
# 모든 기존 세션이 새 마스터에서 NEW로 처리
# → DPI 재검사, flowtable 재등록 → 수초간 성능 저하

# ✅ conntrackd 설정 (/etc/conntrackd/conntrackd.conf)
# Sync {
#     Mode FTFW {            ← Fault Tolerant, Full Write
#         ResendQueueSize 131072
#         PurgeTimeout 60
#     }
#     UDP {
#         IPv4_address 10.0.0.1
#         IPv4_Destination_Address 10.0.0.2
#         Port 3780
#         Interface eth2      ← 동기화 전용 인터페이스
#     }
# }

# conntrackd 시작
systemctl start conntrackd

# VRRP failover 스크립트에 추가
# /etc/keepalived/notify_master.sh:
conntrackd -C /etc/conntrackd/conntrackd.conf -c  # 커밋
conntrackd -C /etc/conntrackd/conntrackd.conf -f  # 플러시
conntrackd -C /etc/conntrackd/conntrackd.conf -R  # 수신 테이블 복원

# 동기화 상태 확인
conntrackd -s
# cache-internal: 150000 entries
# cache-external: 148500 entries  ← 피어와 거의 동기

실수 10: HW flow table 크기 초과 무시

# NIC별 HW flow table 최대 엔트리
# Mellanox CX-6 Dx: ~1M flows
# Intel E810: ~64K flows
# Broadcom P2100: ~500K flows

# ❌ HW 테이블 초과 시 증상:
# - dmesg: "mlx5_core: Failed to add TC flower rule (-ENOSPC)"
# - 새 오프로드 실패 → SW flowtable 폴백 → 성능 급락
# - 기존 HW 규칙은 유지되지만 새 세션은 모두 SW 처리

# ✅ 모니터링 설정
# Prometheus exporter를 위한 HW flow 사용률 체크 스크립트

# 현재 HW offload 세션 수
hw_flows=$(conntrack -L --status OFFLOAD 2>/dev/null | wc -l)
echo "ngfw_hw_flows_current $hw_flows"

# TC filter 통계
tc -s filter show dev eth0 ingress | grep -c "in_hw"
# in_hw = HW에 설치된 규칙 수

# 알림 임계값: HW 한계의 80%에서 경고
hw_max=1000000  # CX-6 Dx
threshold=$(( hw_max * 80 / 100 ))
if [ $hw_flows -gt $threshold ]; then
    logger -p daemon.warning "NGFW: HW flow table usage $hw_flows/$hw_max (${threshold} threshold)"
fi
안티패턴 종합 점검: 위 10가지 실수를 한 번에 점검하는 스크립트를 작성하여 NGFW 배포 전 자동 검증에 활용하세요. 특히 실수 3(fail-open)실수 9(HA 동기화)는 장애 시 서비스 전체에 영향을 미치므로 반드시 사전에 검증해야 합니다. 프로덕션 배포 전에 네트워크 네임스페이스 기반 가상 환경에서 모든 시나리오를 테스트하세요.

실습 가이드

이 섹션에서는 실제 Linux 환경에서 NGFW 오프로드를 단계별로 구현하는 실습을 제공합니다. 네트워크 네임스페이스를 활용하여 물리 장비 없이도 핵심 개념을 실험할 수 있습니다.

실습 환경 구성

요구사항최소 사양권장 사양비고
커널 버전5.13+ (flowtable)6.1+ (full CT offload)uname -r로 확인
nftables0.9.8+1.0.6+nft --version
Suricata6.0+7.0+suricata --build-info
iproute25.10+6.1+ip -V
NIC (Lab 3용)-Mellanox CX-5+ / Intel E810HW offload 실습 시 필요
메모리2 GB8 GB+Suricata + conntrack 테이블
CPU2 코어4+ 코어NFQUEUE 병렬 처리
도구iperf3, curl+ hping3, bpftool, tcpdump테스트 및 디버깅

Lab 1 — 기본 flowtable 오프로드

네트워크 네임스페이스로 라우터를 구성하고, nftables flowtable을 설정한 후 성능을 측정합니다.

#!/bin/bash
# Lab 1: 기본 flowtable 오프로드 실습
# 토폴로지: [client] ---veth--- [router] ---veth--- [server]

set -e

# ============ 1. 네임스페이스 생성 ============
ip netns add client
ip netns add router
ip netns add server

# ============ 2. veth 쌍 생성 ============
# client ↔ router
ip link add c-eth0 type veth peer name r-eth0
ip link set c-eth0 netns client
ip link set r-eth0 netns router

# router ↔ server
ip link add r-eth1 type veth peer name s-eth0
ip link set r-eth1 netns router
ip link set s-eth0 netns server

# ============ 3. IP 설정 ============
# client: 10.0.1.0/24
ip netns exec client ip addr add 10.0.1.10/24 dev c-eth0
ip netns exec client ip link set c-eth0 up
ip netns exec client ip link set lo up
ip netns exec client ip route add default via 10.0.1.1

# router: 게이트웨이
ip netns exec router ip addr add 10.0.1.1/24 dev r-eth0
ip netns exec router ip addr add 10.0.2.1/24 dev r-eth1
ip netns exec router ip link set r-eth0 up
ip netns exec router ip link set r-eth1 up
ip netns exec router ip link set lo up
ip netns exec router sysctl -w net.ipv4.ip_forward=1

# server: 10.0.2.0/24
ip netns exec server ip addr add 10.0.2.20/24 dev s-eth0
ip netns exec server ip link set s-eth0 up
ip netns exec server ip link set lo up
ip netns exec server ip route add default via 10.0.2.1

# ============ 4. 연결 테스트 ============
ip netns exec client ping -c 2 10.0.2.20

echo "=== 네트워크 설정 완료 ==="
# ============ 5. nftables flowtable 설정 (router) ============

ip netns exec router nft -f - <<'EOF'
flush ruleset

table inet ngfw_lab {
    flowtable ft {
        hook ingress priority 0;
        devices = { r-eth0, r-eth1 };
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # ESTABLISHED 세션 → flowtable (SW offload)
        ct state established,related flow add @ft counter accept

        # 새 세션 허용 (테스트용 전체 허용)
        ct state new counter accept

        # INVALID 차단
        ct state invalid counter drop
    }

    # NAT (옵션: SNAT 테스트)
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname "r-eth1" masquerade
    }
}
EOF

echo "=== nftables 설정 완료 ==="
# ============ 6. 성능 측정 ============

# server에서 iperf3 서버 시작
ip netns exec server iperf3 -s -D

# client에서 iperf3 테스트 (10초, TCP)
echo "=== flowtable 활성 상태 성능 ==="
ip netns exec client iperf3 -c 10.0.2.20 -t 10

# ============ 7. 오프로드 확인 ============

# conntrack 상태 확인 (router)
ip netns exec router conntrack -L
# 예상 출력:
# tcp  6 300 ESTABLISHED src=10.0.1.10 dst=10.0.2.20
#   sport=45678 dport=5201 [OFFLOAD] ...

# flowtable 엔트리 확인
ip netns exec router conntrack -L --status ASSURED
# OFFLOAD 상태가 표시되면 SW flowtable에서 처리 중

# nftables 카운터 확인
ip netns exec router nft list ruleset
# forward chain의 counter: 첫 몇 패킷만 카운트
# (나머지는 flowtable에서 바이패스)

# ============ 8. flowtable 비활성 비교 ============

# flowtable 규칙 제거
ip netns exec router nft delete rule inet ngfw_lab forward handle $(
  ip netns exec router nft -a list chain inet ngfw_lab forward | \
  grep "flow add" | awk '{print $NF}'
)

echo "=== flowtable 비활성 상태 성능 ==="
ip netns exec client iperf3 -c 10.0.2.20 -t 10

# 두 결과 비교: flowtable 활성 시 처리량 향상 확인
# ============ 정리 스크립트 ============
ip netns exec server pkill iperf3 2>/dev/null
ip netns del client
ip netns del router
ip netns del server
echo "=== Lab 1 정리 완료 ==="

Lab 2 — NFQUEUE + Suricata DPI 통합

Lab 1의 환경에 Suricata DPI 엔진을 추가하여, 새 세션은 DPI 검사를 거치고 분류 완료된 세션만 오프로드되도록 구성합니다.

# Lab 2: NFQUEUE + Suricata DPI 통합
# 사전 조건: Lab 1의 네트워크 환경 구성 완료
# Suricata 설치: apt install suricata (또는 dnf install suricata)

# ============ 1. Suricata 설정 ============
# /etc/suricata/suricata.yaml 수정 (주요 항목)

cat > /tmp/suricata-nfqueue.yaml <<'EOF'
# NFQUEUE 모드 설정
nfq:
  mode: accept          # 기본 verdict: accept (fail-open)
  repeat-mark: 1
  repeat-mask: 1
  bypass-mark: 8        # DPI 분류 완료 시 이 mark 설정
  bypass-mask: 8
  fail-open: yes        # Suricata 장애 시 트래픽 허용

# NFQUEUE 수신 설정
nfqueue:
  - queue-num: 0
    threads: 2
  - queue-num: 1
    threads: 2

# 출력: eve.json 로깅
outputs:
  - eve-log:
      enabled: yes
      filename: /var/log/suricata/eve.json
      types:
        - alert
        - http
        - dns
        - tls
EOF
# ============ 2. nftables 규칙 (DPI 통합) ============

ip netns exec router nft -f - <<'EOF'
flush ruleset

table inet ngfw_lab2 {
    flowtable ft {
        hook ingress priority 0;
        devices = { r-eth0, r-eth1 };
    }

    chain forward {
        type filter hook forward priority 0; policy drop;

        # 1. DPI 완료 + bypass mark가 있는 EST 세션 → flowtable
        ct state established meta mark & 0x08 == 0x08 \
            flow add @ft counter accept

        # 2. EST/RELATED (아직 DPI 진행 중) → 통과
        ct state established,related counter accept

        # 3. 새 세션 → NFQUEUE (Suricata DPI)
        ct state new queue num 0-1 fanout,bypass

        # 4. INVALID 차단
        ct state invalid counter drop
    }

    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname "r-eth1" masquerade
    }
}
EOF

echo "=== DPI 통합 nftables 설정 완료 ==="
# ============ 3. Suricata 시작 및 테스트 ============

# Suricata를 router 네임스페이스에서 NFQUEUE 모드로 시작
ip netns exec router suricata -c /tmp/suricata-nfqueue.yaml \
  -q 0 -q 1 -D

# 잠시 대기 (초기화)
sleep 3

# ============ 4. DPI 탐지 테스트 ============

# HTTP 요청 (DPI가 HTTP로 분류해야 함)
ip netns exec server python3 -m http.server 80 &
sleep 1
ip netns exec client curl -s http://10.0.2.20/

# Suricata 로그 확인
ip netns exec router cat /var/log/suricata/eve.json | \
  python3 -m json.tool | grep -A5 "\"http\""

# conntrack 확인: bypass mark(8)가 설정되었는지 확인
ip netns exec router conntrack -L | grep mark
# mark=8 → DPI 완료, 오프로드 대상

# iperf3 성능 테스트 (DPI 후 오프로드 확인)
ip netns exec server iperf3 -s -D
ip netns exec client iperf3 -c 10.0.2.20 -t 10

# 결과: 첫 몇 패킷은 NFQUEUE 경유, 이후 flowtable 오프로드

echo "=== Lab 2 완료 ==="

Lab 3 — TC flower eSwitch HW offload (SmartNIC 필요)

주의: 이 Lab은 Mellanox ConnectX-5 이상 또는 Intel E810 시리즈 SmartNIC이 필요합니다. 가상 환경에서는 실행할 수 없습니다. SR-IOV VF가 생성되어 있어야 합니다.
#!/bin/bash
# Lab 3: TC flower eSwitch HW offload
# 사전 조건: SmartNIC (CX-5+/E810), SR-IOV VF 생성됨

NIC="enp4s0f0"  # PF 이름 (환경에 맞게 변경)
PCI="0000:04:00.0"  # PCI 주소

# ============ 1. eSwitch switchdev 전환 ============

# 현재 모드 확인
devlink dev eswitch show pci/$PCI

# VF unbind
for vf in /sys/bus/pci/devices/$PCI/virtfn*; do
    pci_addr=$(basename $(readlink $vf))
    echo $pci_addr > /sys/bus/pci/drivers/mlx5_core/unbind 2>/dev/null || true
done

# switchdev 모드 전환
devlink dev eswitch set pci/$PCI mode switchdev

# VF rebind
for vf in /sys/bus/pci/devices/$PCI/virtfn*; do
    pci_addr=$(basename $(readlink $vf))
    echo $pci_addr > /sys/bus/pci/drivers/mlx5_core/bind 2>/dev/null || true
done

# TC HW offload 활성화
ethtool -K $NIC hw-tc-offload on

echo "=== eSwitch switchdev 전환 완료 ==="

# VF representor 확인
ip link show | grep "${NIC}v"
# ============ 2. TC flower ct 규칙 설치 ============

VF_REP="${NIC}v0"  # VF0 representor

# 기존 규칙 초기화
tc qdisc del dev $VF_REP ingress 2>/dev/null || true
tc qdisc add dev $VF_REP ingress

tc qdisc del dev $NIC ingress 2>/dev/null || true
tc qdisc add dev $NIC ingress

# VF → Uplink 방향: conntrack 추적 시작
tc filter add dev $VF_REP ingress prio 1 \
  protocol ip flower \
  ct_state -trk \
  action ct zone 1

# VF → Uplink: EST 세션 → HW forward
tc filter add dev $VF_REP ingress prio 2 \
  protocol ip flower \
  ct_state +trk+est \
  action ct zone 1 \
  action mirred egress redirect dev $NIC

# VF → Uplink: NEW 세션 → CPU
tc filter add dev $VF_REP ingress prio 3 \
  protocol ip flower \
  ct_state +trk+new \
  action pass

# Uplink → VF 방향 (동일 패턴)
tc filter add dev $NIC ingress prio 1 \
  protocol ip flower \
  ct_state -trk \
  action ct zone 1

tc filter add dev $NIC ingress prio 2 \
  protocol ip flower \
  ct_state +trk+est \
  action ct zone 1 \
  action mirred egress redirect dev $VF_REP

tc filter add dev $NIC ingress prio 3 \
  protocol ip flower \
  ct_state +trk+new \
  action pass

echo "=== TC flower ct 규칙 설치 완료 ==="
# ============ 3. HW offload 확인 ============

# TC 규칙이 HW에 설치되었는지 확인
tc -s filter show dev $VF_REP ingress
# 출력에서 "in_hw" 플래그 확인
# in_hw in_hw_count 1 → HW에 성공적으로 설치됨

# conntrack 오프로드 확인
conntrack -L --status OFFLOAD
# [OFFLOAD] 상태의 세션 확인

# HW 카운터 확인
tc -s filter show dev $VF_REP ingress
# packets/bytes 카운터가 증가하면 HW에서 처리 중

# ethtool 통계
ethtool -S $NIC | grep -E "tx_packets|rx_packets|offload"

echo "=== Lab 3 HW offload 확인 완료 ==="

Lab 4 — XDP DDoS Pre-filter

XDP 프로그램을 작성하여 NIC 드라이버 수준에서 SYN flood 공격을 차단합니다. 이 프로그램은 nftables NGFW 파이프라인 앞에 배치됩니다.

/* xdp_synflood_filter.c — XDP SYN flood 방어 프로그램 */
/* 컴파일: clang -O2 -target bpf -c xdp_synflood_filter.c -o xdp_synflood_filter.o */

#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>

#define MAX_ENTRIES  100000
#define SYN_RATE_LIMIT 100   /* 소스 IP당 초당 SYN 최대 100개 */
#define WINDOW_NS  (1000000000ULL)  /* 1초 (나노초) */

/* 소스 IP별 SYN 카운터 */
struct syn_count {
    __u64 count;           /* 윈도우 내 SYN 수 */
    __u64 window_start;    /* 현재 윈도우 시작 시간 */
};

struct {
    __uint(type, BPF_MAP_TYPE_LRU_HASH);
    __uint(max_entries, MAX_ENTRIES);
    __type(key, __be32);            /* 소스 IP */
    __type(value, struct syn_count);
} syn_rate_map SEC(".maps");

/* IP 차단 리스트 (관리자가 bpftool로 추가) */
struct {
    __uint(type, BPF_MAP_TYPE_LPM_TRIE);
    __uint(max_entries, 10000);
    __uint(map_flags, BPF_F_NO_PREALLOC);
    __type(key, struct lpm_key);
    __type(value, __u32);           /* 1=block */
} blocklist SEC(".maps");

/* 통계 */
struct {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __uint(max_entries, 3);  /* 0:pass, 1:drop_rate, 2:drop_block */
    __type(key, __u32);
    __type(value, __u64);
} xdp_stats SEC(".maps");

struct lpm_key {
    __u32 prefixlen;
    __be32 addr;
};

SEC("xdp")
int xdp_syn_filter(struct xdp_md *ctx)
{
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;
    struct ethhdr *eth = data;
    struct iphdr *iph;
    struct tcphdr *tcph;
    __u32 stat_key;
    __u64 *stat_val;

    /* 경계 검사 */
    if ((void *)(eth + 1) > data_end)
        return XDP_PASS;

    if (eth->h_proto != bpf_htons(ETH_P_IP))
        return XDP_PASS;

    iph = (struct iphdr *)(eth + 1);
    if ((void *)(iph + 1) > data_end)
        return XDP_PASS;

    /* 1. IP 차단 리스트 확인 */
    struct lpm_key lpm = {
        .prefixlen = 32,
        .addr = iph->saddr,
    };
    if (bpf_map_lookup_elem(&blocklist, &lpm)) {
        stat_key = 2;
        stat_val = bpf_map_lookup_elem(&xdp_stats, &stat_key);
        if (stat_val) (*stat_val)++;
        return XDP_DROP;
    }

    /* TCP SYN만 rate limit */
    if (iph->protocol != IPPROTO_TCP)
        goto pass;

    tcph = (struct tcphdr *)((void *)iph + (iph->ihl * 4));
    if ((void *)(tcph + 1) > data_end)
        goto pass;

    /* SYN 패킷만 필터링 (SYN=1, ACK=0) */
    if (!(tcph->syn && !tcph->ack))
        goto pass;

    /* 2. SYN rate limiting */
    __u64 now = bpf_ktime_get_ns();
    struct syn_count *sc;

    sc = bpf_map_lookup_elem(&syn_rate_map, &iph->saddr);
    if (sc) {
        if (now - sc->window_start > WINDOW_NS) {
            /* 새 윈도우 시작 */
            sc->count = 1;
            sc->window_start = now;
        } else {
            sc->count++;
            if (sc->count > SYN_RATE_LIMIT) {
                /* rate limit 초과 → DROP */
                stat_key = 1;
                stat_val = bpf_map_lookup_elem(&xdp_stats, &stat_key);
                if (stat_val) (*stat_val)++;
                return XDP_DROP;
            }
        }
    } else {
        struct syn_count new_sc = {
            .count = 1,
            .window_start = now,
        };
        bpf_map_update_elem(&syn_rate_map, &iph->saddr, &new_sc, BPF_ANY);
    }

pass:
    stat_key = 0;
    stat_val = bpf_map_lookup_elem(&xdp_stats, &stat_key);
    if (stat_val) (*stat_val)++;
    return XDP_PASS;
}

char _license[] SEC("license") = "GPL";
# ============ XDP 프로그램 로드 및 테스트 ============

# 1. 컴파일
clang -O2 -g -target bpf \
  -I /usr/include/$(uname -m)-linux-gnu \
  -c xdp_synflood_filter.c -o xdp_synflood_filter.o

# 2. XDP 프로그램 로드 (generic 모드: 모든 NIC 지원)
ip netns exec router \
  ip link set dev r-eth0 xdpgeneric obj xdp_synflood_filter.o sec xdp

# 확인
ip netns exec router ip link show r-eth0
# → "xdpgeneric ... prog/xdp" 표시

# 3. SYN flood 테스트 (hping3 사용)
# hping3 설치: apt install hping3
ip netns exec client hping3 -S -p 80 --flood 10.0.2.20 &
FLOOD_PID=$!
sleep 5
kill $FLOOD_PID

# 4. XDP 통계 확인
ip netns exec router bpftool map dump name xdp_stats
# key: 0 (pass), 1 (drop_rate), 2 (drop_block)
# drop_rate 카운터가 증가했으면 rate limiting 작동

# 5. IP 차단 리스트에 추가 (bpftool 사용)
# bpftool map update name blocklist \
#   key hex 20 00 00 00 0a 00 01 0a \
#   value hex 01 00 00 00
# → 10.0.1.10/32 차단

# 6. XDP 프로그램 제거
ip netns exec router ip link set dev r-eth0 xdpgeneric off

echo "=== Lab 4 완료 ==="
실습 확장 아이디어:
  • Lab 5: conntrackd + keepalived로 HA failover 테스트 (네임스페이스 2개의 라우터)
  • Lab 6: conntrack zone 기반 멀티 테넌트 격리 (Lab 1에 zone 추가)
  • Lab 7: Prometheus + Grafana로 NGFW 메트릭 대시보드 구성
  • Lab 8: nftables + Suricata + XDP 삼중 파이프라인 전체 통합
실습 환경 토폴로지 (Lab 1~4) client (netns) c-eth0: 10.0.1.10/24 iperf3 -c / curl / hping3 gw: 10.0.1.1 router (netns) r-eth0: 10.0.1.1 r-eth1: 10.0.2.1 XDP (L4) nftables flowtable NFQUEUE Suricata DPI (Q0-1) SNAT Lab 4 Lab 1 Lab 1 Lab 2 server (netns) s-eth0: 10.0.2.20/24 iperf3 -s / python3 http gw: 10.0.2.1 veth pair veth pair Lab 3: HW Offload (SmartNIC) eSwitch switchdev + TC flower ct 물리 NIC(CX-5+/E810) 필요 VF rep → HW FDB → PF uplink

TC flower + CT offload 스테이트풀 방화벽 실전 예제

이 섹션에서는 TC flower + CT action을 사용하여 실제 스테이트풀 방화벽을 구성하는 완전한 예제를 제공합니다. eSwitch switchdev 모드에서 동작하며, 첫 패킷만 커널 conntrack을 거치고 이후 패킷은 하드웨어에서 직접 포워딩됩니다.

전체 아키텍처

TC flower + CT Offload 스테이트풀 방화벽 처리 흐름 물리 NIC PF (uplink rep) eSwitch FDB TC flower HW rules chain 0 → chain 1 (ct) Kernel Slow Path conntrack + nftables 첫 패킷: NEW → ESTABLISHED HW Fast Path CT established match 이후 패킷: 0 CPU cycles ingress miss offload TC flower Chain 구조 상세 chain 0 (pre-ct) action ct zone 1 → goto chain 1 모든 패킷 CT lookup chain 1 (post-ct) ct_state +est +trk → action mirred redirect HW offload (fast path) chain 1 (new) ct_state +new +trk → action ct commit kernel로 전달 (slow) chain 1 (invalid) ct_state +inv +trk → action drop 잘못된 패킷 차단 SNAT/DNAT Offload ct action에 nat 파라미터 추가 action ct commit nat src → HW에서 NAT 주소 변환 수행 conntrack NAT entry → HW table CT Zone 분리 멀티 테넌트 격리용 zone ID action ct zone 1 (tenant A) action ct zone 2 (tenant B) 동일 5-tuple도 zone별 독립 추적 HW 타임아웃 관리 SW conntrack과 동기화 필수 HW aging → SW entry 삭제 SW timeout → HW rule 삭제 불일치 시 stale flow 발생

eSwitch switchdev 모드 준비

# 1. eSwitch switchdev 모드 전환 (Mellanox CX-6 Dx 예시)
# VF 생성 후 switchdev 모드로 전환
echo 2 > /sys/class/net/enp3s0f0/device/sriov_numvfs
devlink dev eswitch set pci/0000:03:00.0 mode switchdev

# 2. VF representor 확인
ip link show | grep "enp3s0f0"
# enp3s0f0: PF (uplink representor)
# enp3s0f0_0: VF0 representor
# enp3s0f0_1: VF1 representor

# 3. TC offload 활성화
ethtool -K enp3s0f0 hw-tc-offload on
ethtool -K enp3s0f0_0 hw-tc-offload on
ethtool -K enp3s0f0_1 hw-tc-offload on

# 4. CT offload 커널 모듈 로드
modprobe act_ct
modprobe cls_flower

TC flower CT 스테이트풀 규칙 구성

#!/bin/bash
# TC flower + CT offload 스테이트풀 방화벽 구성 스크립트
# 대상: eSwitch switchdev 모드 NIC (CX-5+, CX-6, E810)

UPLINK_REP="enp3s0f0"     # PF uplink representor
VF0_REP="enp3s0f0_0"      # VF0 representor (내부 VM/컨테이너)
VF1_REP="enp3s0f0_1"      # VF1 representor (외부 인터페이스)
CT_ZONE=1

# === Ingress 방향 (외부 → 내부) ===

# chain 0: 모든 ingress 패킷에 CT lookup 수행
tc qdisc add dev $VF1_REP ingress
tc filter add dev $VF1_REP ingress prio 1 chain 0 proto ip flower \
    action ct zone $CT_ZONE pipe \
    action goto chain 1

# chain 1: established 세션 → HW fast path로 redirect
tc filter add dev $VF1_REP ingress prio 1 chain 1 proto ip flower \
    ct_state +est+trk \
    action mirred egress redirect dev $VF0_REP

# chain 1: 새 연결 (허용 포트: 80, 443) → CT commit 후 redirect
tc filter add dev $VF1_REP ingress prio 2 chain 1 proto ip flower \
    ct_state +new+trk \
    ip_proto tcp dst_port 80 \
    action ct zone $CT_ZONE commit pipe \
    action mirred egress redirect dev $VF0_REP

tc filter add dev $VF1_REP ingress prio 3 chain 1 proto ip flower \
    ct_state +new+trk \
    ip_proto tcp dst_port 443 \
    action ct zone $CT_ZONE commit pipe \
    action mirred egress redirect dev $VF0_REP

# chain 1: invalid 패킷 → drop
tc filter add dev $VF1_REP ingress prio 10 chain 1 proto ip flower \
    ct_state +inv+trk \
    action drop

# chain 1: 그 외 새 연결 → drop (default deny)
tc filter add dev $VF1_REP ingress prio 100 chain 1 proto ip flower \
    ct_state +new+trk \
    action drop

# === Egress 방향 (내부 → 외부) ===

tc qdisc add dev $VF0_REP ingress
tc filter add dev $VF0_REP ingress prio 1 chain 0 proto ip flower \
    action ct zone $CT_ZONE pipe \
    action goto chain 1

# 내부에서 외부로 나가는 established 트래픽 → HW fast path
tc filter add dev $VF0_REP ingress prio 1 chain 1 proto ip flower \
    ct_state +est+trk \
    action mirred egress redirect dev $VF1_REP

# 내부에서 외부로 새 연결 시작 → 허용 후 commit
tc filter add dev $VF0_REP ingress prio 2 chain 1 proto ip flower \
    ct_state +new+trk \
    action ct zone $CT_ZONE commit pipe \
    action mirred egress redirect dev $VF1_REP

NAT 오프로드 추가

# SNAT offload: 내부 사설 IP → 외부 공인 IP
# chain 0에서 CT + NAT 동시 수행
PUBLIC_IP="203.0.113.1"

tc filter add dev $VF0_REP ingress prio 1 chain 0 proto ip flower \
    action ct zone $CT_ZONE nat src addr $PUBLIC_IP pipe \
    action goto chain 1

# DNAT offload: 외부 → 내부 서비스 포트 매핑
INTERNAL_SERVER="10.0.1.100"

tc filter add dev $VF1_REP ingress prio 1 chain 0 proto ip flower \
    ip_proto tcp dst_port 8080 \
    action ct zone $CT_ZONE nat dst addr $INTERNAL_SERVER port 80 pipe \
    action goto chain 1

오프로드 상태 확인 명령어

# HW offload된 규칙 확인
tc -s filter show dev $VF1_REP ingress

# 출력 예시:
# filter protocol ip pref 1 flower chain 1 handle 0x1
#   ct_state +established+tracked
#   in_hw in_hw_count 1          ← HW에 설치됨
#   action order 1: mirred (Egress Redirect to device enp3s0f0_0)
#   Sent 1523456 bytes 12345 pkt (hardware 1523456 bytes 12345 pkt)

# conntrack 테이블에서 offload된 엔트리 확인
conntrack -L | grep "\[OFFLOAD\]"
# tcp  6 src=10.0.1.100 dst=203.0.113.50 ... [OFFLOAD]

# HW flow 통계
cat /sys/kernel/debug/mlx5/0000:03:00.0/ct/stats
# offloaded: 4523  sw_only: 12  max: 1000000
성능 검증 포인트: tc -s filter show에서 in_hw 플래그와 hardware N bytes N pkt 카운터를 반드시 확인하세요. in_hw가 없으면 규칙이 SW fallback으로 동작 중이며, 성능이 수십 배 차이날 수 있습니다. HW offload 실패 원인은 대부분 dmesg에서 확인할 수 있습니다.

OVS + HW 오프로드 마이크로세그멘테이션

마이크로세그멘테이션은 VM/컨테이너(Container) 간 East-West 트래픽을 세밀하게 제어하는 보안 모델입니다. Open vSwitch(OVS)의 TC flower offload를 활용하면 eSwitch 하드웨어에서 직접 마이크로세그멘테이션 정책을 적용할 수 있어, CPU 오버헤드 없이 수십만 개의 흐름을 처리합니다.

OVS TC Offload 마이크로세그멘테이션 아키텍처 Web Tier (Zone A) VM1 (nginx) VM2 (nginx) VF rep0, VF rep1 allow: 80/tcp, 443/tcp in allow: → App Tier 8080/tcp App Tier (Zone B) VM3 (app) VM4 (app) VF rep2, VF rep3 allow: Web Tier → 8080/tcp allow: → DB Tier 5432/tcp DB Tier (Zone C) VM5 (postgres) VM6 (redis) VF rep4, VF rep5 allow: App Tier → 5432, 6379 deny: Web Tier → DB (직접 차단) eSwitch FDB (HW Offloaded TC flower rules) OVS tc-offload=true → TC flower → HW FDB | CT zone per-tier | per-VF rep ACL 수십만 flow entries, line-rate 처리, CPU 0% 사용 Web→App (허용) App→DB (허용) Web→DB (차단, HW drop) OVS Control Plane ovs-vswitchd (userspace daemon) OpenFlow → datapath → TC flower → HW FDB other_config:hw-offload=true, tc-policy=skip_sw 정책 관리 계층 SDN Controller (OVN, OpenStack Neutron) Security Group → OpenFlow → TC flower chain 동적 정책 업데이트 → HW rule 즉시 반영

OVS HW offload 활성화

# 1. OVS HW offload 활성화
ovs-vsctl set Open_vSwitch . other_config:hw-offload=true
ovs-vsctl set Open_vSwitch . other_config:tc-policy=skip_sw

# 2. OVS 재시작 (설정 적용)
systemctl restart openvswitch-switch

# 3. OVS 브리지 생성 + VF representor 추가
ovs-vsctl add-br br-ngfw
ovs-vsctl add-port br-ngfw enp3s0f0     # PF uplink rep
ovs-vsctl add-port br-ngfw enp3s0f0_0   # VF0 rep (Web VM1)
ovs-vsctl add-port br-ngfw enp3s0f0_1   # VF1 rep (Web VM2)
ovs-vsctl add-port br-ngfw enp3s0f0_2   # VF2 rep (App VM3)
ovs-vsctl add-port br-ngfw enp3s0f0_3   # VF3 rep (App VM4)
ovs-vsctl add-port br-ngfw enp3s0f0_4   # VF4 rep (DB VM5)
ovs-vsctl add-port br-ngfw enp3s0f0_5   # VF5 rep (DB VM6)

마이크로세그멘테이션 OpenFlow 규칙

# 포트 번호 확인
ovs-ofctl dump-ports-desc br-ngfw
# 1(enp3s0f0): addr:... (uplink)
# 2(enp3s0f0_0): addr:... (VM1-web)
# 3(enp3s0f0_1): addr:... (VM2-web)
# 4(enp3s0f0_2): addr:... (VM3-app)
# 5(enp3s0f0_3): addr:... (VM4-app)
# 6(enp3s0f0_4): addr:... (VM5-db)
# 7(enp3s0f0_5): addr:... (VM6-db)

# === Zone A (Web) → Zone B (App): 8080/tcp 허용 ===
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=2,tcp,tp_dst=8080,\
actions=ct(zone=1,commit),output:4"
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=3,tcp,tp_dst=8080,\
actions=ct(zone=1,commit),output:4,output:5"

# === Zone B (App) → Zone C (DB): 5432/tcp, 6379/tcp 허용 ===
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=4,tcp,tp_dst=5432,\
actions=ct(zone=2,commit),output:6"
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=4,tcp,tp_dst=6379,\
actions=ct(zone=2,commit),output:7"
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=5,tcp,tp_dst=5432,\
actions=ct(zone=2,commit),output:6"
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=5,tcp,tp_dst=6379,\
actions=ct(zone=2,commit),output:7"

# === Established 응답 트래픽 (양방향) ===
ovs-ofctl add-flow br-ngfw "priority=200,ct_state=+est+trk,actions=normal"

# === Zone A (Web) → Zone C (DB): 직접 접근 차단 ===
ovs-ofctl add-flow br-ngfw "priority=150,ip,in_port=2,\
nw_dst=10.0.3.0/24,actions=drop"
ovs-ofctl add-flow br-ngfw "priority=150,ip,in_port=3,\
nw_dst=10.0.3.0/24,actions=drop"

# === 외부 → Zone A (Web): 80, 443 허용 ===
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=1,tcp,tp_dst=80,\
actions=ct(zone=0,commit),output:2,output:3"
ovs-ofctl add-flow br-ngfw "priority=100,ip,in_port=1,tcp,tp_dst=443,\
actions=ct(zone=0,commit),output:2,output:3"

# === Default deny ===
ovs-ofctl add-flow br-ngfw "priority=1,actions=drop"

오프로드 확인

# HW offload된 flow 확인
ovs-appctl dpctl/dump-flows type=offloaded

# 출력 예시:
# recirc_id(0),in_port(2),ct_state(est|trk),eth_type(0x0800),
#   ipv4(src=10.0.1.10,dst=10.0.2.20,proto=6),
#   tcp(src=45678,dst=8080), packets:152340, bytes:12345678,
#   used:0.001s, offloaded:yes, dp:tc

# HW flow 수 확인
ovs-appctl dpctl/dump-flows type=offloaded | wc -l

# TC flower HW 규칙 확인 (OVS가 내부적으로 생성)
tc -s filter show dev enp3s0f0_0 ingress
OVS CT offload 제약사항:
  • OVS 2.13+ 및 커널 5.7+에서 TC CT offload 지원
  • ALG(FTP, SIP 등) 프로토콜은 HW offload 불가 → SW fallback
  • CT zone은 NIC 하드웨어마다 최대 개수가 다름 (CX-6: 65535개)
  • NAT + CT 동시 offload 시 tc-policy=skip_sw 대신 skip_hw fallback 확인 필요

nftables + flowtable HW offload 실전 구성

nftables flowtable은 커널 nf_flow_table 인프라를 사용하여 established 세션을 Netfilter 훅을 건너뛰고 직접 전달합니다. NF_FLOWTABLE_HW_OFFLOAD 플래그를 설정하면 이 경로가 NIC 하드웨어에 직접 설치되어 제로 CPU 오버헤드로 패킷을 처리합니다.

nftables flowtable HW Offload 내부 구조 NIC RX eth0 HW Flow Table NIC TCAM/hash lookup 5-tuple match → direct TX SW Flow Table nf_flow_table rhashtable ingress hook에서 lookup Netfilter Full prerouting → forward conntrack + rules NIC TX eth1 HW Hit → Direct TX (0 CPU) miss SW fast path miss nftables 규칙 구조 (nft list ruleset) table inet firewall flowtable ft { hook ingress priority 0 devices = { eth0, eth1 } flags offload ← HW offload! } chain forward { ct state established flow add @ft ← offload! } Offload 내부 동작 1. 첫 패킷: Netfilter full path 2. ct state → established 3. flow add @ft 트리거 4. nf_flow_offload_add() 호출 5. ndo_setup_tc(TC_SETUP_FT) 6. NIC driver → HW flow entry 7. 이후 패킷: HW에서 직접 TX 8. aging timeout → HW entry 삭제 HW Offload 조건 NIC driver가 TC_SETUP_FT 지원 mlx5, ice, nfp 드라이버 미지원 시 SW flowtable fallback IPv4/IPv6 TCP/UDP만 offload ICMP, GRE 등은 SW 처리 NAT offload: 커널 5.13+ VLAN offload: 커널 5.15+ tunnel offload: 커널 6.1+

완전한 nftables 방화벽 + flowtable offload 구성

#!/usr/sbin/nft -f
# nftables + flowtable HW offload 완전 구성 예제
# 요구사항: 커널 5.13+, NIC driver TC_SETUP_FT 지원

flush ruleset

table inet firewall {

    # flowtable 정의: HW offload 활성화
    flowtable ft {
        hook ingress priority 0
        devices = { eth0, eth1 }
        flags offload              # ← HW offload 핵심 플래그
    }

    # NAT용 flowtable (별도 정의 가능)
    flowtable ft-nat {
        hook ingress priority 0
        devices = { eth0, eth1 }
        flags offload
    }

    # === Forward 체인: 방화벽 정책 ===
    chain forward {
        type filter hook forward priority filter; policy drop;

        # 1. established/related 세션 → flowtable offload
        ct state established,related flow add @ft accept

        # 2. 허용 정책: 내부→외부 (새 연결)
        iifname "eth1" oifname "eth0" ct state new accept

        # 3. 허용 정책: 외부→내부 특정 포트
        iifname "eth0" oifname "eth1" tcp dport { 80, 443, 22 } ct state new accept
        iifname "eth0" oifname "eth1" udp dport { 53, 123 } ct state new accept

        # 4. ICMP 허용 (offload 불가, SW 처리)
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # 5. invalid 패킷 차단
        ct state invalid drop

        # 6. 로깅 후 drop (default deny)
        log prefix "NFT-DROP: " limit rate 10/second drop
    }

    # === NAT 체인 ===
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;

        # SNAT: 내부 → 외부 (flowtable에서 NAT도 offload)
        oifname "eth0" masquerade
    }

    chain prerouting {
        type nat hook prerouting priority dstnat; policy accept;

        # DNAT: 외부 포트 8080 → 내부 서버 80
        iifname "eth0" tcp dport 8080 dnat to 10.0.1.100:80
    }

    # === Input 체인 (호스트 보호) ===
    chain input {
        type filter hook input priority filter; policy drop;

        ct state established,related accept
        iif lo accept
        tcp dport 22 ct state new accept
        ip protocol icmp accept
        drop
    }
}

flowtable offload 상태 확인 및 디버깅

# 1. flowtable offload 상태 확인
nft list flowtable inet firewall ft
# flowtable ft {
#     hook ingress priority 0
#     devices = { eth0, eth1 }
#     flags offload

# 2. offload된 flow 목록
cat /proc/net/nf_conntrack | grep "\[OFFLOAD\]"
# ipv4 2 tcp 6 src=10.0.1.10 dst=8.8.8.8 ... [OFFLOAD] ...

# 3. flowtable 통계
cat /proc/sys/net/netfilter/nf_flowtable_tcp_timeout
# 30 (초 단위, 기본값)

# 4. HW offload 활성 확인 (ethtool)
ethtool -k eth0 | grep "hw-tc-offload"
# hw-tc-offload: on

# 5. 커널 로그에서 offload 성공/실패 확인
dmesg | grep -i "flowtable\|flow_offload"
# mlx5_core: flow offload added, cookie=0x12345678
# mlx5_core: flow offload stats: pkts=152340 bytes=12345678

# 6. nftables 카운터로 실시간 모니터링
nft add rule inet firewall forward ct state established counter
nft list chain inet firewall forward
# counter packets 0 bytes 0  ← offload 중이면 0에 가까움
# (HW에서 처리되므로 nftables 카운터 증가하지 않음)
flowtable HW offload 주의사항: nftables forward 체인의 카운터는 offload되지 않은 패킷만 집계합니다. HW offload된 패킷 수를 정확히 확인하려면 conntrack -L[OFFLOAD] 엔트리 또는 ethtool -S eth0 | grep offload를 사용하세요.

Connection Tracking HW 오프로드

Connection Tracking(CT) 하드웨어 오프로드는 NGFW 성능의 핵심입니다. 이 섹션에서는 CT zone, NAT 오프로드, 타임아웃 관리, HW/SW 동기화 메커니즘을 상세히 다룹니다.

CT Zone 아키텍처

CT zone은 독립적인 conntrack 네임스페이스를 제공합니다. 동일한 5-tuple(src IP, dst IP, src port, dst port, protocol)이라도 서로 다른 zone에서는 별개의 연결로 추적됩니다. 멀티 테넌트 환경에서 필수입니다.

속성CT Zone 0 (기본)CT Zone N (사용자 정의)비고
용도일반 conntrack테넌트/VRF 격리zone ID: 0-65535
HW offload기본 지원CX-6+, E810 지원커널 5.13+
NAT 독립성글로벌 NATzone별 독립 NAT동일 내부 IP 가능
최대 엔트리nf_conntrack_max 공유zone별 제한 불가전체 합산 제한
HW 최대 zone-NIC 종속 (CX-6: 64K)HW 테이블 크기
# CT Zone 활용 예시: 테넌트별 격리

# 테넌트 A (zone 100): 192.168.1.0/24
tc filter add dev vf0_rep ingress prio 1 chain 0 proto ip flower \
    src_net 192.168.1.0/24 \
    action ct zone 100 pipe \
    action goto chain 1

# 테넌트 B (zone 200): 192.168.1.0/24 (동일 서브넷이지만 별도 추적)
tc filter add dev vf2_rep ingress prio 1 chain 0 proto ip flower \
    src_net 192.168.1.0/24 \
    action ct zone 200 pipe \
    action goto chain 1

# Zone별 conntrack 엔트리 확인
conntrack -L -z 100  # 테넌트 A 연결 목록
conntrack -L -z 200  # 테넌트 B 연결 목록

# Zone별 NAT: 동일 내부 IP가 다른 공인 IP로 NAT
# zone 100: 192.168.1.10 → 203.0.113.1
tc filter add dev vf0_rep ingress prio 1 chain 0 proto ip flower \
    action ct zone 100 nat src addr 203.0.113.1 pipe \
    action goto chain 1

# zone 200: 192.168.1.10 → 203.0.113.2
tc filter add dev vf2_rep ingress prio 1 chain 0 proto ip flower \
    action ct zone 200 nat src addr 203.0.113.2 pipe \
    action goto chain 1

HW/SW conntrack 타임아웃 동기화

HW와 SW conntrack은 독립적인 타임아웃 타이머를 가집니다. 이 둘의 불일치는 stale flow(유령 세션)나 premature expiry(조기 만료)를 유발하며, NGFW 안정성의 가장 큰 위험 요소입니다.

# SW conntrack 타임아웃 (기본값)
sysctl net.netfilter.nf_conntrack_tcp_timeout_established
# 432000 (5일)

sysctl net.netfilter.nf_conntrack_udp_timeout_stream
# 120 (2분)

# HW 타임아웃 (NIC 드라이버별 상이)
# Mellanox CX-6: 기본 30초 aging, SW와 주기적 동기화
cat /sys/kernel/debug/mlx5/0000:03:00.0/ct/aging_timeout
# 30

# HW aging 동작 방식:
# 1. HW entry에 30초간 패킷 없음 → HW aging event 발생
# 2. 드라이버가 SW conntrack에 통보 (nf_flow_offload_stats_update)
# 3. SW conntrack이 아직 활성이면 → HW entry 재설치
# 4. SW conntrack도 만료됐으면 → HW entry 삭제 확정

# 타임아웃 튜닝: flowtable TCP 타임아웃
sysctl -w net.netfilter.nf_flowtable_tcp_timeout=30
sysctl -w net.netfilter.nf_flowtable_udp_timeout=30

# 장기 세션 보호: TCP keepalive가 HW aging을 리셋
# → keepalive 간격을 HW aging보다 짧게 설정
sysctl -w net.ipv4.tcp_keepalive_time=20
sysctl -w net.ipv4.tcp_keepalive_intvl=5
CT 통계 카운터 동기화: HW에서 처리된 패킷/바이트 수는 주기적으로(보통 1초 간격) SW conntrack 엔트리에 반영됩니다. 따라서 conntrack -L로 보이는 카운터는 최대 1초 지연될 수 있습니다. 실시간 정밀 모니터링이 필요하면 NIC 하드웨어 카운터를 직접 조회하세요.

CT offload 예외 처리

상황동작원인대응
TCP RST/FINHW → SW 복귀연결 종료 시그널(Signal)자동 처리 (HW trap)
TCP 윈도우 밖 패킷HW → SW 복귀잠재적 공격 탐지SW에서 검증 후 재오프로드
ALG 프로토콜 (FTP)오프로드 불가페이로드 수정 필요SW 전용 처리 (flowtable 제외)
IP fragment오프로드 불가완전한 5-tuple 불가SW에서 재조립 후 처리
IPsec ESP/AHcrypto offload만전체 flow offload 불가xfrm device offload 별도 사용
GRE/VXLAN 내부 flow터널 offload 필요outer header만 HW 처리커널 6.1+ tunnel offload
SCTP오프로드 불가드라이버 미지원SW flowtable만 가능
conntrack helper (ALG)오프로드 불가payload inspection 필요해당 flow만 SW 유지

TC police/meter + mirred/sample HW 오프로드

TC flower 오프로드는 매치(match)뿐 아니라 다양한 액션(action)도 하드웨어에서 실행할 수 있습니다. 이 절에서는 act_police(속도 제한), act_sample(패킷 샘플링), act_mirred(미러링/리다이렉트), act_ct(커넥션 트래킹)를 조합하여 NGFW QoS + 모니터링 + 포워딩 파이프라인을 하드웨어에서 구현하는 방법을 살펴봅니다.

tc police action HW 오프로드

act_police토큰 버킷(Token Bucket) 알고리즘을 사용하여 트래픽 속도를 제한합니다. 커널 6.3 이상에서 skip_sw 플래그와 함께 사용하면, NIC ASIC의 하드웨어 미터(Meter)에서 속도 제한을 수행합니다.

토큰 버킷 알고리즘

파라미터설명tc 옵션
rate허용 속도 (CIR: Committed Information Rate)rate 1gbit
burst버스트 허용량 (CBS: Committed Burst Size)burst 64k
peakrate피크 속도 (PIR: Peak Information Rate, 선택)peakrate 2gbit
conform-exceed초과 시 액션 (drop, pipe, ok, reclassify)conform-exceed drop/pipe

per-flow 속도 제한

# === per-flow police 오프로드 ===

# 인그레스 qdisc 생성
tc qdisc add dev enp1s0f0 ingress

# 특정 플로우(10.0.0.0/24 → any, TCP/443)에 1 Gbps 제한
tc filter add dev enp1s0f0 ingress protocol ip \
    flower skip_sw \
    src_ip 10.0.0.0/24 \
    ip_proto tcp dst_port 443 \
    action police rate 1gbit burst 64k \
        conform-exceed drop/pipe \
        hw_stats immediate

# 전체 포트에 10 Gbps 제한 (per-port policing)
tc filter add dev enp1s0f0 ingress protocol all \
    prio 1000 flower skip_sw \
    action police rate 10gbit burst 256k \
        conform-exceed drop/pipe

드라이버 구현: mlx5e_tc_act_police

mlx5 드라이버에서 act_police HW 오프로드는 다음과 같은 경로로 처리됩니다.

/* drivers/net/ethernet/mellanox/mlx5/core/en_tc.c (개요) */

/* TC 액션 파싱 시 police 감지 */
/* tc_act_police_offload()
 *   → mlx5e_tc_act_police.offload()
 *     → mlx5_create_flow_meter()        -- HW 미터 객체 생성
 *       → MLX5_CMD_OP_CREATE_FLOW_METER -- 펌웨어 명령
 *     → FDB 규칙에 미터 연결 */

/* 주요 구조체 */
/* struct mlx5_flow_meter_params {
 *     u64 cir;    -- Committed Information Rate (bytes/sec)
 *     u32 cbs;    -- Committed Burst Size (bytes)
 *     u64 eir;    -- Excess Information Rate (optional)
 *     u32 ebs;    -- Excess Burst Size (optional)
 * }; */
HW 지원 확인: tc 명령에 skip_sw를 지정하면 하드웨어만으로 처리하라는 의미입니다. HW 오프로드가 실패하면 규칙 설치 자체가 에러를 반환합니다. skip_hw는 반대로 소프트웨어만 사용합니다. skip_swskip_hw도 지정하지 않으면 HW를 시도하고 실패 시 SW로 폴백(Fallback)합니다.

tc sample action HW 오프로드

act_sample패킷 샘플링을 수행하여 sFlow/IPFIX 수집기에 트래픽 가시성을 제공합니다. 하드웨어 오프로드 시 CPU 개입 없이 NIC이 직접 샘플 패킷을 추출합니다.

psample 커널 모듈

psample(net/psample/)은 커널의 패킷 샘플링 인프라입니다. NIC 드라이버가 샘플링한 패킷을 netlink 채널을 통해 사용자 공간의 수집기(hsflowd, softflowd 등)에 전달합니다.

파라미터설명tc 옵션
rate샘플 비율 (1:N, N개 패킷 중 1개 샘플)rate 1000
grouppsample 그룹 ID (수집기 식별)group 1
trunc샘플 패킷 절단 크기 (헤더만 수집 시)trunc 128
# === tc sample HW 오프로드 설정 ===

# 1:1000 비율로 샘플링, psample 그룹 1, 헤더 128바이트만
tc filter add dev enp1s0f0 ingress protocol ip \
    flower skip_sw \
    action sample rate 1000 group 1 trunc 128

# 모든 트래픽 샘플링 (matchall 사용)
tc filter add dev enp1s0f0 ingress protocol all \
    matchall skip_sw \
    action sample rate 500 group 1 trunc 256

# psample 그룹 확인
cat /proc/net/psample/groups
# 출력 예시:
# group 1: refcnt 1, packets 523456, bytes 67002368

sFlow 수집기 연동 (hsflowd)

# hsflowd 설치 및 설정
# /etc/hsflowd.conf
# sflow {
#   sampling = 1000
#   polling  = 30
#   collector { ip = 10.0.0.200 udpport = 6343 }
# }

# hsflowd는 psample netlink에서 샘플을 수신하여 sFlow 패킷으로 변환
systemctl start hsflowd
systemctl status hsflowd

# 실시간 sFlow 데이터 확인 (sflowtool)
sflowtool -p 6343 | head -20
IDS 연동: act_sample과 sFlow를 조합하면 CPU 부하 없이 IDS/IPS에 트래픽 가시성을 제공할 수 있습니다. 전체 패킷을 미러링하는 것보다 효율적이며, 1:1000 샘플 비율로도 대부분의 이상 탐지(Anomaly Detection) 알고리즘은 충분한 정확도를 유지합니다.

tc mirred + pedit HW 오프로드

act_mirred는 패킷을 다른 인터페이스로 리다이렉트(redirect)하거나 미러(mirror, 복제)합니다. IDS/IPS TAP 포트 구성에 핵심적이며, act_pedit을 결합하면 미러링 전에 헤더를 수정할 수 있습니다.

mirred redirect vs mirror

모드동작용도
egress redirect패킷을 대상 인터페이스로 전달 (원래 경로 대체)포워딩, Hairpin, NAT 후 전달
egress mirror패킷 복제본을 대상 인터페이스로 전송 (원본은 원래 경로 유지)IDS TAP, 트래픽 분석, 감사 로깅
# === mirred 오프로드: IDS TAP 포트 구성 ===

# 특정 플로우를 IDS 모니터링 포트(enp1s0f1)로 미러링
tc filter add dev enp1s0f0 ingress protocol ip \
    flower skip_sw \
    src_ip 10.0.0.0/24 \
    ip_proto tcp dst_port 443 \
    action mirred egress mirror dev enp1s0f1 pipe \
    action mirred egress redirect dev enp1s0f0_1

# 전체 포트 미러링 (matchall)
tc filter add dev enp1s0f0 ingress protocol all \
    matchall skip_sw \
    action mirred egress mirror dev enp1s0f1

# 이그레스 방향도 미러링 (양방향 TAP)
tc qdisc add dev enp1s0f0 clsact
tc filter add dev enp1s0f0 egress protocol all \
    matchall skip_sw \
    action mirred egress mirror dev enp1s0f1

pedit을 이용한 헤더 수정 후 미러링

# ERSPAN-like: 미러링 전에 GRE 헤더 정보를 DSCP에 기록
# (실제 ERSPAN 캡슐화는 HW 지원 필요)
tc filter add dev enp1s0f0 ingress protocol ip \
    flower skip_sw \
    ip_proto tcp \
    action pedit ex munge ip dscp set 46 pipe \
    action mirred egress mirror dev enp1s0f1

# VLAN 태그 추가 후 미러링 (TAP 포트에서 VLAN으로 소스 구분)
tc filter add dev enp1s0f0 ingress protocol ip \
    flower skip_sw \
    src_ip 10.0.1.0/24 \
    action vlan push id 100 pipe \
    action mirred egress mirror dev enp1s0f1

tc meter (committed/peak) HW 오프로드

Two-Rate Three-Color Marker(trTCM, RFC 2698)는 트래픽을 CIR(Committed Information Rate)과 PIR(Peak Information Rate)를 기준으로 Green/Yellow/Red 세 가지 색상으로 분류합니다. 이 분류 결과를 skb->priority에 반영하여 후속 QoS 스케줄링에 활용합니다.

trTCM 색상 분류

색상조건처리
GreenCIR 이내정상 전달, 최고 우선순위
YellowCIR 초과, PIR 이내혼잡 시 우선 드롭 대상
RedPIR 초과즉시 드롭 또는 재분류
# === Two-Rate Three-Color Marker HW 오프로드 ===

# CIR=1Gbps, CBS=64KB, PIR=2Gbps, PBS=128KB
tc filter add dev enp1s0f0 ingress protocol ip \
    flower skip_sw \
    src_ip 10.0.0.0/24 \
    action police rate 1gbit burst 64k \
        peakrate 2gbit mtu 128k \
        conform-exceed pipe/pipe pipe \
    action skbedit priority 1  # Green → 높은 우선순위

# Yellow 트래픽 재분류 (체인으로 분기)
# police exceed → pipe → 다음 action에서 priority 낮춤
tc filter add dev enp1s0f0 ingress protocol ip \
    flower skip_sw \
    src_ip 10.0.0.0/24 \
    action police rate 1gbit burst 64k \
        conform-exceed ok/pipe pipe \
    action skbedit priority 7  # Yellow → 낮은 우선순위

HTB/PRIO qdisc와 통합

# police 색상 분류 → PRIO qdisc로 계층적 QoS
# 이그레스에 PRIO qdisc 설정 (3개 밴드)
tc qdisc add dev enp1s0f0 root handle 1: prio bands 3

# 밴드별 rate 제한 (HTB)
tc qdisc add dev enp1s0f0 parent 1:1 handle 10: htb
tc class add dev enp1s0f0 parent 10: classid 10:1 htb rate 5gbit
tc qdisc add dev enp1s0f0 parent 1:2 handle 20: htb
tc class add dev enp1s0f0 parent 20: classid 20:1 htb rate 3gbit
tc qdisc add dev enp1s0f0 parent 1:3 handle 30: htb
tc class add dev enp1s0f0 parent 30: classid 30:1 htb rate 1gbit

# police에서 설정한 priority에 따라 밴드 매핑
# priority 1(Green) → 밴드 0(최고), 4(Yellow) → 밴드 1, 7(Red) → 밴드 2
커널 버전 참고: act_policepeakrate HW 오프로드는 커널 6.5 이상에서 안정적으로 지원됩니다. trTCM의 세 가지 색상을 모두 구분하려면 NIC 하드웨어가 dual-rate meter를 지원해야 합니다. 지원 여부는 ethtool -i로 드라이버 버전을 확인하고, 벤더 릴리스 노트를 참조합니다.

통합 예제: NGFW QoS + 모니터링 + 포워딩 파이프라인

앞서 소개한 모든 TC 액션을 결합하여, 하나의 TC flower 체인에서 NGFW의 QoS, 모니터링, 스테이트풀 방화벽, NAT, 포워딩을 모두 하드웨어에서 처리하는 완전한 파이프라인을 구성합니다.

파이프라인 구성: 인그레스 → 매치 → police → sample → ct → nat → mirred

# =============================================================
# 통합 NGFW HW 오프로드 파이프라인 (전체 skip_sw)
# =============================================================

# 0. 사전 설정
tc qdisc add dev enp1s0f0 ingress
tc qdisc add dev enp1s0f0_1 ingress   # VF1 representor

# =============================================================
# 1단계: chain 0 — 매치 + police(속도 제한) + sample(IDS) + CT 진입
# =============================================================
tc filter add dev enp1s0f0 ingress protocol ip \
    chain 0 prio 1 flower skip_sw \
    ip_proto tcp \
    src_ip 10.0.0.0/24 dst_ip 192.168.1.0/24 \
    dst_port 443 \
    action police rate 1gbit burst 64k \
        conform-exceed drop/pipe pipe \
    action sample rate 1000 group 1 trunc 128 pipe \
    action ct zone 1 nat pipe \
    action goto chain 1

# =============================================================
# 2단계: chain 1 — CT 상태 확인 + NAT + 포워딩
# =============================================================

# ESTABLISHED 세션: NAT 적용 후 VF1으로 리다이렉트
tc filter add dev enp1s0f0 ingress protocol ip \
    chain 1 prio 1 flower skip_sw \
    ct_state +trk+est \
    action mirred egress redirect dev enp1s0f0_1

# 새 연결(NEW): CT 커밋 + DNAT + 포워딩
tc filter add dev enp1s0f0 ingress protocol ip \
    chain 1 prio 10 flower skip_sw \
    ct_state +trk+new \
    ip_proto tcp dst_port 443 \
    action ct commit zone 1 \
        nat dst addr 192.168.1.10 port 8443 pipe \
    action mirred egress redirect dev enp1s0f0_1

# 허용되지 않은 트래픽: 차단
tc filter add dev enp1s0f0 ingress protocol ip \
    chain 1 prio 99 flower skip_sw \
    action drop

# =============================================================
# 3단계: 역방향 (VF1 → 외부)
# =============================================================
tc filter add dev enp1s0f0_1 ingress protocol ip \
    chain 0 flower skip_sw \
    ip_proto tcp ct_state -trk \
    action ct zone 1 nat pipe \
    action goto chain 1

tc filter add dev enp1s0f0_1 ingress protocol ip \
    chain 1 flower skip_sw \
    ct_state +trk+est \
    action mirred egress redirect dev enp1s0f0

오프로드 상태 검증

# === 규칙 설치 및 HW 통계 확인 ===

# 모든 규칙이 HW에 설치되었는지 확인 (in_hw 플래그)
tc -s filter show dev enp1s0f0 ingress
# 출력 예시:
# filter protocol ip pref 1 flower chain 0
#   in_hw in_hw_count 1
#   action order 1: police 0x1 rate 1Gbit burst 64Kb ...
#     Sent 892345678 bytes 5234567 pkt (hw: 892345678 bytes 5234567 pkt)
#   action order 2: sample rate 1/1000 group 1 trunc 128 ...
#     Sent 892345 bytes 5234 pkt (sampled)
#   action order 3: ct zone 1 nat pipe ...
#     Sent 892345678 bytes 5234567 pkt
#   action order 4: goto chain 1

# conntrack 오프로드 엔트리 확인
conntrack -L | grep zone=1 | head -5

# police 드롭 통계
tc -s actions ls action police
# 출력: police 0x1 ... drop 12345 overlimits 12345

# sample 통계
cat /proc/net/psample/groups

# 실시간 모니터링 (1초 간격)
watch -n 1 'tc -s filter show dev enp1s0f0 ingress chain 0'
액션 순서 주의: TC 액션 체인에서 액션의 순서가 매우 중요합니다. policesample보다 먼저 와야 rate limit을 초과한 패킷이 샘플링되지 않습니다. ctmirred보다 먼저 와야 커넥션 트래킹이 완료된 후 포워딩됩니다. 순서를 잘못 지정하면 보안 정책이 우회될 수 있습니다.

TC 액션 오프로드 파이프라인 다이어그램

아래 다이어그램은 TC 액션들이 하드웨어에서 처리되는 순서와 각 액션의 역할, 그리고 샘플 복제본이 별도의 모니터링 포트로 전달되는 경로를 보여줍니다.

TC 액션 HW 오프로드 파이프라인 (전체 skip_sw) Ingress Port RX TC flower 5-tuple Match act_police Rate Limit 1 Gbps / 64KB act_sample IDS Tap 1:1000 샘플 act_ct Conntrack Zone 1 act_nat NAT Rewrite DNAT / SNAT act_mirred Forward / Mirror Egress Port TX DROP (rate 초과) Monitoring Port IDS / sFlow 수집기 복제본 DROP (정책 거부) 범례: HW 포워딩 경로 (skip_sw) DROP 경로 (rate 초과 / 정책 거부) 샘플 복제본 → 모니터링 포트 모든 액션이 NIC ASIC에서 순차 실행 — CPU 개입 없이 라인 레이트 NGFW 처리
프로덕션 배포 팁: 통합 파이프라인 배포 시 단계적으로 규칙을 추가하는 것을 권장합니다. 먼저 skip_hw로 소프트웨어에서 정상 동작을 확인한 뒤, skip_sw로 변경하여 하드웨어 오프로드를 활성화합니다. tc -s filter showhw_stats를 실시간 모니터링하여 예상치 못한 동작을 빠르게 감지합니다.

대규모 규칙 관리

프로덕션 NGFW 환경에서는 수만~수십만 개의 ACL 규칙, 수백만 개의 conntrack 엔트리를 관리해야 합니다. 규칙 수가 증가할수록 삽입 지연, 메모리 사용량, 조회 성능이 달라지며, HW offload의 한계점도 드러납니다.

규칙 수에 따른 성능 특성 비교 Lookup 지연 (나노초) 1000 500 100 10 0 1K 10K 100K 1M 10M 규칙 수 HW TCAM HW Hash SW hash SW linear 규칙 삽입 시간 (초) 600 300 60 10 0 1K 10K 100K 1M 10M nft batch TC HW iptables NIC 하드웨어 규칙 용량 비교 NIC 모델 TCAM 규칙 CT 엔트리 NAT 엔트리 삽입 속도 Lookup CX-5 (25G) ~16K 1M 256K ~5K/s O(1) CX-6 Dx (100G) ~64K 4M 1M ~20K/s O(1) CX-7 (400G) ~128K 16M 4M ~50K/s O(1) Intel E810 ~8K 512K 128K ~3K/s O(1) BlueField-3 DPU ~256K 64M 16M ~100K/s O(1)

대규모 규칙 최적화 전략

전략설명적용 효과구현 방법
계층적 규칙 구조TC chain으로 다단계 매칭규칙 수 80% 감소chain 0→1→2 계층화
nftables set/mapIP 집합을 set으로 그룹화단일 규칙으로 수천 IP 매칭set allowlist { type ipv4_addr; flags interval; }
batch 업데이트규칙 추가/삭제 일괄 처리삽입 시간 10배 향상nft -f ruleset.nft
nftables concat복합 키로 멀티 필드 매칭규칙 수 대폭 감소ip saddr . tcp dport
HW 규칙 분할자주 매칭되는 규칙 우선 HWHW TCAM 효율 극대화상위 10% 규칙만 HW offload
CT 기반 offloadACL 대신 CT offload 사용ACL 규칙 수 무관첫 패킷만 ACL 검사
# nftables set 활용: 대규모 IP 목록 효율적 관리
nft add table inet firewall
nft add set inet firewall blocklist {
    type ipv4_addr\;
    flags interval\;
    auto-merge\;
}

# 블록리스트에 IP 범위 일괄 추가 (배치)
nft add element inet firewall blocklist {
    10.0.0.0/8,
    172.16.0.0/12,
    192.168.0.0/16,
    100.64.0.0/10
}

# set 참조 규칙: 단 1줄로 수천 개 IP 매칭
nft add rule inet firewall forward ip saddr @blocklist drop

# nftables concat: 복합 키 매칭
nft add set inet firewall svc_acl {
    type ipv4_addr . inet_service\;
}

nft add element inet firewall svc_acl {
    10.0.1.0/24 . 80,
    10.0.1.0/24 . 443,
    10.0.2.0/24 . 8080,
    10.0.3.0/24 . 5432
}

nft add rule inet firewall forward ip saddr . tcp dport @svc_acl accept

규칙 수 증가 시 성능 벤치마크

#!/bin/bash
# 대규모 규칙 삽입 벤치마크 스크립트

RULE_COUNTS="100 1000 10000 50000 100000"

for count in $RULE_COUNTS; do
    echo "=== Testing $count rules ==="

    # nftables batch 파일 생성
    echo "flush chain inet firewall test_chain" > /tmp/bench.nft
    for i in $(seq 1 $count); do
        oct3=$(( (i / 256) % 256 ))
        oct4=$(( i % 256 ))
        echo "add rule inet firewall test_chain ip saddr 10.${oct3}.${oct4}.0/24 accept" >> /tmp/bench.nft
    done

    # 삽입 시간 측정
    time_start=$(date +%s%N)
    nft -f /tmp/bench.nft
    time_end=$(date +%s%N)
    insert_ms=$(( (time_end - time_start) / 1000000 ))
    echo "Insert time: ${insert_ms}ms"

    # HW offload된 규칙 수 확인
    hw_rules=$(tc -s filter show dev eth0 ingress 2>/dev/null | grep -c "in_hw")
    echo "HW offloaded rules: $hw_rules"

    # Lookup 벤치마크 (iperf3로 처리량 측정)
    iperf3 -c 10.0.2.1 -t 5 -P 4 --json | jq '.end.sum_sent.bits_per_second'

    # 메모리 사용량
    echo "conntrack memory: $(cat /proc/slabinfo | grep nf_conntrack | awk '{print $3 * $4}')"

    nft flush chain inet firewall test_chain
done
HW TCAM 용량 초과 주의: TC flower HW offload 규칙이 NIC TCAM 용량을 초과하면 -ENOSPC 에러와 함께 SW fallback됩니다. 이때 dmesg에 "failed to offload rule" 메시지가 기록됩니다. 프로덕션에서는 ethtool -S eth0 | grep tc_offload로 HW 규칙 사용량을 모니터링하고, 80% 임계값에서 경보를 설정하세요.

NGFW offload 모니터링 및 통계 수집

NGFW offload 환경에서는 HW에서 처리되는 패킷이 기존 SW 카운터에 반영되지 않으므로, 전용 모니터링 체계가 필요합니다. ethtool, devlink trap, conntrack 이벤트, NIC 하드웨어 카운터를 조합하여 종합적인 가시성을 확보합니다.

NGFW Offload 모니터링 아키텍처 데이터 소스 계층 ethtool -S HW pkt/byte counters devlink trap exception packets conntrack event NEW/DESTROY/UPDATE TC flower stats per-rule HW counters debugfs/sysfs driver internals perf tracing 메트릭 수집 계층 node_exporter (custom) conntrack_exporter tc_exporter (custom) devlink_trap_exporter Prometheus TSDB, 15s scrape interval Grafana NGFW Offload Dashboard Alertmanager 임계값 경보 (Slack, PagerDuty) 핵심 메트릭: HW offload율 | CT 테이블 사용률 | TCAM 사용률 | exception 패킷율 | 규칙 삽입 실패율 | flow aging율

ethtool HW 카운터 수집

# Mellanox CX-6 HW offload 관련 카운터
ethtool -S enp3s0f0 | grep -E "offload|ct_|flow_"
# tx_vport_rdma_ucast_bytes: 0
# rx_steer_missed_packets: 0
# ct_offload_rx_packets: 15234567
# ct_offload_rx_bytes: 12345678901
# ct_offload_tx_packets: 14567890
# ct_offload_tx_bytes: 11234567890
# flow_table_hw_count: 45230
# flow_table_hw_max: 4000000
# flow_table_sw_count: 120
# tc_offload_rx_packets: 2345678
# tc_offload_tx_packets: 2234567

# Intel E810 HW 카운터
ethtool -S eth0 | grep -E "fdir|offload"
# fdir_match: 1234567
# fdir_miss: 456
# fdir_sb_match: 234567
# rx_hw_offload_packets: 9876543

# 주기적 수집 스크립트 (Prometheus 텍스트 형식)
cat << 'SCRIPT' > /usr/local/bin/ngfw-metrics.sh
#!/bin/bash
IFACE="${1:-enp3s0f0}"
PREFIX="ngfw_offload"

ct_rx_pkts=$(ethtool -S $IFACE 2>/dev/null | awk '/ct_offload_rx_packets/ {print $2}')
ct_tx_pkts=$(ethtool -S $IFACE 2>/dev/null | awk '/ct_offload_tx_packets/ {print $2}')
hw_flows=$(ethtool -S $IFACE 2>/dev/null | awk '/flow_table_hw_count/ {print $2}')
hw_max=$(ethtool -S $IFACE 2>/dev/null | awk '/flow_table_hw_max/ {print $2}')
sw_flows=$(ethtool -S $IFACE 2>/dev/null | awk '/flow_table_sw_count/ {print $2}')

# conntrack 통계
ct_total=$(conntrack -C 2>/dev/null || echo 0)
ct_max=$(sysctl -n net.netfilter.nf_conntrack_max 2>/dev/null || echo 0)
ct_offloaded=$(conntrack -L 2>/dev/null | grep -c "\[OFFLOAD\]" || echo 0)

echo "# HELP ${PREFIX}_ct_rx_packets CT offloaded RX packets"
echo "# TYPE ${PREFIX}_ct_rx_packets counter"
echo "${PREFIX}_ct_rx_packets{iface=\"$IFACE\"} ${ct_rx_pkts:-0}"

echo "# HELP ${PREFIX}_ct_tx_packets CT offloaded TX packets"
echo "# TYPE ${PREFIX}_ct_tx_packets counter"
echo "${PREFIX}_ct_tx_packets{iface=\"$IFACE\"} ${ct_tx_pkts:-0}"

echo "# HELP ${PREFIX}_hw_flows Current HW flow entries"
echo "# TYPE ${PREFIX}_hw_flows gauge"
echo "${PREFIX}_hw_flows{iface=\"$IFACE\"} ${hw_flows:-0}"

echo "# HELP ${PREFIX}_hw_flows_max Maximum HW flow entries"
echo "# TYPE ${PREFIX}_hw_flows_max gauge"
echo "${PREFIX}_hw_flows_max{iface=\"$IFACE\"} ${hw_max:-0}"

echo "# HELP ${PREFIX}_conntrack_total Total conntrack entries"
echo "# TYPE ${PREFIX}_conntrack_total gauge"
echo "${PREFIX}_conntrack_total ${ct_total}"

echo "# HELP ${PREFIX}_conntrack_offloaded Offloaded conntrack entries"
echo "# TYPE ${PREFIX}_conntrack_offloaded gauge"
echo "${PREFIX}_conntrack_offloaded ${ct_offloaded}"

# Offload 비율 계산
if [ "$ct_total" -gt 0 ]; then
    offload_ratio=$(echo "scale=4; $ct_offloaded / $ct_total" | bc)
else
    offload_ratio=0
fi
echo "# HELP ${PREFIX}_offload_ratio Ratio of offloaded connections"
echo "# TYPE ${PREFIX}_offload_ratio gauge"
echo "${PREFIX}_offload_ratio $offload_ratio"
SCRIPT
chmod +x /usr/local/bin/ngfw-metrics.sh

devlink trap 모니터링

# devlink trap: HW에서 SW로 전달된 예외 패킷 모니터링
devlink trap show pci/0000:03:00.0

# 특정 trap 그룹 통계
devlink trap group show pci/0000:03:00.0 group l2_drops
devlink trap group show pci/0000:03:00.0 group l3_drops
devlink trap group show pci/0000:03:00.0 group acl_drops

# trap 카운터 (패킷 수)
devlink trap show pci/0000:03:00.0 trap source_mac_is_multicast
# pci/0000:03:00.0:
#   name source_mac_is_multicast type drop
#   generic true action drop group l2_drops
#   stats:
#     rx:
#       bytes 0 packets 0

# 실시간 trap 모니터링 (tcpdump처럼)
devlink trap set pci/0000:03:00.0 trap ingress_flow_action_drop action trap
# → 캡처된 패킷이 devlink trap policer를 통해 CPU로 전달

# trap policer 설정 (CPU 보호)
devlink trap policer set pci/0000:03:00.0 policer 1 rate 1000 burst 128

# 주기적 trap 통계 수집
watch -n 5 'devlink -s trap show pci/0000:03:00.0 | grep -E "packets [1-9]"'

핵심 경보 규칙

메트릭임계값심각도설명
HW flow 사용률> 80%WarningTCAM/hash 테이블 용량 부족 예고
HW flow 사용률> 95%CriticalSW fallback 발생, 성능 급감
CT offload 비율< 70%Warning대부분 세션이 SW 처리 중
devlink trap 패킷율> 10K/sWarningexception 경로 과부하
conntrack 테이블> 90%Critical새 연결 거부 위험
TC 규칙 삽입 실패> 0WarningHW offload 실패 (용량/미지원)
flow aging 급증전일 대비 2xInfo트래픽 패턴 변화 감지

벤더별 offload 지원 현황 비교

NGFW 하드웨어 오프로드 지원 수준은 NIC 벤더와 모델에 따라 크게 다릅니다. 이 섹션에서는 주요 벤더별 오프로드 기능 매트릭스, 드라이버 성숙도, 커널 버전 요구사항을 비교합니다.

벤더별 NGFW Offload 기능 매트릭스 기능 NVIDIA/Mellanox CX-5/6/7, BF-2/3 Intel E810, IPU (Mt. Evans) Broadcom BCM5760X, Stingray Netronome Agilio CX (nfp) Marvell Prestera, OCTEON TC flower offload CT HW offload NAT offload flowtable HW offload eSwitch switchdev OVS TC offload tunnel (VXLAN) offload IPsec crypto offload devlink trap DPU/SmartNIC BlueField-3 Mt. Evans IPU Stingray PS1100R OCTEON 10 ● 완전 지원 ◐ 부분 지원 / 제한적 ○ 미지원 기준: Linux 커널 6.6 LTS (2024)

NVIDIA/Mellanox 상세

NVIDIA/Mellanox ConnectX 시리즈는 Linux 커널 NGFW offload에서 가장 성숙한 에코시스템을 제공합니다. mlx5 드라이버가 upstream 커널에 포함되어 있으며, TC flower, CT offload, NAT offload, OVS offload를 모두 지원합니다.

모델대역폭CT 엔트리TCAM 규칙최소 커널주요 기능
CX-525/100G1M16K4.19TC flower, switchdev, flowtable
CX-6 Dx25/100G4M64K5.7+ CT offload, NAT offload
CX-6 Lx25G1M16K5.7CX-6 Dx 기능 서브셋
CX-7400G16M128K6.2+ enhanced steering, crypto
BlueField-2100G4M64K5.11+ ARM SoC, 전용 OS
BlueField-3400G64M256K6.2+ 16 ARM cores, crypto

Intel 상세

모델대역폭CT 엔트리TCAM 규칙최소 커널주요 기능
E810 (ice)25/100G512K8K5.9TC flower, switchdev, ADQ
E810 + ACC100100G512K8K5.14+ FEC offload
E830 (예정)200G2M32K6.8++ enhanced CT, tunnel
IPU (Mt. Evans)200GTBDTBDTBDIDPF driver, P4 pipeline
벤더 선택 가이드:
  • NGFW 전용 (최대 기능): NVIDIA CX-6 Dx / CX-7 — CT, NAT, OVS offload 모두 지원
  • DPU 기반 (최대 유연성): NVIDIA BlueField-3 — ARM에서 커스텀 파이프라인 실행
  • 가성비 (기본 offload): Intel E810 — flowtable + 기본 TC flower
  • Broadcom/Marvell: 스위치 ASIC 기반 offload에 강점, Linux 드라이버 성숙도는 상대적으로 낮음

커널 6.x NGFW offload 최신 변경사항

Linux 커널 6.x 시리즈에서는 NGFW offload 관련 기능이 대폭 확장되었습니다. CT offload 성능 개선, 새로운 offload 경로, eBPF 기반 확장 등 주요 변경사항을 정리합니다.

커널 버전변경사항영향관련 서브시스템
6.0nf_conntrack 성능 개선: per-CPU hash resizeconntrack 삽입 성능 40% 향상nf_conntrack
6.1flowtable tunnel offload (VXLAN, Geneve)터널 트래픽 HW offload 가능nf_flow_table, mlx5
6.1TC flower ct action NAT 포트 범위NAPT 오프로드 범위 확대act_ct
6.2mlx5 CX-7 steering 아키텍처 (HWS)규칙 삽입 속도 5배 향상mlx5_core
6.2nftables flowtable counter offloadHW 패킷 카운터를 flowtable에 반영nf_flow_table
6.3TC flower police action HW offloadQoS rate limiting을 HW에서 처리act_police, mlx5
6.4CT timeout policy offload프로토콜별 HW 타임아웃 설정act_ct, nf_conntrack
6.5flowtable priority 지원멀티 flowtable 우선순위 제어nf_flow_table
6.5mlx5 connection tracking 스케일 개선CT offload 엔트리 16M+ 지원mlx5_core
6.6 LTSice driver switchdev CT offloadIntel E810 CT 오프로드 지원ice
6.7nftables inner header match offload터널 내부 패킷 매칭 HW offloadnf_tables, mlx5
6.8TC flower sample action offloadHW에서 패킷 샘플링 (sFlow/NetFlow)act_sample, mlx5
6.9WQ_BH workqueue (softirq 대체)네트워크 스택 지연 감소workqueue, net
6.10nf_flow_table GRO 연동 개선offload 경로에서 GRO 활용nf_flow_table
6.11TC flower ct action mark offloadCT mark를 HW에서 설정/매칭act_ct, mlx5
6.12mlx5 enhanced connection tracking v2CT miss 시 SW fallback 성능 개선mlx5_core

주요 변경사항 상세

커널 6.1: flowtable tunnel offload

# 커널 6.1+에서 VXLAN 터널 트래픽을 flowtable HW offload 가능
table inet firewall {
    flowtable ft {
        hook ingress priority 0
        devices = { eth0, vxlan0 }  # ← VXLAN 인터페이스 포함
        flags offload
    }

    chain forward {
        type filter hook forward priority filter; policy drop;
        # VXLAN 터널을 통한 세션도 HW offload됨
        ct state established,related flow add @ft accept
        # ... (나머지 규칙)
    }
}

커널 6.2: mlx5 HWS (Hardware Steering)

# mlx5 CX-7 HWS 모드 활성화 (기본값은 FWS)
# HWS: 규칙 삽입 50K/s 이상 (FWS 대비 5배)
devlink dev param set pci/0000:03:00.0 name flow_steering_mode \
    value "hmfs" cmode runtime

# HWS 모드 확인
devlink dev param show pci/0000:03:00.0 name flow_steering_mode
# pci/0000:03:00.0:
#   name flow_steering_mode type generic
#   values:
#     cmode runtime value hmfs

커널 6.5: CT 스케일 개선

# CT offload 엔트리 수 확인 (CX-7)
cat /sys/kernel/debug/mlx5/0000:03:00.0/ct/stats
# max_ct_entries: 16777216    ← 16M
# active_ct_entries: 4523120  ← 현재 활성
# ct_insert_rate: 45230/s
# ct_delete_rate: 42100/s
# ct_miss_to_sw: 12/s

# 성능 비교 (커널 6.4 vs 6.5, CX-7)
# 6.4: CT insert ~10K/s, max 4M entries
# 6.5: CT insert ~50K/s, max 16M entries
# (connection rate 5x 향상)

커널 6.8: TC sample action offload

# HW에서 직접 패킷 샘플링 (sFlow 용도)
# CPU를 거치지 않고 NIC에서 1/1000 비율로 샘플링

tc filter add dev enp3s0f0 ingress prio 1 proto ip flower \
    skip_sw \
    action sample rate 1000 group 1 trunc 128 \
    action mirred egress redirect dev enp3s0f0_0

# psample 수신 (sFlow collector에서 활용)
# psample: group=1, seq=12345, iif=3, orig_size=1500, data=...

# 기존 방법 (SW): CPU에서 모든 패킷을 보고 1/N을 추출
# 새 방법 (HW): NIC가 직접 샘플링 → CPU 부하 0
커널 버전 선택 권장사항:
  • 프로덕션 (보수적): 커널 6.6 LTS — CT offload + flowtable tunnel + 충분한 안정성
  • 고성능 NGFW: 커널 6.8+ — sample offload + police offload + CT mark offload
  • CX-7 / BlueField-3: 커널 6.2+ 필수 — HWS steering 지원
  • Intel E810: 커널 6.6+ 권장 — ice switchdev CT offload 안정화

멀티 클러스터 NGFW offload 연동

Kubernetes 멀티 클러스터 환경에서 NGFW offload를 활용하려면 CNI 플러그인, Service Mesh, Network Policy를 HW offload와 통합해야 합니다. 이 섹션에서는 대표적인 아키텍처 패턴과 구현 방법을 다룹니다.

Kubernetes CNI + NGFW offload 아키텍처

CNI 플러그인HW offload 지원NGFW 연동 방법비고
OVN-KubernetesOVS TC offloadNetworkPolicy → OVS OpenFlow → TC flower HWNVIDIA 공식 지원
CiliumeBPF offloadCiliumNetworkPolicy → eBPF → XDP HW offloadNetronome nfp 지원
CalicoeBPF dataplaneGlobalNetworkPolicy → eBPF TC → HW (제한적)XDP offload 개발 중
SR-IOV CNIVF representorPod VF → eSwitch TC flower → HW ACLSRIOV + switchdev 필수
AntreaOVS TC offloadAntreaPolicy → OVS → TC flower HWVMware 주도
# Kubernetes NetworkPolicy → HW offload 예시 (OVN-Kubernetes)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: web-tier-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      tier: web
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          role: loadbalancer
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 443
  egress:
  - to:
    - podSelector:
        matchLabels:
          tier: app
    ports:
    - protocol: TCP
      port: 8080
  # OVN-Kubernetes가 이 정책을 OpenFlow → TC flower → HW offload로 변환
  # Pod VF representor에 eSwitch FDB 규칙 자동 설치
# OVN-Kubernetes HW offload 활성화 확인
kubectl -n ovn-kubernetes get configmap ovn-config -o yaml | grep hw-offload
# hw-offload: "true"

# Pod의 VF representor에 설치된 HW 규칙 확인
# (노드에서 실행)
tc -s filter show dev enp3s0f0_2 ingress  # Pod의 VF rep
# filter protocol ip pref 100 flower chain 1
#   ct_state +established+tracked
#   in_hw in_hw_count 1
#   action order 1: mirred (Egress Redirect to device enp3s0f0_3)

# HW offload된 NetworkPolicy 확인 (OVN northd)
ovn-nbctl list ACL | grep "hw_offload"

고가용성(HA) NGFW offload

NGFW offload 환경에서 HA(고가용성)를 구현할 때, HW에 설치된 flow 엔트리의 동기화가 가장 큰 과제입니다. Active-Standby 및 Active-Active 구성별 세션 동기화 전략을 다룹니다.

HA 모드별 offload 동기화

HA 모드세션 동기화HW flow 처리failover 시간제약사항
Active-Standbyconntrackd FTFWStandby: SW only, failover 시 HW re-offload2-5초 (HW re-install)failover 중 일시적 성능 저하
Active-Active (ECMP)conntrackd + flow hash양쪽 모두 HW offload, hash 기반 분산<1초 (hash rehash)비대칭 트래픽 처리 복잡
Active-Active (bonding)conntrackd 양방향양쪽 NIC에 동일 HW flow<1초bond 모드 제약 (mode 4)
Cluster (3+ 노드)conntrackd multicast각 노드 독립 HW offload2-10초대역폭 제한, 동기화 지연
# conntrackd HA 구성: HW offload 환경 최적화
cat /etc/conntrackd/conntrackd.conf
Sync {
    Mode FTFW {
        DisableExternalCache Off
        CommitTimeout 1800
        PurgeTimeout 5
    }

    # HW offload된 엔트리도 동기화 대상에 포함
    # (OFFLOAD 상태의 conntrack 엔트리는 주기적으로 SW에 stats 동기화)

    Multicast {
        IPv4_address 225.0.0.50
        Group 3780
        IPv4_interface 10.0.0.1
        Interface eth2
        SndSocketBuffer 1249280
        RcvSocketBuffer 1249280
        Checksum on
    }
}

General {
    Nice -20
    # 1M conntrack 엔트리 동기화 시 메모리
    HashSize 524288
    HashLimit 1048576

    # HW offload 엔트리 필터: offload 상태도 동기화
    Filter From Kernelspace {
        Protocol Accept {
            TCP
            UDP
            ICMP
        }
        Address Ignore {
            IPv4_address 127.0.0.1
        }
    }

    # Failover 시 HW flow re-install 스크립트
    EventIterationLimit 200
}

# Failover 스크립트: HW flow 재설치
cat /etc/conntrackd/primary-backup.sh
#!/bin/bash
case "$1" in
    primary)
        conntrackd -c
        conntrackd -f
        conntrackd -R
        # HW offload 재활성화
        nft flush flowtable inet firewall ft
        nft add flowtable inet firewall ft \
            { hook ingress priority 0\; devices = { eth0, eth1 }\; flags offload\; }
        logger "NGFW HA: Primary role - HW offload re-enabled"
        ;;
    backup)
        conntrackd -t
        # Standby에서는 SW flowtable만 유지 (HW 리소스 절약)
        nft delete flowtable inet firewall ft 2>/dev/null
        nft add flowtable inet firewall ft \
            { hook ingress priority 0\; devices = { eth0, eth1 }\; }
        logger "NGFW HA: Backup role - SW flowtable only"
        ;;
    fault)
        conntrackd -t
        logger "NGFW HA: Fault state"
        ;;
esac
HA failover 시 HW flow 재설치 지연: Active-Standby failover 시 Standby 노드의 NIC에 수백만 개의 HW flow를 재설치하는 데 수 초~수십 초가 소요될 수 있습니다. 이 기간 동안 모든 트래픽은 SW flowtable/Netfilter 경로로 처리됩니다. failover 직후 일시적 CPU 스파이크에 대비하여 CPU headroom을 20% 이상 확보하세요.

NGFW offload 트러블슈팅

NGFW offload 문제는 HW/SW/드라이버의 복합적 상호작용에서 발생합니다. 이 섹션에서는 실전에서 자주 겪는 문제와 체계적 디버깅 방법을 제공합니다.

트러블슈팅 의사결정 트리

NGFW Offload 트러블슈팅 의사결정 트리 성능 문제 / offload 실패 hw-tc-offload on 인가? ethtool -K ethX hw-tc-offload on No Yes eSwitch switchdev 모드? devlink dev eswitch set mode switchdev No Yes tc filter에 in_hw 표시? dmesg 확인: TCAM full → 규칙 축소 unsupported → 규칙 변경 No Yes 처리량이 line-rate 미달? 원인 분석: 1. conntrack -L | grep -v OFFLOAD → SW flow 확인 2. ethtool -S | grep miss → cache miss 확인 3. perf top → CPU 병목 확인 Yes 정상 동작 확인 완료 No 간헐적 세션 끊김 발생? HW/SW 타임아웃 불일치 확인: 1. HW aging < TCP keepalive? 2. conntrackd 동기화 지연? Yes 고급 디버깅: ftrace nf_flow_offload* devlink trap monitoring No

자주 발생하는 문제와 해결

증상원인진단 명령해결 방법
TC filter에 in_hw 미표시NIC가 해당 규칙 타입 미지원dmesg | grep "offload"지원되는 match/action 조합으로 변경
간헐적 패킷 드롭TCAM 용량 초과 → 일부 규칙 SW fallbackethtool -S eth0 | grep tc_offload_fail규칙 수 축소 또는 CT offload 방식 전환
conntrack 테이블 가득 참HW offload 엔트리도 SW 테이블 점유conntrack -C vs nf_conntrack_maxsysctl nf_conntrack_max 증가
HW offload 후 카운터 0정상 (HW에서 처리)ethtool -S의 HW 카운터 확인ethtool/debugfs 카운터 사용
HA failover 시 긴 끊김HW flow 재설치 지연time nft list flowtablefailover 스크립트에 SW flowtable 선행 활성화
NAT offload 실패NAT + CT 복합 offload 미지원dmesg | grep "nat offload"CX-6 Dx 이상 사용 또는 SW NAT fallback
OVS flow offload 부분만 동작tc-policy=skip_sw 미설정ovs-vsctl get Open_vSwitch . other_configtc-policy=skip_sw 설정 후 OVS 재시작(Reboot)
# 종합 진단 스크립트
#!/bin/bash
echo "=== NGFW Offload 진단 ==="
IFACE="${1:-enp3s0f0}"

echo ""
echo "1. HW TC offload 상태:"
ethtool -k $IFACE | grep "hw-tc-offload"

echo ""
echo "2. eSwitch 모드:"
devlink dev eswitch show pci/$(ethtool -i $IFACE | awk '/bus-info/ {print $2}') 2>/dev/null

echo ""
echo "3. TC flower HW 규칙 수:"
tc -s filter show dev $IFACE ingress 2>/dev/null | grep -c "in_hw"

echo ""
echo "4. Conntrack 상태:"
echo "  Total: $(conntrack -C)"
echo "  Max: $(sysctl -n net.netfilter.nf_conntrack_max)"
echo "  Offloaded: $(conntrack -L 2>/dev/null | grep -c '\[OFFLOAD\]')"

echo ""
echo "5. HW 카운터:"
ethtool -S $IFACE 2>/dev/null | grep -E "ct_offload|flow_table|tc_offload" | head -10

echo ""
echo "6. 최근 offload 관련 커널 메시지:"
dmesg | grep -iE "offload|flower|flow_table|eswitch" | tail -10

echo ""
echo "7. devlink trap 통계 (drop 항목):"
devlink -s trap show pci/$(ethtool -i $IFACE | awk '/bus-info/ {print $2}') 2>/dev/null | \
    grep -A2 "type drop" | grep "packets [1-9]" | head -5

echo ""
echo "=== 진단 완료 ==="

참고자료

커널 공식 문서

벤더 기술 문서

DPI/IPS 엔진

표준/벤치마크

고가용성/운영

커널 소스 경로

다음 학습: