NGFW 암/복호화 HW 오프로드
NGFW 암/복호화 HW 오프로드 심층 가이드: kTLS HW 오프로드, IPSec crypto/packet/full 모드, MACsec 오프로드, Intel QAT/Marvell NITROX 크립토 가속기, SSL/TLS Inspection 파이프라인, 암호화 기술별 아키텍처 매핑, 알고리즘 지원 매트릭스, 통합 구성 예제
- NGFW 하드웨어 오프로드 — 3대 오프로드 아키텍처, Fast/Slow/Exception 경로, Stateful 방화벽 오프로드
- Netfilter — 리눅스 커널 패킷 필터링 프레임워크
- Netfilter Flowtable — SW/HW 오프로드 메커니즘
NGFW에서 암호화 트래픽(Encrypted Traffic) 처리는 가장 CPU 집약적인 작업입니다. TLS 1.3 시대에 전체 웹 트래픽의 95% 이상이 암호화되어 있으며, NGFW는 이 트래픽을 복호화 → 검사(DPI/IPS) → 재암호화하거나, 암호화 상태로 메타데이터 기반 분류를 수행해야 합니다. 이 문서에서는 NIC/SmartNIC/전용 ASIC에서 암·복호화를 하드웨어로 오프로드하는 모든 방식을 심층 분석합니다.
암호화 기술별 아키텍처 매핑
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 (레거시) | 지원 | 지원 | 지원 | 미지원 | 미지원 |
암호화 파이프라인 단계와 레이턴시
AES-256-GCM 암호화 한 패킷의 처리를 단계별로 분해하면, 각 아키텍처에서 병목이 되는 지점이 어디인지 명확해집니다. 아래 다이어그램은 1,400바이트 페이로드(일반 MTU) 기준의 처리 단계를 보여줍니다.
핵심 인사이트: 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 Encrypt | 2~8 Gbps/core | NIC 라인레이트 | 100~200 Gbps | 모델별 (50~100 Gbps) |
| AES-256-GCM Decrypt | 2~8 Gbps/core | NIC 라인레이트 | 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-Poly1305 | 3~10 Gbps/core | 일부 NIC 지원 | 지원 | 벤더별 |
| 전력 효율 (Gbps/W) | 0.1~0.3 | 1~5 | 2~10 | 벤더 최적화 |
kTLS (Kernel TLS) HW 오프로드
kTLS(Kernel TLS)는 TLS 레코드 계층(record layer)의 암·복호화를 커널에서 수행하는 메커니즘입니다. 유저스페이스 TLS 라이브러리(OpenSSL, GnuTLS)가 핸드셰이크를 완료하면, 대칭키와 암호화 파라미터를 setsockopt(SOL_TLS)로 커널에 전달합니다. 이후 데이터 전송은 커널이 직접 TLS 레코드를 구성하고, NIC이 인라인 암호화를 수행합니다.
kTLS의 하이브리드 아키텍처
kTLS는 단일 아키텍처가 아닌 하이브리드입니다. TLS 프로토콜의 두 단계(핸드셰이크와 레코드 전송)가 서로 다른 아키텍처에서 처리됩니다.
- 핸드셰이크 단계 (RSA/ECDHE 비대칭키): CPU에서 실행 — QAT Lookaside로 가속 가능
- 레코드 전송 단계 (AES-GCM 대칭키): NIC 인라인에서 실행 — 호스트 메모리 우회, 라인레이트
이 하이브리드 구조가 중요한 이유는 CPS 병목(핸드셰이크)과 처리량 병목(레코드 전송)을 각각 최적의 아키텍처로 해결하기 때문입니다.
kTLS 동작 모드
| 모드 | 암호화 위치 | TLS 헤더 | sendfile() 지원 | 성능 | NIC 요구 |
|---|---|---|---|---|---|
| SW kTLS | 커널 (crypto API) | 커널 구성 | 지원 (zero-copy) | 3~10 Gbps/core | 없음 |
| HW TX offload | NIC (송신) | 커널 구성 | 지원 | NIC 라인레이트 | tls-hw-tx-offload |
| HW RX offload | NIC (수신) | NIC 파싱 | - | NIC 라인레이트 | tls-hw-rx-offload |
| HW Full offload | NIC (양방향) | 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 부담을 제거합니다.
- 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 NIC 호환성
| NIC | TX offload | RX offload | TLS 1.2 | TLS 1.3 | AES-128-GCM | AES-256-GCM | 최대 연결 수 | 커널 최소 버전 |
|---|---|---|---|---|---|---|---|---|
| NVIDIA CX-6 Dx | 지원 | 지원 | 지원 | 지원 | 지원 | 지원 | ~1M | 5.3+ (TX), 5.9+ (RX) |
| NVIDIA CX-7 | 지원 | 지원 | 지원 | 지원 | 지원 | 지원 | ~4M | 5.3+ |
| NVIDIA BlueField-3 | 지원 | 지원 | 지원 | 지원 | 지원 | 지원 | DPU 메모리 의존 | 5.3+ |
| Intel E810 | 지원 | 미지원 | 지원 | 지원 (6.1+) | 지원 | 지원 | ~16K | 5.14+ |
| Broadcom P2100 | 제한적 | 미지원 | 지원 | 미지원 | 지원 | 미지원 | ~8K | 5.17+ |
| Marvell LiquidIO | 지원 | 지원 | 지원 | 미지원 | 지원 | 지원 | ~32K | 5.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 라인레이트 | 거의 없음 |
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 offload NIC 호환성 매트릭스
| 기능 | NVIDIA CX-6 Dx | NVIDIA CX-7 | NVIDIA BF-3 | Intel E810 | Marvell 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의 관계
- 데이터센터 내부 보안: 서버 간 East-West 트래픽을 L2에서 암호화. NGFW는 MACsec 복호화 후 L3/L4 검사 수행
- Zero Trust 네트워크: 모든 L2 세그먼트에서 암호화를 기본 적용하고, NGFW가 복호화된 트래픽만 검사
- HW offload 필수: MACsec 암·복호화가 SW면 라인레이트 불가. NIC HW offload로 성능 유지
# 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 지원 현황
| NIC | MACsec HW offload | GCM-AES-128 | GCM-AES-256 | XPN (Extended PN) | 최대 SC 수 | 커널 최소 |
|---|---|---|---|---|---|---|
| NVIDIA CX-6 Dx | 지원 | 지원 | 지원 | 지원 (6.6+) | ~128 | 5.12+ |
| NVIDIA CX-7 | 지원 | 지원 | 지원 | 지원 | ~256 | 5.12+ |
| Intel E810 | 미지원 | - | - | - | - | - |
| Microchip VSC7558 | 지원 (switchdev) | 지원 | 지원 | 미지원 | ~64 | 5.7+ |
| Marvell CN10K | 지원 | 지원 | 지원 | 지원 | ~512 | 6.1+ |
MACsec 프레임 구조
MACsec는 이더넷 프레임에 SecTAG(Security Tag)와 ICV(Integrity Check Value)를 추가합니다. SecTAG는 EtherType 0x88E5로 식별되며, 원본 이더넷 페이로드 전체가 AES-GCM으로 암호화됩니다.
| 필드 | 크기 | 설명 | HW offload 처리 |
|---|---|---|---|
| DA + SA | 12B | 목적지/출발지 MAC (평문 유지) | NIC이 그대로 전달 |
| SecTAG | 8~16B | EtherType(0x88E5) + TCI/AN + SL + PN [+ SCI] | NIC이 삽입/제거 |
| Secure Data | 가변 | 원본 EtherType + 페이로드 (AES-GCM 암호화) | NIC HW 암·복호화 |
| ICV | 8~16B | GCM 인증 태그 (무결성 검증) | NIC HW 검증/생성 |
| FCS | 4B | 새 Frame Check Sequence | NIC 재계산 |
MACsec 프레임 구조 (IEEE 802.1AE)
일반 이더넷:
┌──────┬──────┬──────────┬──────────────────────────┬─────┐
│ DA │ SA │ EthType │ Payload │ FCS │
│ 6B │ 6B │ 2B │ 46~1500B │ 4B │
└──────┴──────┴──────────┴──────────────────────────┴─────┘
MACsec 프레임:
┌──────┬──────┬──────────────────┬──────────────────────┬──────┬─────┐
│ DA │ SA │ SecTAG │ Secure Data │ ICV │ FCS │
│ 6B │ 6B │ 8~16B │ (암호화된 페이로드) │8~16B │ 4B │
│ │ │ ┌─────────────┐ │ ┌────────────────┐ │ │ │
│ │ │ │EType=0x88E5 │ │ │원본 EthType │ │ │ │
│ │ │ │TCI/AN│SL│PN │ │ │+ 원본 Payload │ │ │ │
│ │ │ │[SCI 8B opt] │ │ │(AES-GCM 암호화)│ │ │ │
│ │ │ └─────────────┘ │ └────────────────┘ │ │ │
└──────┴──────┴──────────────────┴──────────────────────┴──────┴─────┘
평문 유지 암호화 영역 인증
- TCI (Tag Control Information): V(버전) + ES(End Station) + SC(SCI 포함 여부) + SCB + E(암호화) + C(변경됨) 비트
- AN (Association Number): 2비트, 키 롤오버 시 새 SA 식별 (0~3 순환)
- SL (Short Length): 페이로드가 48바이트 미만일 때 실제 길이 표시
- PN (Packet Number): 32비트 (기본) 또는 64비트 (XPN), anti-replay 검사에 사용
- SCI (Secure Channel Identifier): 8바이트, 출발지 MAC + 포트 식별자 (선택적)
MKA (MACsec Key Agreement) 프로토콜
MACsec의 키 교환은 MKA(MACsec Key Agreement, IEEE 802.1X-2020) 프로토콜이 담당합니다. MKA는 EAP(802.1X) 인증 후 CAK(Connectivity Association Key)를 공유하고, 이로부터 세션키(SAK)를 파생합니다.
| 키 계층 | 설명 | 수명 | 생성 주체 |
|---|---|---|---|
| CAK (Connectivity Association Key) | 마스터 키, EAP 인증 또는 수동 설정으로 생성 | 장기 (수일~영구) | RADIUS/수동 |
| CKN (CAK Name) | CAK 식별자, MKA 피어 간 CAK 매칭에 사용 | CAK와 동일 | RADIUS/수동 |
| KEK (Key Encrypting Key) | CAK에서 파생, SAK 배포 시 암호화에 사용 | CAK 변경 시 재생성 | KDF(CAK) |
| ICK (Integrity Check Key) | CAK에서 파생, MKA PDU 무결성 검증 | CAK 변경 시 재생성 | KDF(CAK) |
| SAK (Secure Association Key) | 실제 MACsec 암호화에 사용되는 세션 키 | 단기 (PN 소진 또는 정책) | Key Server 파생 |
# MKA + MACsec HW offload 설정 (wpa_supplicant 기반)
# /etc/wpa_supplicant/macsec.conf
# Pre-shared CAK/CKN 방식 (정적 키)
cat << 'EOF' > /etc/wpa_supplicant/macsec.conf
ctrl_interface=/var/run/wpa_supplicant
eapol_version=3
network={
key_mgmt=NONE
eapol_flags=0
# MKA 설정
mka_cak=0011223344556677889900aabbccddeeff
mka_ckn=0011223344556677889900aabbccddeeff00112233445566778899
mka_priority=100 # Key Server 선출 우선순위 (낮을수록 우선)
# MACsec 정책
macsec_policy=1 # 1=보호 필수 (MACsec 미지원 피어 차단)
macsec_integ_only=0 # 0=암호화+무결성, 1=무결성만
macsec_replay_protect=1 # anti-replay 활성화
macsec_replay_window=0 # replay 윈도우 (0=strict)
macsec_port=1 # SCI 포트 번호
# HW offload 설정
macsec_offload=1 # 0=SW, 1=MAC offload, 2=PHY offload
}
EOF
# wpa_supplicant 시작 (MKA 세션 수립)
wpa_supplicant -i eth0 -D macsec_linux -c /etc/wpa_supplicant/macsec.conf -B
# MKA 세션 상태 확인
wpa_cli -i eth0 status
# wpa_state=COMPLETED
# macsec_policy=SHOULD_SECURE
# Authenticated=TRUE
# Secured=TRUE
# Port_Valid=TRUE
# MACsec 인터페이스 자동 생성 확인
ip link show type macsec
# macsec0: ... state UP
# macsec sci ff:ff:ff:ff:ff:ff:00:01 protect on encrypt on
# offload mac
# MKA 통계
wpa_cli -i eth0 mka_stats
# MKA_DISTRIBUTED_SAK=5
# MKA_LATEST_SAK_PN=1
MACsec 커널 내부 처리 경로
/* drivers/net/macsec.c — MACsec HW offload 등록 및 처리 흐름 */
/* 1. MACsec offload 인터페이스 등록 */
static const struct macsec_ops *macsec_get_ops(struct net_device *dev,
enum macsec_offload offload)
{
/* offload == MACSEC_OFFLOAD_MAC → NIC 드라이버의 macsec_ops 사용 */
/* offload == MACSEC_OFFLOAD_PHY → PHY 드라이버의 macsec_ops 사용 */
if (offload == MACSEC_OFFLOAD_MAC)
return dev->macsec_ops;
else if (offload == MACSEC_OFFLOAD_PHY)
return dev->phydev ? dev->phydev->macsec_ops : NULL;
return NULL;
}
/* 2. SA 추가 시 HW offload 경로 */
static int macsec_add_txsa(struct sk_buff *skb,
struct genl_info *info)
{
const struct macsec_ops *ops = macsec_get_ops(dev, offload);
/* HW offload인 경우 NIC 드라이버에 SA 설치 */
if (ops) {
ctx.sa.assoc_num = an;
ctx.sa.tx_sa = tx_sa;
ctx.secy = secy;
ret = ops->mdo_add_txsa(&ctx); /* NIC HW에 SA 키 설치 */
if (ret)
return ret;
}
/* SA가 HW에 설치되면, 이후 TX 패킷은 NIC이 자동 암호화 */
}
/* 3. RX 경로: HW offload 시 NIC이 복호화 완료 */
static rx_handler_result_t macsec_handle_frame(
struct sk_buff **pskb)
{
struct macsec_rx_sc *rx_sc;
/* HW offload: NIC이 이미 SecTAG 제거 + 복호화 + ICV 검증 완료 */
if (macsec_is_offloaded(macsec)) {
/* skb에 원본 이더넷 프레임 (평문) 상태로 전달됨 */
/* → 상위 네트워크 스택으로 직접 전달 */
return RX_HANDLER_PASS;
}
/* SW: 커널이 직접 SecTAG 파싱 → AES-GCM 복호화 → ICV 검증 */
sc = macsec_find_rx_sc(secy, sci);
ret = macsec_decrypt(skb, sc->sa[an]);
/* ... */
}
MACsec + NGFW Zero Trust 통합 시나리오
데이터센터 Zero Trust 아키텍처에서 MACsec와 NGFW를 결합하는 대표적 패턴입니다. 모든 L2 세그먼트에서 MACsec 암호화를 적용하고, NGFW가 복호화된 트래픽에 대해 L3~L7 검사를 수행합니다.
#!/bin/bash
# Zero Trust 데이터센터: MACsec HW offload + NGFW DPI 통합
# === 1. MACsec HW offload 인터페이스 (서버 ↔ ToR 스위치 간) ===
# 각 서버의 NIC이 ToR 스위치와 MACsec 세션 수립
ip link add link eth0 macsec0 type macsec \
sci $(cat /sys/class/net/eth0/address | tr -d ':'):0001 \
encrypt on protect on \
offload mac
# === 2. MACsec 위에 NGFW nftables 규칙 적용 ===
# MACsec 복호화 후 macsec0 인터페이스에서 L3/L4 필터링
nft -f - << 'EOF'
table inet zt_firewall {
chain input {
type filter hook input priority 0; policy drop;
# MACsec 인터페이스에서만 트래픽 허용
iifname "macsec0" jump macsec_inspect
iifname "eth0" drop # 비암호화 트래픽 차단
# loopback 허용
iif lo accept
}
chain macsec_inspect {
# conntrack + DPI
ct state established,related accept
ct state invalid drop
# 허용된 서비스만 통과
tcp dport { 22, 80, 443, 8443 } ct state new accept
udp dport { 53, 123 } accept
# 나머지 → 로그 + 차단
log prefix "[ZT-DROP] " counter drop
}
chain forward {
type filter hook forward priority 0; policy drop;
# MACsec 인터페이스 간 포워딩 (NGFW가 라우터 역할)
iifname "macsec*" oifname "macsec*" \
ct state established,related accept
iifname "macsec*" oifname "macsec*" \
ct state new counter queue num 0-3 fanout,bypass
}
}
EOF
# === 3. 확인 ===
ip macsec show
# TXSC: ... (offload: mac, state: on)
# RXSC: ... (offload: mac, state: on)
# MACsec HW 카운터 → 정상 암·복호화 확인
ethtool -S eth0 | grep -i macsec
# tx_macsec_pkts: 5678901
# rx_macsec_pkts: 5670000
# rx_macsec_decrypt_fail: 0 ← 0이면 정상
전용 크립토 가속기 (Intel QAT, Marvell NITROX)
NIC inline crypto와 별도로, 전용 크립토 가속 카드는 대량의 비대칭키 연산(RSA/ECDHE 핸드셰이크)과 대칭키 암호화를 모두 처리할 수 있습니다. NGFW에서 SSL Inspection의 TLS 핸드셰이크 병목(CPS 한계)을 해소하는 핵심 구성 요소입니다.
주요 크립토 가속기 비교
| 가속기 | 유형 | 대칭키 처리량 | RSA-2048 ops/s | ECDHE P-256 ops/s | TLS 핸드셰이크/s | Linux 드라이버 |
|---|---|---|---|---|---|---|
| Intel QAT 4xxx (4th Gen Xeon 내장) | 내장 ASIC | 100 Gbps | 100K | 200K | ~100K | qat_4xxx (커널 5.18+) |
| Intel QAT 8970 (PCIe 카드) | PCIe 카드 | 200 Gbps | 140K | 280K | ~140K | qat_c62x |
| Marvell NITROX V | PCIe 카드 | 100 Gbps | 100K | 200K | ~100K | nitrox (crypto API) |
| Marvell LiquidSecurity | HSM + 가속 | 50 Gbps | 50K | 100K | ~50K | 전용 드라이버 |
| ARM CryptoCell | SoC 내장 | 1~5 Gbps | 5K | 10K | ~5K | ccree |
| CPU (AES-NI) | CPU 명령어 | 2~8 Gbps/core | 5K/core | 10K/core | ~5K/core | aesni_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
Marvell NITROX V 상세
Marvell NITROX V는 PCIe Gen4 x16 폼팩터의 전용 크립토 가속 카드로, Intel QAT의 주요 경쟁 제품입니다. SSL/TLS 핸드셰이크 가속과 IPSec 벌크 암호화를 동시에 처리합니다. NGFW에서 NITROX는 특히 대규모 VPN 게이트웨이와 고밀도 SSL Inspection 환경에서 사용됩니다.
| 스펙 | NITROX V CNN55XX | NITROX V-T (Thunderbolt) | Intel QAT 4xxx |
|---|---|---|---|
| 대칭키 처리량 | 100 Gbps | 200 Gbps | 100 Gbps |
| RSA-2048 ops/s | 100K | 200K | 100K |
| ECDHE P-256 ops/s | 200K | 400K | 200K |
| TLS 핸드셰이크/s | ~100K | ~200K | ~100K |
| 인터페이스 | PCIe Gen3 x16 | PCIe Gen4 x16 | CPU 내장 / PCIe |
| VF (SR-IOV) | 128 VF | 128 VF | 최대 16 VF |
| Linux 드라이버 | nitrox (crypto API) | nitrox (crypto API) | qat_4xxx |
| DPDK PMD | crypto_nitrox | crypto_nitrox | crypto_qat |
| OpenSSL 엔진 | 지원 | 지원 | qatengine |
# Marvell NITROX V 설정 및 확인
# 1. 디바이스 확인
lspci -d 177d: | grep -i "Crypto\|Cavium"
# 0000:86:00.0 Co-processor: Cavium, Inc. NITROX V [CNN55XX] (rev 01)
# 2. 커널 모듈 로드
modprobe nitrox
# 3. crypto API 등록 확인
cat /proc/crypto | grep -B2 "driver.*nitrox"
# name : gcm(aes)
# driver : gcm-aes-nitrox
# priority : 4000
# 4. SR-IOV VF 생성 (멀티테넌트/컨테이너 환경)
echo 4 > /sys/bus/pci/devices/0000:86:00.0/sriov_numvfs
# → 4개 VF 생성, 각 VF를 컨테이너/VM에 할당 가능
# 5. NITROX 상태 확인
cat /sys/kernel/debug/nitrox/0000:86:00.0/stats
# requests_submitted: 12345678
# requests_completed: 12345670
# requests_pending: 8
# requests_error: 0
Linux Crypto API 비동기 배칭 메커니즘
크립토 가속기의 성능을 최대화하려면 비동기(Async) 배칭이 핵심입니다. PCIe DMA 왕복 레이턴시(10~50μs)를 상쇄하려면, 단일 요청이 아닌 다수의 요청을 한 번에 가속기에 제출하여 처리량을 극대화해야 합니다.
/* Linux Crypto API 비동기 배칭 패턴 */
/* IPSec xfrm이나 kTLS에서 내부적으로 사용하는 구조 */
/* 1. cryptd (crypto daemon) — 비동기 래퍼 */
/* 동기 알고리즘을 비동기로 변환하여 커널 워커 스레드에서 실행 */
struct crypto_aead *aead;
aead = crypto_alloc_aead("cryptd(gcm(aes))", 0, 0);
/* → cryptd 래퍼가 요청을 큐에 넣고 워커 스레드에서 배치 처리 */
/* 2. pcrypt (parallel crypto) — 멀티코어 병렬 처리 */
/* 다수의 암호화 요청을 여러 CPU에 분산 */
aead = crypto_alloc_aead("pcrypt(gcm(aes))", 0, 0);
/* → padata 프레임워크를 사용하여 코어 간 요청 분산 */
/* → QAT/NITROX가 등록되어 있으면 각 코어에서 HW 가속기 활용 */
/* 3. HW 가속기의 배칭 처리 내부 */
/* drivers/crypto/qat/qat_algs.c 기반 */
static int qat_aead_encrypt(struct aead_request *areq)
{
struct qat_crypto_instance *inst = ctx->inst;
/* 요청을 Ring Buffer에 추가 */
ret = adf_send_message(inst->sym_tx, (u32 *)msg);
if (ret == -EAGAIN) {
/* Ring이 가득 참 → 백프레셔 */
/* 이전 배치가 완료될 때까지 대기 */
return -EBUSY;
}
/* 요청이 Ring에 추가됨 → HW가 배치로 처리 */
/* Ring이 일정 수준 차면 HW가 자동으로 DMA 실행 */
return -EINPROGRESS; /* 비동기: 콜백에서 완료 통지 */
}
/* 4. 완료 콜백: 인터럽트 코얼레싱으로 배치 완료 */
static void qat_aead_cb(struct icp_qat_fw_la_resp *resp)
{
struct aead_request *areq = (void *)resp->opaque_data;
/* HW 완료 → 콜백 호출 → xfrm/kTLS에 결과 전달 */
areq->base.complete(&areq->base, 0);
}
DPDK Cryptodev PMD 연동
고성능 NGFW에서 커널 crypto API 대신 DPDK Cryptodev 프레임워크를 사용하면, 폴링 모드(PMD)로 크립토 가속기를 직접 제어하여 인터럽트 오버헤드를 제거하고 레이턴시를 최소화할 수 있습니다. Snort 3, Suricata AF_XDP 모드 등에서 활용됩니다.
| 항목 | 커널 Crypto API | DPDK Cryptodev PMD |
|---|---|---|
| 동작 방식 | 인터럽트 기반 (NAPI 유사) | 폴링 기반 (busy-wait) |
| 컨텍스트 스위치 | 있음 (콜백) | 없음 (동일 스레드) |
| 배치 크기 제어 | HW/드라이버 의존 | 어플리케이션이 직접 제어 |
| 레이턴시 | 10~50μs (인터럽트 포함) | 3~10μs (폴링) |
| CPU 사용 | 유휴 시 0% | 항상 100% (폴링 코어) |
| 적합 환경 | 범용 서버, 가변 부하 | 전용 NGFW, 고정 부하 |
/* DPDK Cryptodev: QAT PMD를 사용한 IPSec 암호화 예시 */
/* DPDK 23.11+ 기준 */
/* 1. Cryptodev 디바이스 초기화 */
struct rte_cryptodev_config conf = {
.nb_queue_pairs = 4, /* 4 큐쌍 (코어당 1개) */
.ff_disable = 0,
};
rte_cryptodev_configure(cdev_id, &conf);
/* 각 큐쌍 설정 */
struct rte_cryptodev_qp_conf qp_conf = {
.nb_descriptors = 2048, /* 디스크립터 수 (배치 크기 결정) */
};
for (int qp = 0; qp < 4; qp++)
rte_cryptodev_queue_pair_setup(cdev_id, qp, &qp_conf, socket_id);
rte_cryptodev_start(cdev_id);
/* 2. AES-256-GCM 세션 생성 */
struct rte_crypto_sym_xform xform = {
.type = RTE_CRYPTO_SYM_XFORM_AEAD,
.aead = {
.op = RTE_CRYPTO_AEAD_OP_ENCRYPT,
.algo = RTE_CRYPTO_AEAD_AES_GCM,
.key = { .data = key, .length = 32 },
.iv = { .offset = IV_OFFSET, .length = 12 },
.digest_length = 16,
.aad_length = 12, /* ESP AAD: SPI + SeqNum */
},
};
struct rte_cryptodev_sym_session *sess;
sess = rte_cryptodev_sym_session_create(cdev_id, &xform, sess_pool);
/* 3. 배치 암호화: enqueue → dequeue 패턴 */
/* NGFW fast path에서 패킷 배치로 처리 */
#define BURST_SIZE 32
struct rte_crypto_op *ops[BURST_SIZE];
struct rte_crypto_op *completed[BURST_SIZE];
/* 패킷 배치 → crypto op 구성 */
for (int i = 0; i < nb_pkts; i++) {
ops[i] = rte_crypto_op_alloc(op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
rte_crypto_op_attach_sym_session(ops[i], sess);
ops[i]->sym->m_src = mbufs[i];
/* IV, AAD, digest 오프셋 설정... */
}
/* 4. 비동기 enqueue (배치) */
nb_enq = rte_cryptodev_enqueue_burst(cdev_id, qp_id, ops, nb_pkts);
/* 5. 폴링 dequeue (완료 대기) */
do {
nb_deq = rte_cryptodev_dequeue_burst(cdev_id, qp_id,
completed, BURST_SIZE);
} while (nb_deq == 0);
/* 6. 완료된 패킷 → NIC TX (IPSec ESP 전송) */
for (int i = 0; i < nb_deq; i++) {
if (completed[i]->status == RTE_CRYPTO_OP_STATUS_SUCCESS)
rte_eth_tx_buffer(port_id, tx_queue, tx_buf, completed[i]->sym->m_src);
}
- 코어 전용 할당 필수: 폴링 모드이므로 crypto 코어가 항상 100% CPU를 사용합니다. NGFW에서 패킷 처리 코어와 crypto 코어를 분리하여 할당해야 합니다
- 세션 풀 크기: 동시 IPSec SA 수 × 방향(TX+RX) 이상의 세션 풀이 필요합니다. 부족하면 세션 생성 실패로 트래픽 드롭이 발생합니다
- 혼합 사용 불가: 동일 QAT/NITROX 디바이스를 커널 crypto API와 DPDK PMD에서 동시 사용할 수 없습니다. SR-IOV VF로 분할하면 커널(PF) + DPDK(VF) 혼합 사용이 가능합니다
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이 아닌 패시브 복호화이므로 클라이언트에 인증서를 설치할 필요가 없습니다.
- 적용 대상: 기업 내부 웹 서버, API 게이트웨이 앞단의 NGFW
- 제한: PFS(Perfect Forward Secrecy) cipher suite(ECDHE) 사용 시 세션키 추출 불가 → RSA 키 교환만 가능 (TLS 1.3에서는 불가)
- 대안: TLS 1.3에서는 서버가 세션 키를 NGFW에 전달하는 키 에스크로(Key Escrow) 방식 또는 eBPF 기반 세션키 추출
방식 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 트래픽을 복호화하지 않고, 외부에서 관찰 가능한 메타데이터만으로 위협을 탐지합니다:
- JA4/JA4+ 핑거프린팅: TLS Client Hello의 구조적 특성으로 클라이언트/악성코드 식별
- 인증서 분석: 서버 인증서의 CN/SAN, 발급자, 유효기간 검사 (TLS 1.2에서만)
- DNS 상관분석: DNS 쿼리와 TLS 연결을 연계하여 목적지 도메인 추론
- 트래픽 패턴 분석: 패킷 크기/타이밍 분포로 애플리케이션 유형 추론 (머신러닝 기반)
- ESNI/ECH 탐지: ECH 사용 여부를 탐지하여 정책 적용 (차단 또는 추가 검사)
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 암호화 투명 처리
커널 Crypto API 내부 구조
리눅스 커널의 Crypto API는 모든 암호화 오프로드의 기반 프레임워크입니다. kTLS, IPSec(xfrm), dm-crypt 등이 이 API를 통해 SW/HW 가속기를 투명하게 활용합니다. NGFW에서 크립토 가속기의 동작을 이해하려면 이 API의 알고리즘 선택 메커니즘과 fallback 구조를 이해해야 합니다.
알고리즘 등록과 우선순위 선택
커널에 로드된 모든 crypto 드라이버는 /proc/crypto에 등록됩니다. 동일 알고리즘(예: gcm(aes))에 대해 여러 구현이 존재할 수 있으며, priority(우선순위) 값이 높은 구현이 자동으로 선택됩니다.
| 드라이버 | 알고리즘 | 우선순위 | 유형 | 비동기 |
|---|---|---|---|---|
gcm-aes-qat | gcm(aes) | 4001 | HW (QAT PCIe) | 지원 |
gcm-aes-nitrox | gcm(aes) | 4000 | HW (NITROX PCIe) | 지원 |
generic-gcm-aesni | gcm(aes) | 400 | CPU (AES-NI) | 미지원 |
gcm_base(ctr(aes-generic),ghash-generic) | gcm(aes) | 100 | 순수 SW | 미지원 |
# crypto API에 등록된 알고리즘 확인
cat /proc/crypto | grep -E "^(name|driver|priority|type)" | head -40
# gcm(aes) 알고리즘의 모든 구현과 우선순위 확인
cat /proc/crypto | grep -B1 -A3 "gcm(aes)"
# name : gcm(aes)
# driver : gcm-aes-qat ← QAT HW (최고 우선순위)
# module : qat_4xxx
# priority : 4001
# --
# name : gcm(aes)
# driver : generic-gcm-aesni ← CPU AES-NI
# module : aesni_intel
# priority : 400
# 특정 드라이버의 지원 알고리즘 목록
cat /proc/crypto | grep -B1 "driver.*qat" | grep name
# name : gcm(aes)
# name : rfc4106(gcm(aes)) ← IPSec ESP용
# name : rfc4543(gcm(aes)) ← IPSec AH용
# name : rsa
# name : ecdh
변환(Transform) 유형 체계
Crypto API는 알고리즘을 용도별 변환 유형(Transform Type)으로 분류합니다. NGFW에서 사용하는 주요 변환 유형과 해당하는 오프로드 기술의 매핑입니다.
| 변환 유형 | 커널 구조체 | 용도 | NGFW 적용 | HW 가속기 |
|---|---|---|---|---|
| aead | crypto_aead | 인증 암호화 (AES-GCM, ChaCha20-Poly1305) | IPSec ESP, kTLS 레코드 | QAT, NITROX, NIC inline |
| skcipher | crypto_skcipher | 대칭키 블록 암호 (AES-CBC, AES-CTR) | dm-crypt, 레거시 IPSec | QAT, NITROX, CAAM |
| akcipher | crypto_akcipher | 비대칭키 (RSA, ECDSA) | TLS 핸드셰이크 (인증서 검증) | QAT, NITROX |
| kpp | crypto_kpp | 키 합의 (ECDHE, DH) | TLS 핸드셰이크 (키 교환) | QAT, NITROX |
| ahash | crypto_ahash | 비동기 해시 (SHA-256/512) | IPSec AH, HMAC | QAT, CAAM, SHA-NI |
| rng | crypto_rng | 난수 생성 (DRBG, RDRAND) | 키 생성, IV 생성 | RDRAND, RDSEED |
/* Crypto API 변환 유형별 할당과 사용 */
/* 1. AEAD (IPSec ESP / kTLS) */
struct crypto_aead *aead;
aead = crypto_alloc_aead("rfc4106(gcm(aes))", 0, 0);
/* → 커널이 우선순위에 따라 QAT → AES-NI → SW 순으로 선택 */
/* → rfc4106은 IPSec ESP의 AES-GCM 래퍼 (8바이트 AAD = SPI+SeqNum) */
crypto_aead_setkey(aead, key, key_len);
crypto_aead_setauthsize(aead, 16); /* ICV 태그 16바이트 */
/* 2. akcipher (TLS 핸드셰이크 인증서 검증) */
struct crypto_akcipher *rsa;
rsa = crypto_alloc_akcipher("rsa", 0, 0);
/* → QAT RSA 가속 (priority 4000+) 또는 SW 구현 */
/* → TLS 핸드셰이크 시 서버 인증서의 RSA 서명 검증에 사용 */
/* 3. kpp (TLS 핸드셰이크 ECDHE 키 교환) */
struct crypto_kpp *ecdh;
ecdh = crypto_alloc_kpp("ecdh-nist-p256", 0, 0);
/* → QAT ECDHE 가속 또는 커널 SW 구현 */
/* → 공유 비밀(shared secret) 생성 → PRF로 세션키 파생 */
HW Fallback 메커니즘
HW 가속기가 특정 알고리즘이나 키 크기를 지원하지 않을 때, 커널은 자동으로 SW 구현으로 폴백합니다. 이 메커니즘은 NGFW에서 혼합 트래픽(AES-GCM + ChaCha20)을 처리할 때 중요합니다.
/* HW fallback 메커니즘 (NIC inline crypto의 경우) */
/* drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c 기반 */
static int mlx5e_xfrm_add_state(struct xfrm_state *x,
struct netlink_ext_ack *extack)
{
/* NIC이 지원하는 알고리즘인지 확인 */
if (x->aead->alg_id != SADB_X_EALG_AES_GCM_ICV16) {
/* AES-GCM 이외 (ChaCha20, AES-CBC 등) → HW 오프로드 거부 */
NL_SET_ERR_MSG_MOD(extack, "Only AES-GCM supported");
return -EOPNOTSUPP;
/* → xfrm 스택이 자동으로 SW crypto (AES-NI) 사용 */
}
if (x->aead->alg_key_len != 128 &&
x->aead->alg_key_len != 256) {
/* 지원하지 않는 키 크기 → SW 폴백 */
return -EOPNOTSUPP;
}
/* HW SA 테이블에 공간이 있는지 확인 */
if (mlx5e_ipsec_sa_count(priv) >= priv->ipsec->max_sa) {
/* SA 테이블 가득 참 → SW 폴백 */
return -ENOSPC;
}
/* 모든 조건 충족 → HW offload 설치 */
return mlx5e_ipsec_create_sa(priv, x);
}
/* kTLS fallback: NIC TLS context 부족 시 */
/* net/tls/tls_device.c */
static int tls_set_device_offload(struct sock *sk, ...)
{
ret = netdev->tlsdev_ops->tls_dev_add(netdev, sk, dir, crypto_info);
if (ret) {
/* NIC offload 실패 → SW kTLS로 자동 폴백 */
/* /proc/net/tls_stat의 TlsCurrTxSw 증가 */
ctx->tx_conf = TLS_SW;
return 0; /* 사용자에게 에러가 아닌 투명한 폴백 */
}
ctx->tx_conf = TLS_HW;
return 0;
}
/proc/net/tls_stat의 TlsCurrTxSw/TlsCurrRxSw가 증가하면 kTLS SW 폴백이 발생한 것이고, ip -s xfrm state에서 offload 없는 SA가 있으면 IPSec SW 폴백입니다. 운영 중 이 수치를 모니터링하여 NIC SA 테이블 크기나 QAT 용량이 부족하지 않은지 확인해야 합니다.
암호화 오프로드 성능 튜닝 및 모니터링
암호화 오프로드의 실제 성능은 설정, NIC 펌웨어 버전, 커널 파라미터, 트래픽 패턴에 따라 크게 달라집니다. 이 섹션에서는 NGFW 운영 환경에서의 실전 튜닝과 병목 진단 방법을 다룹니다.
ethtool 카운터 해석 가이드
NIC 암호화 오프로드의 상태를 판단하는 핵심 카운터들입니다. 이 카운터들을 모니터링하면 오프로드가 정상 동작하는지, 어디서 병목이 발생하는지 파악할 수 있습니다.
| 카운터 | 의미 | 정상 범위 | 이상 시 원인 |
|---|---|---|---|
tx_tls_encrypted_packets | NIC HW가 TLS 암호화한 패킷 수 | 꾸준히 증가 | 0이면 kTLS HW offload 미활성 |
tx_tls_ooo | TLS out-of-order resync 횟수 | 전체 대비 <0.01% | 높으면 TCP 재전송 빈발 |
tx_tls_drop_no_sync_data | resync 실패로 드롭된 패킷 | 0 | >0이면 NIC TLS 상태 불일치 |
rx_tls_decrypted_packets | NIC HW가 TLS 복호화한 패킷 수 | 꾸준히 증가 | 0이면 RX offload 미활성 |
rx_tls_resync_req_pkt | RX resync 요청 횟수 | 전체 대비 <0.1% | 높으면 패킷 로스/리오더링 |
tx_ipsec_encrypt | NIC HW가 IPSec 암호화한 패킷 수 | 꾸준히 증가 | 0이면 IPSec offload 미활성 |
rx_ipsec_auth_fail | IPSec ICV 검증 실패 (무결성 오류) | 0 | >0이면 키 불일치/공격/손상 |
tx_macsec_pkts | MACsec HW 암호화 패킷 수 | 꾸준히 증가 | 0이면 MACsec offload 미활성 |
rx_macsec_decrypt_fail | MACsec 복호화 실패 | 0 | >0이면 키 불일치/프레임 손상 |
# 종합 암호화 오프로드 상태 확인 스크립트
#!/bin/bash
# crypto-offload-status.sh — NGFW 암호화 오프로드 종합 진단
NIC=${1:-eth0}
echo "=== $NIC 암호화 오프로드 상태 ==="
echo ""
echo "--- kTLS 오프로드 ---"
cat /proc/net/tls_stat 2>/dev/null || echo "kTLS 미지원"
echo ""
echo "--- NIC TLS 카운터 ---"
ethtool -S $NIC 2>/dev/null | grep -i tls
echo ""
echo "--- NIC IPSec 카운터 ---"
ethtool -S $NIC 2>/dev/null | grep -i ipsec
echo ""
echo "--- NIC MACsec 카운터 ---"
ethtool -S $NIC 2>/dev/null | grep -i macsec
echo ""
echo "--- IPSec SA 오프로드 상태 ---"
ip xfrm state show 2>/dev/null | grep -A1 offload
echo ""
echo "--- NIC offload feature flags ---"
ethtool -k $NIC 2>/dev/null | grep -E "tls|ipsec|macsec"
echo ""
echo "--- Crypto API HW 가속기 ---"
cat /proc/crypto | grep -B1 "driver.*\(qat\|nitrox\|caam\)" | grep -E "name|driver"
perf를 이용한 암호화 병목 진단
암호화 처리가 CPU에서 수행되고 있는지, HW 가속기로 오프로드되었는지를 perf로 확인할 수 있습니다. 오프로드가 정상 동작하면 crypto 관련 커널 함수의 CPU 사용이 거의 0에 가까워야 합니다.
# 1. 암호화 관련 커널 함수 CPU 사용률 확인
# AES-NI 함수가 상위에 있으면 → SW 처리 중 (HW offload 미동작)
perf top -g --no-children -e cycles:k -- \
--call-graph fp --filter 'aes\|gcm\|crypto\|esp\|xfrm'
# 2. IPSec 관련 함수 프로파일링 (10초 수집)
perf record -g -a -- sleep 10
perf report --no-children | grep -E "aesni|gcm|esp_output|esp_input|xfrm"
# HW offload 정상 시: 이 함수들의 CPU 점유율 ≈ 0%
# SW 처리 시: aesni_gcm_enc/dec가 상위에 위치
# 3. 코어별 crypto 부하 분석
# 특정 코어에 crypto 부하가 집중되는지 확인
perf stat -a -e instructions,cycles \
-e 'crypto_dispatch*' \
--per-core -- sleep 5
# 4. QAT 가속기 활용 확인
# QAT 드라이버 함수가 호출되면 HW 가속 동작 중
perf record -g -a -- sleep 5
perf report | grep -E "qat_|adf_"
# qat_aead_encrypt: HW 암호화 요청 제출
# adf_send_message: QAT Ring에 메시지 전달
# 5. kTLS SW 폴백 비율 실시간 모니터링
watch -n 1 'cat /proc/net/tls_stat | grep -E "Curr|Device|Error"'
# TlsCurrTxDevice가 증가하면 HW offload 정상
# TlsCurrTxSw가 증가하면 SW 폴백 발생
핵심 튜닝 파라미터
| 파라미터 | 기본값 | 권장값 (NGFW) | 효과 |
|---|---|---|---|
ethtool -K tls-hw-tx-offload | off (일부 NIC) | on | kTLS TX HW offload 활성화 |
ethtool -K tls-hw-rx-offload | off (일부 NIC) | on | kTLS RX HW offload 활성화 |
ethtool -K esp-hw-offload | on | on | IPSec crypto offload 활성화 |
net.core.default_qdisc | fq_codel | fq | kTLS + TCP pacing 최적화 |
net.ipv4.tcp_congestion_control | cubic | bbr | kTLS sendfile() 처리량 향상 |
QAT NumberCyInstances | 2 | 코어 수에 맞춤 | QAT 인스턴스 병렬화 |
QAT NumConcurrentSymRequests | 512 | 2048~4096 | 동시 처리 요청 수 확대 |
NIC rx-usecs (인터럽트 코얼레싱) | 50 | 20~50 | crypto 완료 콜백 레이턴시 조절 |
# NGFW 암호화 오프로드 최적화 설정 예시
# 1. kTLS HW offload 활성화
ethtool -K eth0 tls-hw-tx-offload on
ethtool -K eth0 tls-hw-rx-offload on
# 2. IPSec HW offload 활성화
ethtool -K eth0 esp-hw-offload on
ethtool -K eth0 esp-tx-csum-hw-offload on
# 3. TCP pacing + kTLS 최적화
sysctl -w net.core.default_qdisc=fq
sysctl -w net.ipv4.tcp_congestion_control=bbr
# 4. 인터럽트 코얼레싱 (crypto 완료 레이턴시 최적화)
# 값이 낮으면 레이턴시↓ 처리량↓, 높으면 레이턴시↑ 처리량↑
ethtool -C eth0 rx-usecs 30 tx-usecs 30
# 5. QAT 설정 최적화
# /etc/qat_4xxx.conf (Intel QAT 4xxx)
# NumberCyInstances = 8 # CPU 코어 수에 맞춤
# NumConcurrentSymRequests = 4096
# NumConcurrentAsymRequests = 1024
# 6. NUMA 친화성: QAT가 연결된 NUMA 노드에 처리 코어 배치
# QAT PCIe 디바이스의 NUMA 노드 확인
cat /sys/bus/pci/devices/0000:6b:00.0/numa_node
# 0
# NUMA 노드 0의 코어에 IPSec/SSL 처리 고정
# Suricata나 nginx의 worker를 같은 NUMA 노드 코어에 할당
taskset -c 0-7 suricata -c /etc/suricata/suricata.yaml
lstopo 또는 numactl --hardware로 토폴로지를 확인하고, crypto 워크로드를 가속기와 같은 NUMA 노드에 배치해야 합니다.
TLS 1.3 / QUIC / ECH 시대의 오프로드 도전과제
암호화 프로토콜의 발전은 NGFW 오프로드에 새로운 도전과제를 제시합니다. TLS 1.3의 보안 강화, QUIC의 UDP 기반 전환, ECH의 메타데이터 암호화는 기존 오프로드 전략의 근본적인 재검토를 요구합니다.
TLS 1.3이 오프로드에 미치는 변화
TLS 1.3은 TLS 1.2 대비 핸드셰이크 구조와 레코드 포맷이 크게 변경되었으며, 이는 HW 오프로드 설계에 직접적인 영향을 미칩니다.
| 변경 사항 | TLS 1.2 | TLS 1.3 | 오프로드 영향 |
|---|---|---|---|
| 핸드셰이크 RTT | 2-RTT | 1-RTT (0-RTT PSK 가능) | CPS 향상, 가속기 부담 감소 |
| 키 교환 | RSA 또는 ECDHE | ECDHE만 (PFS 필수) | 패시브 복호화(방식 2) 불가능 |
| 인증서 암호화 | 평문 전송 | 핸드셰이크 이후 암호화 | 인증서 기반 분류 불가 |
| cipher suite | 다양 (CBC, GCM, ...) | AEAD만 (AES-GCM, ChaCha20) | NIC inline 호환성 향상 |
| 0-RTT (Early Data) | 없음 | PSK 기반 0-RTT | DPI 검사 전 데이터 전송 가능 |
| 레코드 유형 암호화 | 평문 Content-Type | Content-Type 암호화 | 레코드 유형 기반 필터링 불가 |
# TLS 1.3 세션키 에스크로: SSLKEYLOGFILE 기반
# 서버 측에서 세션키를 파일/소켓으로 export
# 1. nginx: ssl_key_log 디렉티브 (OpenSSL 3.0+)
# /etc/nginx/nginx.conf
# ssl_key_log /var/log/nginx/tls_keys.log;
# 2. 키 로그 포맷 (Wireshark 호환)
# CLIENT_RANDOM
# CLIENT_HANDSHAKE_TRAFFIC_SECRET (TLS 1.3)
# SERVER_HANDSHAKE_TRAFFIC_SECRET (TLS 1.3)
# CLIENT_TRAFFIC_SECRET_0 (TLS 1.3)
# SERVER_TRAFFIC_SECRET_0 (TLS 1.3)
# 3. NGFW에서 키 에스크로를 받아 패시브 복호화
# Suricata TLS 키 에스크로 설정 (suricata.yaml)
# tls:
# key-log-file: /var/log/nginx/tls_keys.log
# decrypt: yes
# 4. eBPF 기반 자동 키 추출 (서버 설정 변경 없이)
# ecapture 도구: OpenSSL uprobe로 세션키 자동 캡처
# ecapture tls --hex --pid=12345
QUIC 암호화와 오프로드 한계
QUIC(HTTP/3)는 UDP 위에서 TLS 1.3을 통합하며, 전체 웹 트래픽의 30% 이상을 차지합니다. QUIC의 암호화 구조는 기존 TCP 기반 오프로드와 근본적으로 다릅니다.
| 특성 | TLS over TCP | QUIC (TLS 1.3 통합) | 오프로드 영향 |
|---|---|---|---|
| 전송 계층 | TCP | UDP | TCP 기반 kTLS offload 불가 |
| 암호화 범위 | 페이로드만 (TCP 헤더 평문) | 대부분의 헤더 + 페이로드 | 5-tuple 기반 flowtable 오프로드 가능하나 DPI 제한 |
| 연결 식별 | 5-tuple (IP+Port) | Connection ID (CID) | NIC 연결 추적 재설계 필요 |
| 0-RTT | TLS 1.3 0-RTT (제한적) | 기본 지원 (PSK + 주소 검증) | DPI 없이 데이터 전달 가능 |
| 연결 마이그레이션 | 불가 (IP 변경 시 재연결) | CID 기반 투명 마이그레이션 | SA/flowtable 규칙 무효화 |
| 멀티플렉싱 | HTTP/2 스트림 (HOL blocking) | 독립 스트림 (HOL-free) | 스트림별 검사 필요 |
기존 TLS와 달리, QUIC는 패킷 헤더 일부도 암호화합니다:
QUIC Long Header (핸드셰이크 단계):
┌──────────────────────────────────────────────┐ │ Form(1) │ Fixed(1) │ Type(2) │ Reserved(2) │ ← 평문 │ Version(32) │ ← 평문 │ DCID Len(8) │ DCID(0~20B) │ ← 평문 │ SCID Len(8) │ SCID(0~20B) │ ← 평문 │ Payload Length │ Packet Number │ ← PN 암호화 │ Payload (CRYPTO frames) │ ← AEAD 암호화 └──────────────────────────────────────────────┘
QUIC Short Header (데이터 전송 단계):
┌──────────────────────────────────────────────┐ │ Form(1)=0 │ Fixed(1) │ Spin(1) │ Reserved(2)│ ← 평문 │ Key Phase(1) │ PN Length(2) │ ← 헤더 보호 │ DCID (서버가 선택한 길이) │ ← 평문 │ Packet Number (1~4B) │ ← PN 암호화 │ Payload (STREAM/DATAGRAM frames) │ ← AEAD 암호화 └──────────────────────────────────────────────┘
QUIC Header Protection으로 인해 패킷 번호가 암호화되어 있으므로, NIC이 패킷 번호를 읽으려면 먼저 AES-ECB 1블록 복호화가 필요합니다. 이것이 현재 NIC inline crypto로 QUIC offload가 어려운 핵심 이유입니다.
- 현재: 커널 QUIC 지원(RFC 9000)이 초기 단계이며, NIC inline QUIC offload를 지원하는 하드웨어는 없습니다. QUIC 트래픽은 UDP로 전송되므로 kTLS offload가 적용되지 않습니다
- 커널 kQUIC: kTLS와 유사한
setsockopt(SOL_QUIC)기반 커널 QUIC 레코드 레이어가 논의 중이며, 이것이 구현되면 NIC inline QUIC offload의 기반이 됩니다 - NGFW 대안: 현재 QUIC 트래픽은 ① UDP 443 차단 후 TCP TLS 폴백 유도, ② JA4 핑거프린팅으로 메타데이터 분류, ③ eBPF 에이전트로 QUIC 라이브러리 후킹 등으로 대응합니다
- NVIDIA BlueField-3: DPU의 ARM 코어에서 QUIC 핸들링을 수행하는 하이브리드 접근이 시도되고 있습니다
ECH (Encrypted Client Hello)와 SSL Inspection
ECH(Encrypted Client Hello, RFC 8467)는 TLS 핸드셰이크의 Client Hello에서 SNI(Server Name Indication)를 암호화합니다. NGFW에서 SNI는 복호화 없이 목적지 도메인을 식별하는 핵심 메타데이터였으므로, ECH는 NGFW의 정책 기반 SSL Inspection에 심각한 영향을 미칩니다.
| NGFW 기능 | ECH 이전 | ECH 이후 | 대응 방안 |
|---|---|---|---|
| 도메인 기반 SSL Bypass | SNI로 bank.com 식별 → 검사 제외 | SNI 암호화로 식별 불가 | DNS 연계 또는 IP 기반 정책 |
| 카테고리 필터링 | SNI → URL 카테고리 DB 조회 | SNI 미확인 | DNS-over-HTTPS 차단 + 일반 DNS 감청 |
| 인증서 분석 | TLS 1.2: 서버 인증서 평문 | TLS 1.3+ECH: 인증서도 암호화 | MITM 프록시만 가능 |
| JA4 핑거프린팅 | Client Hello 전체 분석 | Outer Client Hello만 분석 가능 | JA4 정확도 감소, 보조 지표 필요 |
| SSL Inspection 적용 | SNI 기반 선택적 검사 | 전수 검사 또는 미검사 이분법 | DNS 정책 + MITM + eBPF 조합 |
# ECH 탐지 및 대응: nftables + DNS 연계
# 1. ECH 사용 탐지 (TLS Client Hello에서 ECH 확장 검출)
# TLS Client Hello의 Extension Type 0xfe0d (65037) = ECH
# nftables에서 raw 페이로드 매칭 (제한적)
nft add rule inet filter forward \
tcp dport 443 \
meta l4proto tcp \
@th,0,8 0x16 \
counter \
log prefix "[TLS-ECH-DETECT] "
# 2. ECH 대응 전략: DNS 기반 정책 (DNS가 평문인 경우)
# NGFW에서 DNS 응답의 HTTPS RR (Type 65)에서 ECH 설정 감지
# DNS HTTPS RR의 ech= 파라미터가 있으면 ECH 사용 예정
# 3. DoH (DNS-over-HTTPS) 차단으로 DNS 가시성 확보
# 잘 알려진 DoH 서버 IP 차단
nft add set inet filter doh_servers { type ipv4_addr\; }
nft add element inet filter doh_servers \
{ 1.1.1.1, 8.8.8.8, 9.9.9.9, 104.16.248.249, 104.16.249.249 }
nft add rule inet filter forward \
tcp dport 443 ip daddr @doh_servers \
counter drop
# 4. 기업 내부: 자체 DNS 서버 강제 + ECH 비활성화 정책
# Chrome: chrome://flags → #encrypted-client-hello → Disabled
# GPO: HKLM\SOFTWARE\Policies\Google\Chrome\EncryptedClientHelloEnabled=0
# Firefox: about:config → network.dns.echconfig.enabled=false
PQC (Post-Quantum Cryptography) 전환과 오프로드
양자 컴퓨터 위협에 대비한 포스트 양자 암호화(PQC) 전환이 진행 중입니다. NIST가 2024년 표준화한 ML-KEM(Kyber), ML-DSA(Dilithium) 등의 PQC 알고리즘은 기존 암호화 대비 키 크기와 연산 특성이 크게 다르며, 이는 HW 오프로드에 새로운 도전과제를 제시합니다.
| 항목 | ECDHE P-256 (현재) | ML-KEM-768 (PQC) | 하이브리드 X25519+ML-KEM | 오프로드 영향 |
|---|---|---|---|---|
| 공개키 크기 | 32B | 1,184B | 1,216B | Client Hello 크기 증가 → MTU 초과 가능 |
| 암호문 크기 | 32B | 1,088B | 1,120B | 핸드셰이크 패킷 3~5배 증가 |
| CPU 연산 (캡슐화) | ~0.1ms | ~0.05ms | ~0.15ms | ML-KEM은 오히려 빠름 (격자 기반) |
| QAT/NITROX 지원 | 지원 | 미지원 (2026 현재) | ECDHE만 HW, ML-KEM은 SW | 하이브리드 모드에서 부분 가속만 |
| NIC inline 영향 | N/A (핸드셰이크) | N/A (핸드셰이크) | 없음 | 레코드 암호화(AES-GCM)는 변경 없음 |
- 핸드셰이크 패킷 크기 증가: ML-KEM 하이브리드 Client Hello는 ~1.5KB로, TCP MSS(1460B)를 초과할 수 있습니다. 이 경우 Client Hello가 여러 TCP 세그먼트에 걸쳐 전송되어, 단일 패킷 DPI로 SNI를 추출하던 NGFW 로직이 실패할 수 있습니다
- 레코드 계층은 변경 없음: PQC는 핸드셰이크(키 교환/서명)에만 적용됩니다. 레코드 계층은 여전히 AES-256-GCM을 사용하므로, kTLS/IPSec NIC inline offload는 영향 없이 그대로 동작합니다
- HW 가속기 업그레이드 필요: QAT/NITROX의 PQC 지원은 펌웨어 업데이트로 추가될 예정이며, 신규 ASIC(Intel QAT 5xxx 등)에서 네이티브 PQC 가속이 계획되어 있습니다
- Chrome/Firefox 기본 활성화: 2025년부터 주요 브라우저가 X25519+ML-KEM-768 하이브리드를 기본값으로 사용하므로, NGFW는 PQC 하이브리드 핸드셰이크를 정상적으로 처리할 수 있어야 합니다
참고자료
커널 공식 문서
- Linux Kernel: XFRM Device Offload — IPSec HW offload API (crypto/packet/full mode)
- Linux Kernel: TLS Offload — kTLS HW offload 커널 문서
- Linux Kernel: Crypto API — 커널 암호화 API 프레임워크, 알고리즘 등록/우선순위
- Linux Kernel: MACsec — MACsec HW offload, MKA 통합
- Linux Kernel: BPF/XDP 문서 — XDP 프로그램 작성, 맵 타입, HW offload
벤더 기술 문서
- NVIDIA Crypto Offload — ConnectX-6 Dx/7 IPSec, TLS 하드웨어 암호화 오프로드
- Intel ICE Driver (E810) — E810 IPSec crypto offload 지원 드라이버
- Intel QAT — Quick Assist Technology 개요, 드라이버, 성능 가이드
RFC 및 표준
- IEEE 802.1AE — MACsec: Media Access Control Security
- IEEE 802.1X-2020 — MKA (MACsec Key Agreement) 프로토콜
- RFC 8446 — TLS 1.3 프로토콜 명세
- RFC 9000 — QUIC: A UDP-Based Multiplexed and Secure Transport
- RFC 8467 / draft-ietf-tls-esni — ECH (Encrypted Client Hello)
- FIPS 203 — ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism, Kyber)
커널 소스 경로
net/xfrm/xfrm_device.c— IPSec HW offload 디바이스 APInet/tls/tls_device.c— kTLS NIC HW offload 등록 및 처리drivers/net/macsec.c— MACsec 오프로드 프레임워크drivers/crypto/qat/— Intel QAT 가속기 드라이버drivers/crypto/marvell/nitrox/— Marvell NITROX 가속기 드라이버crypto/pcrypt.c— 병렬 crypto (padata 기반 멀티코어 분산)crypto/cryptd.c— 비동기 crypto 데몬 (동기→비동기 래퍼)
- NGFW 하드웨어 오프로드 — 3대 오프로드 아키텍처, Fast/Slow/Exception 경로, Stateful 방화벽 오프로드
- 상용 NGFW HW 아키텍처 — Fortinet NP7, Palo Alto FPGA, Check Point SecureXL 비교
- NGFW HW 오프로드 레퍼런스 — TC action, Bridge/switchdev, FIB, Tunnel, qdisc 오프로드 전체 레퍼런스
- 프로그래머블 NGFW 파이프라인 — eBPF/XDP, P4, QUIC/ECH 도전과제