MACsec (IEEE 802.1AE)
IEEE 802.1AE MACsec은 이더넷 L2 프레임을 홉 단위로 암호화(Encryption)·무결성(Integrity) 검증하는 표준입니다. Linux 커널의 drivers/net/macsec.c 구현을 중심으로 SecTAG/ICV 프레임 구조, GCM-AES 암호 스위트, MKA(802.1X-2010) 키 합의 프로토콜, CAK→SAK 키 계층, 커널 TX/RX 경로, NIC HW offload, ip macsec 운영 명령, 데이터센터 East-West 트래픽 보호 패턴, 성능 벤치마크와 트러블슈팅을 실전 운영 관점에서 정리합니다.
핵심 요약
- MACsec — IEEE 802.1AE 표준으로, 이더넷 프레임을 L2에서 홉 단위(hop-by-hop) 암호화·무결성 보호합니다.
- SecTAG — 원래 EtherType 자리에 삽입되는 보안 태그(8~16바이트)로, SCI와 패킷(Packet) 번호를 운반합니다.
- ICV — 프레임 끝에 추가되는 무결성 검증 값(Integrity Check Value, 8~16바이트)입니다.
- MKA — MACsec Key Agreement(IEEE 802.1X-2010)로, 피어 간 SAK(Secure Association Key)를 합의합니다.
- SAK — 실제 프레임 암복호화에 사용되는 대칭 키이며, CAK에서 파생됩니다.
- HW Offload — NIC가 암복호화를 하드웨어에서 처리해 CPU 부담을 제거합니다.
단계별 이해
- L2 암호화의 위치를 파악하기
MACsec은 이더넷 헤더 바로 뒤에서 동작합니다. IP 이상의 계층은 전혀 관여하지 않습니다. - 프레임 구조를 먼저 이해하기
SecTAG와 ICV가 원래 프레임의 어디에 삽입되는지 그림으로 확인하면 나머지가 쉬워집니다. - 키 합의와 데이터 경로를 분리해서 보기
MKA는 EAPoL 프레임으로 키를 교환하고, MACsec은 그 키로 데이터를 암호화합니다. 두 경로는 독립적입니다. - SW vs HW offload를 구분하기
소프트웨어 경로는 커널 crypto API를 사용하고, HW offload는 NIC 펌웨어(Firmware)가 처리합니다. 성능 차이가 극적입니다. - 문제는 통계와 카운터로 확인하기
ip -s macsec show의 InPktsOK, InPktsInvalid, OutPktsProtected가 첫 번째 진단 지표입니다.
drivers/net/macsec.c), 5.6에서 HW offload 인프라가 추가되었습니다.
2026년 3월 기준 최신 stable 커널에서 CONFIG_MACSEC은 대부분의 배포판에서 모듈로 활성화되어 있습니다.
IEEE 802.1AE 표준 개요
IEEE 802.1AE는 이더넷 LAN에서 데이터 기밀성(confidentiality), 데이터 무결성(integrity), 데이터 원본 인증(origin authentication)을 제공하는 표준입니다. 핵심 특징은 다음과 같습니다.
- 홉 단위(hop-by-hop) 보호: 종단 간(end-to-end) 보호가 아니라, 직접 연결된 두 장치(호스트↔스위치, 스위치↔스위치) 사이의 링크를 보호합니다.
- L2 투명성: IP 이상의 프로토콜에는 완전히 투명합니다. 상위 계층은 MACsec의 존재를 인식하지 못합니다.
- Secure Channel / Secure Association: 각 방향마다 독립된 Secure Channel(SC)이 존재하고, 각 SC 안에 최대 4개의 Secure Association(SA)이 키 로테이션을 위해 준비됩니다.
- 패킷 번호(PN): 각 SA는 단조 증가하는 32비트(또는 XPN에서 64비트) 패킷 번호를 유지하여 재전송(Retransmission) 공격을 방어합니다.
| 표준 문서 | 범위 | 핵심 내용 |
|---|---|---|
| IEEE 802.1AE-2006 | MACsec 프레임 형식, 보안 모델 | SecTAG, ICV, SCI, SC/SA 개념 정의 |
| IEEE 802.1AEbn-2011 | GCM-AES-256 추가 | 128비트 외에 256비트 키 지원 |
| IEEE 802.1AEbw-2013 | Extended Packet Numbering | 64비트 PN으로 고속 링크의 PN 소진 방지 |
| IEEE 802.1AEcg-2017 | 통합 개정판 | GCM-AES-XPN-128/256 추가 |
| IEEE 802.1X-2010 | MKA 프로토콜 | 키 합의, 키 서버 선출, SAK 분배 |
MACsec vs IPSec vs WireGuard vs kTLS 비교
네트워크 보안은 계층마다 다른 도구가 존재합니다. MACsec은 L2에서 동작하므로 다른 암호화 메커니즘과 경쟁이 아니라 보완 관계입니다.
| 항목 | MACsec (802.1AE) | IPSec / xfrm | WireGuard | kTLS |
|---|---|---|---|---|
| 동작 계층 | L2 (이더넷) | L3 (IP) | L3 (IP over UDP) | L4-7 (TLS) |
| 보호 범위 | 홉 단위 (point-to-point) | 종단 간 / 게이트웨이 | 종단 간 | 종단 간 |
| 암호 알고리즘 | GCM-AES-128/256, XPN | 다양 (협상) | ChaCha20-Poly1305 고정 | TLS 표준 스위트 |
| 키 합의 | MKA (EAPoL 기반) | IKEv2 | Noise_IKpsk2 | TLS 핸드셰이크 (유저스페이스) |
| 브로드캐스트/멀티캐스트 | 지원 | 제한적 | 미지원 | 미지원 |
| 라우팅(Routing) 가능성 | 중간 라우터가 복호화(Decryption) 필요 | 터널(Tunnel)/트랜스포트 모드 | AllowedIPs 라우팅 | TCP 커넥션 기반 |
| HW offload | NIC 레벨 (line-rate) | 일부 NIC/IPU | 미지원 | NIC TLS offload |
| 대표 용도 | 데이터센터 링크 암호화 | 사이트 간 VPN | 원격 접속 VPN | HTTPS 가속 |
SecTAG와 ICV 프레임 형식
MACsec은 원래 이더넷 프레임에 두 가지 요소를 추가합니다: 헤더 쪽의 SecTAG(Security Tag)와 꼬리 쪽의 ICV(Integrity Check Value)입니다.
| 필드 | 크기 | 설명 |
|---|---|---|
| MACsec EtherType | 2바이트 | 항상 0x88E5. 원래 EtherType 위치에 삽입됩니다. |
| TCI (Tag Control Info) | 6비트 | V(버전), ES(End Station), SC(SCI 포함 여부), SCB(Single Copy Broadcast), E(암호화), C(변경됨) 플래그 |
| AN (Association Number) | 2비트 | 현재 사용 중인 SA 번호 (0-3). 키 로테이션 시 변경됩니다. |
| SL (Short Length) | 1바이트 | Secure Data가 48바이트 미만일 때 실제 길이. 그 외에는 0입니다. |
| Packet Number (PN) | 4바이트 | 단조 증가하는 패킷 번호. replay protection과 GCM nonce 구성에 사용됩니다. |
| SCI (Secure Channel Identifier) | 8바이트 (선택) | 송신자 MAC 주소(6B) + Port Identifier(2B). point-to-point에서는 생략 가능합니다. |
| ICV | 8 또는 16바이트 | GCM-AES 인증 태그. 기본 16바이트, 단축(8바이트)은 보안성이 낮아 권장되지 않습니다. |
GCM-AES-128/256, GCM-AES-XPN 암호 스위트
MACsec은 AES-GCM (Galois/Counter Mode)만을 암호 스위트로 사용합니다. IPSec처럼 다양한 알고리즘을 협상하지 않으며, 표준에 정의된 4가지 스위트 중 하나를 선택합니다.
| Cipher Suite | Cipher Suite ID | 키 길이 | PN 크기 | 특징 |
|---|---|---|---|---|
| GCM-AES-128 | 0x0080C20001000001 | 128비트 | 32비트 | 기본(default) 스위트. 대부분의 구현이 지원합니다. |
| GCM-AES-256 | 0x0080C20001000002 | 256비트 | 32비트 | 더 강한 키. 양자 내성(quantum resistance) 여유를 확보합니다. |
| GCM-AES-XPN-128 | 0x0080C20001000003 | 128비트 | 64비트 | 고속 링크(40G/100G 이상)에서 PN 소진 방지. |
| GCM-AES-XPN-256 | 0x0080C20001000004 | 256비트 | 64비트 | 최고 보안 + 고속 링크 겸용. |
AES-GCM은 AEAD(Authenticated Encryption with Associated Data) 모드로, 암호화와 무결성 검증을 한 번의 연산으로 수행합니다. GCM의 nonce(IV)는 다음과 같이 구성됩니다:
/* GCM nonce (12바이트) 구성 */
struct macsec_gcm_nonce {
/* 표준 PN (32비트) */
u8 salt[4]; /* SAK와 함께 분배되는 고정 salt */
u8 iv[4]; /* 0으로 패딩 또는 SSCI */
u32 pn; /* 패킷 번호 (네트워크 바이트 순서) */
/* XPN (64비트) 일 때 */
/* salt[4] XOR SSCI || pn_upper[4] || pn_lower[4] */
};
MKA (MACsec Key Agreement) 프로토콜
MKA는 IEEE 802.1X-2010에 정의된 키 합의 프로토콜로, MACsec이 사용할 SAK를 안전하게 분배합니다. MKA는 EAPoL(Extensible Authentication Protocol over LAN) 프레임, 구체적으로 EAPoL-MKA (EtherType 0x888E)를 사용합니다.
MKA의 핵심 개념들:
- MKPDU (MKA Protocol Data Unit): EAPoL 프레임에 실려 전달되는 MKA 메시지입니다. 여러 Parameter Set을 포함합니다.
- MI (Member Identifier): 각 MKA 참여자를 식별하는 12바이트 랜덤 값입니다.
- MN (Message Number): MKPDU의 시퀀스 번호로, 재전송 공격을 방지합니다.
- CKN (Connectivity association Key Name): CAK를 식별하는 이름(최대 32바이트)입니다.
- Live Peer List / Potential Peer List: 인증 완료된 피어와 아직 확인 중인 피어의 목록입니다.
- Key Server: SAK 생성과 분배를 담당하는 참여자입니다. 우선순위(Priority)와 SCI로 선출됩니다.
CAK → ICK → KEK → SAK 키 계층 구조
MACsec의 키 계층은 단일 루트 키(CAK)에서 모든 운영 키를 파생하는 구조입니다.
| 키 | 파생 원본 | 용도 | 수명 |
|---|---|---|---|
| CAK | 사전 공유(PSK) 또는 EAP 인증 | 모든 하위 키의 루트. 직접 데이터 암호화에 사용되지 않음 | 관리자가 변경할 때까지 |
| CKN | 관리자 설정 또는 EAP MSK에서 파생 | CAK를 식별하는 이름 (키 자체가 아님) | CAK와 동일 |
| ICK | CAK + CKN (AES-CMAC KDF) | MKPDU의 ICV(무결성) 생성 및 검증 | CAK 변경 시 재파생 |
| KEK | CAK + CKN (AES-CMAC KDF) | SAK를 AES Key Wrap으로 래핑하여 분배 | CAK 변경 시 재파생 |
| SAK | 키 서버가 랜덤 생성 | 실제 데이터 프레임의 GCM-AES 암복호화 | 로테이션 주기 또는 PN 소진 시 |
# PSK 모드에서 CAK/CKN 예시
# CAK: 128비트 (16바이트 hex) 또는 256비트 (32바이트 hex)
CAK="0123456789abcdef0123456789abcdef"
# CKN: 최대 32바이트 hex, 보통 CAK와 같은 길이
CKN="0123456789abcdef0123456789abcdef"
SAK 로테이션과 키 서버 선출
MKA는 SAK를 주기적으로 로테이션하여 장기간 같은 키가 사용되는 것을 방지합니다. 키 서버 선출과 SAK 로테이션 메커니즘은 다음과 같습니다.
키 서버 선출 규칙
- 모든 참여자는 MKPDU에 Key Server Priority 값을 포함합니다 (0-255, 기본값 일반적으로 16).
- 낮은 우선순위 값이 더 높은 우선순위를 가집니다.
- 우선순위가 동일하면 낮은 SCI(MAC 주소 기반)가 키 서버가 됩니다.
- 키 서버만이 SAK를 생성하고 KEK로 래핑하여 분배할 수 있습니다.
SAK 로테이션 트리거
- PN 소진 임박: 32비트 PN이 임계값(기본 0xC0000000)에 도달하면 새 SAK가 필요합니다.
- 참여자 변경: 새 참여자가 합류하거나 기존 참여자가 이탈하면 새 SAK를 분배합니다.
- 정책 기반: 관리자가 설정한 주기에 따라 로테이션합니다.
- AN (Association Number) 순환: 새 SAK는 다음 AN(0→1→2→3→0)에 설치되고, 양측 확인 후 이전 SA가 제거됩니다.
Linux 커널 MACsec 아키텍처
Linux MACsec은 drivers/net/macsec.c에 구현된 가상 네트워크 디바이스입니다. 실제 물리 NIC(real_dev) 위에 MACsec 가상 디바이스(macsec_dev)를 얹는 구조로, VLAN 디바이스와 유사한 패턴입니다.
커널 MACsec 모듈의 주요 구성 요소:
- macsec_dev:
net_device를 확장한 가상 디바이스. 상위 스택에는 일반 이더넷 인터페이스처럼 보입니다. - real_dev: MACsec이 올라가는 실제 물리 NIC.
rx_handler가 등록되어 EtherType 0x88E5 프레임을 가로챕니다. - macsec_secy: SecY(Security Entity) 상태를 관리하는 구조체(Struct). TX SC, RX SC 목록, 암호 스위트, 검증 모드를 포함합니다.
- Crypto API 연동:
gcm(aes)AEAD transform을 사용. AES-NI가 있으면 하드웨어 가속됩니다. - Netlink 인터페이스:
RTM_NEWLINK/RTM_DELLINK와 MACsec 전용 속성으로 설정됩니다.
MACsec 가상 net_device 구조
MACsec 디바이스는 ARPHRD_ETHER 타입의 일반 이더넷 디바이스로 등록됩니다. ip link에서 macsec 타입으로 생성하며, 내부적으로 rtnl_link_ops를 통해 관리됩니다.
/* drivers/net/macsec.c - 주요 구조체 관계 */
struct macsec_dev {
struct macsec_secy secy; /* SecY 상태 */
struct net_device *real_dev; /* 하위 물리 NIC */
struct pcpu_secy_stats __percpu *stats; /* per-CPU 통계 */
struct list_head secys; /* real_dev 당 MACsec 디바이스 목록 */
struct gro_cells gro_cells; /* GRO 셀 */
enum macsec_offload offload; /* SW / HW offload 모드 */
};
/* net_device_ops */
static const struct net_device_ops macsec_netdev_ops = {
.ndo_init = macsec_dev_init,
.ndo_uninit = macsec_dev_uninit,
.ndo_open = macsec_dev_open,
.ndo_stop = macsec_dev_stop,
.ndo_start_xmit = macsec_start_xmit, /* TX 진입점 */
.ndo_change_mtu = macsec_change_mtu,
.ndo_set_mac_address = macsec_set_mac_address,
.ndo_get_stats64 = macsec_get_stats64,
.ndo_change_rx_flags = macsec_change_rx_flags,
.ndo_set_rx_mode = macsec_set_rx_mode,
};
MACsec 디바이스의 특징:
- MTU:
real_dev->mtu - (SecTAG 크기 + ICV 크기)로 자동 설정됩니다. - MAC 주소: 기본적으로 real_dev와 동일하지만, 독립적으로 변경할 수 있습니다.
- 하나의 real_dev에 여러 MACsec 디바이스: SCI가 다르면 동일 NIC 위에 여러 MACsec 인터페이스를 생성할 수 있습니다.
- promisc 모드: MACsec 디바이스가 올라오면 real_dev는 promiscuous 모드가 됩니다 (다른 MAC의 MACsec 프레임도 수신해야 하므로).
송신 경로: macsec_start_xmit() → SecTAG 삽입 → GCM 암호화
상위 스택이 MACsec 디바이스로 패킷을 보내면 macsec_start_xmit()이 호출됩니다. 이 함수는 원본 프레임에 SecTAG를 삽입하고 GCM-AES로 암호화한 뒤 real_dev를 통해 전송합니다.
/* TX 경로 핵심 코드 흐름 (단순화) */
static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct macsec_dev *macsec = macsec_priv(dev);
struct macsec_secy *secy = &macsec->secy;
struct macsec_tx_sc *tx_sc = &secy->tx_sc;
struct macsec_tx_sa *tx_sa;
/* 1. 활성 SA 선택 */
tx_sa = macsec_txsa_get(tx_sc->sa[tx_sc->encoding_sa]);
if (!tx_sa) goto drop;
/* 2. PN 할당 (32비트 또는 64비트) */
if (secy->xpn)
pn = atomic64_inc_return(&tx_sa->next_pn_halves.counter);
else
pn = atomic_inc_return(&tx_sa->next_pn_halves.pn32);
/* 3. PN 소진 체크 */
if (pn >= tx_sa->next_pn_halves.lower)
goto drop; /* PN wrapped - SAK 로테이션 필요 */
/* 4. SecTAG 삽입 + 암호화 */
macsec_encrypt(skb, dev);
return NETDEV_TX_OK;
}
수신 경로: macsec_handle_frame() → ICV 검증 → 복호화
real_dev에 도착한 EtherType 0x88E5 프레임은 rx_handler인 macsec_handle_frame()으로 전달됩니다.
수신 경로의 주요 검증 단계:
- SecTAG 유효성: EtherType, 버전 비트, TCI 플래그 조합이 유효한지 확인합니다.
- SCI 매칭: SecTAG의 SCI(또는 추론된 SCI)로 해당 RX SC를 검색합니다. 매칭되는 SC가 없으면 drop됩니다.
- SA 선택: AN 필드로 RX SA를 선택합니다. 해당 SA가 비활성이면 drop됩니다.
- GCM-AES 복호화: SA의 키로 페이로드를 복호화하고 ICV를 검증합니다. ICV 불일치는 즉시 drop + InPktsNotValid 증가.
- Replay check: PN이 윈도우 내에 있고 중복이 아닌지 확인합니다.
- 프레임 복원: SecTAG와 ICV를 제거하고 원래 EtherType을 복원하여 상위 스택으로 전달합니다.
패킷 번호 기반 Replay Protection
MACsec의 replay protection은 각 RX SA가 유지하는 패킷 번호 윈도우로 구현됩니다.
/* replay 윈도우 검사 (단순화) */
static bool macsec_pn_check(struct macsec_rx_sa *rx_sa, u32 pn)
{
u32 latest_pn = rx_sa->next_pn; /* 지금까지 수신한 최대 PN + 1 */
u32 window = rx_sa->replay_protect_window;
if (pn == 0)
return false; /* PN 0은 항상 무효 */
if (pn >= latest_pn)
return true; /* 새로운 PN → 항상 허용 */
if (latest_pn - pn > window)
return false; /* 윈도우 밖 → 너무 오래된 패킷 */
/* 윈도우 내 → 비트맵으로 중복 체크 */
return !test_bit(pn % window, rx_sa->replay_bitmap);
}
| 파라미터 | 설명 | 기본값 |
|---|---|---|
| replay_protect | replay protection 활성화 여부 | 활성 (on) |
| window | 허용하는 PN 순서 역전 범위 | 0 (엄격 순서, 역전 불허) |
SCI (Secure Channel Identifier)와 SA (Secure Association)
SCI와 SA의 관계는 MACsec 보안 모델의 핵심입니다.
| 개념 | 방향 | 수량 | 설명 |
|---|---|---|---|
| SecY | - | MACsec 디바이스당 1개 | 보안 엔티티. TX SC 1개 + RX SC 복수를 포함합니다. |
| SCI | - | SC당 1개 | MAC 주소(6B) + Port ID(2B) = 8바이트 식별자 |
| TX SC | 송신 | SecY당 정확히 1개 | 자신의 SCI를 가지며, 최대 4개의 TX SA를 포함 |
| RX SC | 수신 | 피어당 1개 (복수 가능) | 상대방의 SCI에 대응하며, 최대 4개의 RX SA를 포함 |
| SA | 양방향 | SC당 최대 4개 (AN 0-3) | 실제 키(SAK)와 PN 상태를 보유. 키 로테이션의 단위 |
| AN | 양방향 | 0, 1, 2, 3 | SecTAG에 포함되어 수신측이 어떤 SA/키를 사용할지 식별 |
주요 커널 자료구조
/* include/net/macsec.h - 핵심 자료구조 */
/* SecY: 보안 엔티티 */
struct macsec_secy {
struct net_device *netdev; /* 연결된 macsec net_device */
unsigned int n_rx_sc; /* RX SC 개수 */
sci_t sci; /* 자신의 SCI */
u16 key_len; /* SAK 길이 (16 또는 32바이트) */
u16 icv_len; /* ICV 길이 (8 또는 16바이트) */
enum macsec_validation_type validate_frames; /* strict/check/disabled */
bool xpn; /* Extended Packet Numbering */
bool operational; /* SecY 동작 상태 */
bool protect_frames; /* 송신 보호 활성화 */
bool replay_protect; /* replay protection */
u32 replay_window; /* replay 윈도우 크기 */
struct macsec_tx_sc tx_sc; /* 송신 SC (1개) */
struct macsec_rx_sc __rcu *rx_sc; /* 수신 SC 목록 (RCU) */
};
/* TX Secure Channel */
struct macsec_tx_sc {
bool encrypt; /* 암호화 활성화 (false면 무결성만) */
bool send_sci; /* SecTAG에 SCI 포함 여부 */
u8 encoding_sa; /* 현재 활성 TX SA 번호 (0-3) */
struct macsec_tx_sa __rcu *sa[MACSEC_NUM_AN]; /* TX SA 배열 */
struct pcpu_tx_sc_stats __percpu *stats;
};
/* TX Secure Association */
struct macsec_tx_sa {
struct macsec_key key; /* SAK + salt */
ssci_t ssci; /* Short SCI (XPN용) */
union {
atomic_t pn32; /* 32비트 PN 카운터 */
atomic64_t pn64; /* 64비트 PN 카운터 (XPN) */
} next_pn_halves;
bool active; /* SA 활성 상태 */
struct macsec_tx_sa_stats __percpu *stats;
struct rcu_head rcu;
};
/* RX Secure Channel */
struct macsec_rx_sc {
struct macsec_rx_sc __rcu *next; /* 다음 RX SC (linked list) */
sci_t sci; /* 상대방 SCI */
bool active;
struct macsec_rx_sa __rcu *sa[MACSEC_NUM_AN]; /* RX SA 배열 */
struct pcpu_rx_sc_stats __percpu *stats;
struct rcu_head rcu;
};
/* RX Secure Association */
struct macsec_rx_sa {
struct macsec_key key; /* SAK + salt */
ssci_t ssci;
atomic_t next_pn; /* 기대되는 다음 PN */
bool active;
struct macsec_rx_sa_stats __percpu *stats;
struct rcu_head rcu;
};
rcu_dereference()로, 구조체 변경은 rtnl_lock 아래에서 수행됩니다. 이는 MACsec이 고속 데이터 경로에서 락 없이 동작할 수 있게 합니다.
MACsec HW Offload 아키텍처
Linux 5.6부터 MACsec은 NIC 하드웨어에 암복호화를 위임할 수 있는 offload 인프라를 제공합니다. HW offload가 활성화되면 CPU는 SecTAG 삽입/제거와 GCM 연산을 수행하지 않으며, NIC가 line-rate로 처리합니다.
offload 모드는 두 가지입니다:
| 모드 | enum 값 | 설명 |
|---|---|---|
| Off (SW) | MACSEC_OFFLOAD_OFF |
기본값. 커널이 Crypto API로 모든 암복호화를 수행합니다. |
| PHY offload | MACSEC_OFFLOAD_PHY |
PHY 칩이 MACsec 처리. phy_device->macsec_ops를 사용합니다. |
| MAC offload | MACSEC_OFFLOAD_MAC |
NIC MAC 레벨에서 처리. netdev->macsec_ops를 사용합니다. |
macsec_ops 콜백(Callback)과 드라이버 구현
NIC 드라이버가 MACsec HW offload을 지원하려면 struct macsec_ops를 구현하고 등록해야 합니다.
/* include/net/macsec.h */
struct macsec_ops {
/* SecY 관리 */
int (*mdo_dev_open)(struct macsec_context *ctx);
int (*mdo_dev_stop)(struct macsec_context *ctx);
int (*mdo_add_secy)(struct macsec_context *ctx);
int (*mdo_upd_secy)(struct macsec_context *ctx);
int (*mdo_del_secy)(struct macsec_context *ctx);
/* TX SA 관리 */
int (*mdo_add_txsa)(struct macsec_context *ctx);
int (*mdo_upd_txsa)(struct macsec_context *ctx);
int (*mdo_del_txsa)(struct macsec_context *ctx);
/* RX SC 관리 */
int (*mdo_add_rxsc)(struct macsec_context *ctx);
int (*mdo_upd_rxsc)(struct macsec_context *ctx);
int (*mdo_del_rxsc)(struct macsec_context *ctx);
/* RX SA 관리 */
int (*mdo_add_rxsa)(struct macsec_context *ctx);
int (*mdo_upd_rxsa)(struct macsec_context *ctx);
int (*mdo_del_rxsa)(struct macsec_context *ctx);
/* 통계 */
int (*mdo_get_dev_stats)(struct macsec_context *ctx);
int (*mdo_get_tx_sc_stats)(struct macsec_context *ctx);
int (*mdo_get_tx_sa_stats)(struct macsec_context *ctx);
int (*mdo_get_rx_sc_stats)(struct macsec_context *ctx);
int (*mdo_get_rx_sa_stats)(struct macsec_context *ctx);
/* 인서트 모드 (선택) */
int (*mdo_insert_tx_tag)(struct macsec_context *ctx);
};
드라이버 구현 시 핵심 사항:
- macsec_context: 커널이 콜백에 전달하는 컨텍스트로, SecY, SC, SA 정보와 SAK를 포함합니다.
- 원자적(Atomic) 업데이트: SA 키 교체 시 트래픽 중단 없이 NIC 내부 테이블을 업데이트해야 합니다.
- 통계 콜백: HW offload 시 NIC가 카운터를 유지하므로,
mdo_get_*_stats로 이를 커널에 보고합니다. - fallback 없음: HW offload가 설정된 후에는 SW fallback이 자동으로 활성화되지 않습니다. NIC가 지원하지 않는 기능(예: XPN)을 요청하면 에러를 반환합니다.
HW Offload 지원 NIC
| 벤더 / 드라이버 | 칩 | offload 모드 | 특이사항 |
|---|---|---|---|
| Mellanox (NVIDIA) / mlx5 | ConnectX-6 Dx 이상 | MAC offload | GCM-AES-128/256, XPN 지원. 가장 완성도 높은 구현. |
| Intel / ice | E810 시리즈 | MAC offload | GCM-AES-128/256 지원. 6.x 커널에서 점진적으로 확장. |
| Marvell / mvpp2 | Armada 7K/8K | MAC offload | 임베디드/네트워킹 프로세서 기반. |
| NXP / felix (ocelot) | LS1028A, VSC7511 등 | MAC offload | 스위치 ASIC의 MACsec 엔진 활용. |
| Microchip / lan966x | LAN966x | MAC offload | 산업용/IoT 이더넷 스위치. |
| 다양한 PHY 벤더 | Vitesse/Microchip PHY 등 | PHY offload | PHY 내장 MACsec 엔진. MDIO로 제어. |
# NIC의 MACsec offload 지원 확인
ethtool -k eth0 | grep macsec
# macsec-hw-offload: on [requested on]
# offload 모드 설정 (ip link 생성 시)
ip link add link eth0 macsec0 type macsec sci 1 encrypt on offload mac
HW Offload 통계와 모니터링
HW offload 시 통계는 NIC 하드웨어 카운터에서 가져옵니다. ip -s macsec show는 offload 모드에 관계없이 동일한 형식으로 통계를 표시합니다.
# MACsec 통계 확인
ip -s macsec show
# 출력 예시:
# 3: macsec0: protect on validate strict sc off sa off encrypt on
# send_sci on end_station off scb off replay off
# cipher suite: GCM-AES-128, using ICV length 16
# TXSC: 001122334455005c on SA 0
# 0: PN 42857362, state on, key 01000000000000000000000000000000
# InPktsUntagged 0 InPktsNoTag 0
# InPktsOK 5827391
# InPktsInvalid 0 InPktsNotValid 0
# InPktsLate 0 InPktsDelayed 0
# InPktsNotUsingSA 0 InPktsUnusedSA 0
# OutPktsProtected 5827422
# OutPktsEncrypted 5827422
# 통계 카운터 의미:
# InPktsOK: 복호화+ICV 검증 성공
# InPktsInvalid: ICV 검증 실패 (validate=check 시에도 카운트)
# InPktsNotValid: ICV 검증 실패 + drop (validate=strict)
# InPktsLate: replay 윈도우 밖 (너무 오래된 PN)
# InPktsDelayed: replay 윈도우 내이지만 순서 역전
# OutPktsProtected: 보호된 송신 패킷 (무결성)
# OutPktsEncrypted: 암호화된 송신 패킷
ip macsec show 출력에 offload mac 또는 offload phy가 표시되면 HW offload가 활성화된 상태입니다. SW 모드에서는 이 필드가 나타나지 않습니다.
ip macsec 명령어 완전 가이드
iproute2의 ip macsec 하위 명령은 MACsec 디바이스와 SA를 관리하는 기본 도구입니다.
# === MACsec 디바이스 생성 ===
# 기본 생성 (GCM-AES-128, 암호화 활성)
ip link add link eth0 macsec0 type macsec encrypt on
# SCI 명시적 지정
ip link add link eth0 macsec0 type macsec \
sci 0x0011223344550001 encrypt on
# GCM-AES-256 스위트 사용
ip link add link eth0 macsec0 type macsec \
cipher gcm-aes-256 encrypt on
# GCM-AES-XPN-128 (64비트 PN, 고속 링크용)
ip link add link eth0 macsec0 type macsec \
cipher gcm-aes-xpn-128 encrypt on
# HW offload 활성화
ip link add link eth0 macsec0 type macsec \
encrypt on offload mac
# replay protection 활성화 (윈도우 크기 128)
ip link add link eth0 macsec0 type macsec \
encrypt on replay on window 128
# 무결성 전용 (암호화 안 함, ICV만)
ip link add link eth0 macsec0 type macsec \
encrypt off protect on
# === TX SA 설정 ===
# TX SA 추가 (AN 0, 초기 PN 1)
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 0123456789abcdef0123456789abcdef
# TX SA 추가 (AN 1, AES-256 키)
ip macsec add macsec0 tx sa 1 pn 1 on \
key 01 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
# XPN 모드 TX SA (salt와 ssci 지정)
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 0123456789abcdef0123456789abcdef \
salt 0123456789ab ssci 1
# === RX SC 및 RX SA 설정 ===
# 상대방의 RX SC 추가 (상대방의 SCI)
ip macsec add macsec0 rx 001122334455 port 1
# RX SA 추가 (동일한 SAK)
ip macsec add macsec0 rx 001122334455 port 1 sa 0 pn 1 on \
key 00 0123456789abcdef0123456789abcdef
# === 인터페이스 활성화 ===
ip link set macsec0 up
ip addr add 192.168.100.1/24 dev macsec0
# === 상태 확인 ===
# MACsec 상태 요약
ip macsec show
# 상세 통계
ip -s macsec show
# JSON 출력 (스크립트용)
ip -j macsec show | jq .
# === SA 상태 변경 ===
# TX SA 비활성화
ip macsec set macsec0 tx sa 0 off
# encoding_sa 변경 (키 로테이션)
ip link set macsec0 type macsec encodingsa 1
# === 삭제 ===
# SA 삭제
ip macsec del macsec0 tx sa 0
# RX SC 삭제
ip macsec del macsec0 rx 001122334455 port 1
# MACsec 디바이스 삭제
ip link del macsec0
wpa_supplicant MKA 설정
wpa_supplicant는 MKA 프로토콜의 유저스페이스 구현을 제공하며, MACsec 키 합의를 자동으로 수행합니다. 수동으로 SA를 설정하는 ip macsec과 달리, wpa_supplicant는 MKA를 통해 SAK를 자동 교환하고 로테이션합니다.
# wpa_supplicant 실행 예시
wpa_supplicant -i macsec0 -Dmacsec_linux -c /etc/wpa_supplicant/macsec.conf
# 또는 systemd 서비스로 실행
systemctl start wpa_supplicant-macsec@eth0
Static CAK/CKN 설정 (PSK 모드)
가장 간단한 MKA 설정은 Static CAK(사전 공유 키) 모드입니다. 양측에 동일한 CAK와 CKN을 설정하면 MKA가 자동으로 SAK를 합의합니다.
# /etc/wpa_supplicant/macsec-psk.conf
# --- 호스트 A ---
ctrl_interface=/var/run/wpa_supplicant
eapol_version=3
ap_scan=0
fast_reauth=1
network={
key_mgmt=NONE
eapol_flags=0
macsec_policy=1 # 1 = MACsec 필수
macsec_integ_only=0 # 0 = 암호화+무결성, 1 = 무결성만
macsec_replay_protect=1
macsec_replay_window=0
mka_cak=0123456789abcdef0123456789abcdef
mka_ckn=6162636465666768696a6b6c6d6e6f70
mka_priority=16 # 키 서버 우선순위 (0-255)
}
# --- 호스트 B ---
# 동일한 mka_cak, mka_ckn 사용
# mka_priority를 다르게 하면 키 서버 역할이 결정됨
# 양쪽 호스트에서 실행
# 호스트 A (eth0 = 직결 링크)
wpa_supplicant -i eth0 -Dmacsec_linux -c /etc/wpa_supplicant/macsec-psk.conf &
# MKA가 성공하면 자동으로 macsec0 인터페이스 생성
# IP 주소 할당
ip addr add 10.0.0.1/24 dev macsec0
ip link set macsec0 up
# MKA 상태 확인
wpa_cli -i eth0 status
# ... key_mgmt=NONE
# ... Supplicant PAE state=AUTHENTICATED
# ... MKA status: active
# SAK 교환 확인
ip -s macsec show
600으로 설정하고, 운영 환경에서는 EAP 기반 인증을 권장합니다. CAK가 유출되면 모든 파생 키(ICK, KEK, SAK)가 손상됩니다.
EAP 기반 MACsec (802.1X + MKA)
엔터프라이즈 환경에서는 RADIUS 서버와 802.1X EAP 인증을 결합하여 MACsec을 구성합니다. EAP 인증이 성공하면 MSK(Master Session Key)에서 CAK와 CKN이 자동 파생됩니다.
# /etc/wpa_supplicant/macsec-eap.conf
ctrl_interface=/var/run/wpa_supplicant
eapol_version=3
ap_scan=0
network={
key_mgmt=IEEE8021X
eap=TLS # 또는 PEAP, TTLS 등
eapol_flags=0
# EAP-TLS 인증서
identity="host-a@example.com"
ca_cert="/etc/pki/tls/certs/ca.pem"
client_cert="/etc/pki/tls/certs/host-a.pem"
private_key="/etc/pki/tls/private/host-a.key"
private_key_passwd="secret"
# MACsec 정책
macsec_policy=1
macsec_integ_only=0
macsec_replay_protect=1
macsec_replay_window=32
# EAP에서 CAK/CKN 자동 파생
# mka_cak/mka_ckn은 설정하지 않음!
}
EAP 기반 MACsec의 흐름:
- 802.1X 인증: Supplicant가 Authenticator(스위치)를 통해 RADIUS 서버와 EAP 인증을 수행합니다.
- MSK 파생: EAP 인증 성공 시 양측이 MSK(Master Session Key)를 공유합니다.
- CAK/CKN 파생: MSK에서 CAK와 CKN이 KDF로 파생됩니다.
- MKA 시작: CAK/CKN으로 MKA 프로토콜이 자동 시작되어 SAK를 합의합니다.
- MACsec 보호: SAK 합의 완료 후 데이터 프레임 보호가 시작됩니다.
| 항목 | PSK 모드 | EAP 모드 |
|---|---|---|
| CAK 소스 | 관리자가 수동 설정 | EAP MSK에서 자동 파생 |
| CKN 소스 | 관리자가 수동 설정 | EAP 세션 ID에서 자동 파생 |
| CAK 수명 | 관리자가 변경할 때까지 영구 | EAP 재인증 주기에 따라 갱신 |
| 확장성 | 수동 키 관리로 제한적 | RADIUS 중앙 관리로 대규모 적합 |
| 인프라 요구 | 없음 (호스트 쌍 설정만) | RADIUS 서버, PKI 인증서 필요 |
| 적합 환경 | 소규모, 서버 간 직결 | 엔터프라이즈, 대규모 데이터센터 |
systemd-networkd를 이용한 MACsec 설정
systemd 248+ 버전의 systemd-networkd는 MACsec 디바이스 설정을 기본 지원합니다. wpa_supplicant 없이 정적 키 모드의 MACsec을 구성할 수 있습니다.
# /etc/systemd/network/25-macsec.netdev
[NetDev]
Name=macsec0
Kind=macsec
[MACsec]
Port=1
Encrypt=yes
# /etc/systemd/network/25-macsec.network
[Match]
Name=macsec0
[Network]
Address=10.0.0.1/24
# /etc/systemd/network/25-macsec-key.keyfile
# (별도 키 파일, 권한 600)
[MACsecTransmitAssociation]
Number=0
PacketNumber=1
KeyId=00
Key=0123456789abcdef0123456789abcdef
[MACsecReceiveChannel]
MACAddress=aa:bb:cc:dd:ee:ff
Port=1
[MACsecReceiveAssociation]
Number=0
PacketNumber=1
KeyId=00
Key=0123456789abcdef0123456789abcdef
# 적용
systemctl restart systemd-networkd
networkctl status macsec0
데이터센터 East-West 트래픽 보호 패턴
MACsec의 가장 대표적인 용도는 데이터센터 내부(East-West) 링크 암호화입니다. 서버 간 또는 서버-TOR(Top of Rack) 스위치 간 직결 링크를 MACsec으로 보호하면, 물리적 케이블 도청(wiretapping)이나 중간자 공격(MITM)을 방어할 수 있습니다.
데이터센터 MACsec 배포 패턴
| 패턴 | 구간 | 키 관리 | 장점 |
|---|---|---|---|
| Host-to-TOR | 서버 NIC ↔ TOR 스위치 포트 | 서버별 PSK 또는 802.1X | 서버 측에서 제어 가능, NIC HW offload 활용 |
| Switch-to-Switch | TOR ↔ Spine/Leaf 스위치 | 스위치 쌍별 PSK | 패브릭 전체 암호화, ASIC 가속 |
| End-to-End (희소) | 서버 ↔ 서버 (직결) | 서버 쌍별 PSK | 스위치 불필요, 가장 단순한 구성 |
스위치 연동 (Cisco/Arista/Juniper MACsec 상호운용)
Linux 호스트의 MACsec을 엔터프라이즈 스위치와 연동하려면 양측의 설정을 맞춰야 합니다.
| 스위치 벤더 | MACsec 설정 위치 | 주의사항 |
|---|---|---|
| Cisco (IOS-XE/NX-OS) | mka policy, macsec 인터페이스 명령 |
CKN 길이를 64hex(32B)로 맞춰야 함. should-secure 모드 주의 |
| Arista (EOS) | mac security 프로파일 |
PSK fallback 정책 확인. LLDP와 MACsec 순서 주의 |
| Juniper (Junos) | set security macsec |
connectivity-association 이름과 CKN 매핑(Mapping) 확인 |
# Cisco IOS-XE 스위치와 Linux 호스트 연동 예시
# --- Cisco 스위치 측 (간략) ---
# mka policy my-policy
# key-server-priority 10
# macsec-cipher-suite gcm-aes-128
# interface GigabitEthernet1/0/1
# mka policy my-policy
# mka pre-shared-key key-chain my-keychain
# macsec
# --- Linux 호스트 측 ---
# /etc/wpa_supplicant/macsec-cisco.conf
ctrl_interface=/var/run/wpa_supplicant
eapol_version=3
ap_scan=0
network={
key_mgmt=NONE
eapol_flags=0
macsec_policy=1
macsec_integ_only=0
# Cisco와 동일한 CAK/CKN (CKN은 64 hex 문자 = 32바이트)
mka_cak=0123456789abcdef0123456789abcdef
mka_ckn=6162636465666768696a6b6c6d6e6f706162636465666768696a6b6c6d6e6f70
mka_priority=20
}
# 실행
wpa_supplicant -i eth0 -Dmacsec_linux -c /etc/wpa_supplicant/macsec-cisco.conf
성능 벤치마크 (SW vs HW Offload)
MACsec의 성능은 SW vs HW offload에 따라 극적으로 달라집니다. 소프트웨어 경로에서는 모든 패킷마다 GCM-AES 암복호화를 CPU가 수행해야 하므로, 고속 링크에서는 CPU가 병목(Bottleneck)이 됩니다. HW offload는 NIC 내장 crypto 엔진이 line-rate로 처리하므로 CPU 부담이 사실상 없습니다.
SW MACsec 성능 특성
소프트웨어 MACsec의 성능은 여러 요인에 의해 결정됩니다:
- AES-NI 유무: AES-NI(Intel) 또는 ARMv8-CE(ARM) 없이는 SW MACsec이 사실상 사용할 수 없을 만큼 느립니다. AES-NI가 있으면 단일 코어에서 ~5-8 Gbps, 없으면 ~500 Mbps 수준입니다.
- 패킷 크기: GCM-AES는 패킷당 고정 비용(nonce 설정, 태그 생성)이 있으므로, 작은 패킷일수록 오버헤드(Overhead) 비율이 높아집니다. 64바이트 패킷 대비 1500바이트 패킷에서 약 10배의 처리량(Throughput) 차이가 나타납니다.
- CPU 아키텍처: PCLMULQDQ(캐리 없는 곱셈) 명령어가 GCM의 GHASH 연산을 가속합니다. 최신 CPU일수록 GCM 처리량이 높습니다.
- NUMA 배치: NIC와 같은 NUMA 노드의 CPU가 crypto 처리를 하도록 IRQ affinity를 설정하면 캐시(Cache) 미스가 줄어 성능이 향상됩니다.
프레임 크기별 성능 영향
| 프레임 크기 | SW GCM-AES-128 (Mpps) | SW 처리량 (Gbps) | HW 처리량 (Gbps) | 비고 |
|---|---|---|---|---|
| 64 바이트 | ~1.5 | ~0.8 | line-rate | per-packet 오버헤드 지배적 |
| 256 바이트 | ~1.2 | ~2.5 | line-rate | |
| 512 바이트 | ~0.9 | ~3.7 | line-rate | |
| 1024 바이트 | ~0.7 | ~5.7 | line-rate | |
| 1500 바이트 | ~0.55 | ~6.6 | line-rate | 일반적인 MTU |
| 9000 바이트 (Jumbo) | ~0.18 | ~12.9 | line-rate | 처리량 최적 |
| 구성 | 처리량 (iperf3, TCP) | CPU 사용률 | 레이턴시 추가 |
|---|---|---|---|
| MACsec 없음 (baseline) | 25 Gbps | ~15% | - |
| SW MACsec (GCM-AES-128, AES-NI) | ~8-12 Gbps | ~90-100% | ~5-15 µs |
| SW MACsec (GCM-AES-256, AES-NI) | ~6-10 Gbps | ~90-100% | ~8-20 µs |
| HW Offload MACsec (ConnectX-6 Dx) | 25 Gbps (line-rate) | ~15% (baseline 동일) | ~1-2 µs |
| HW Offload MACsec (100G NIC) | 100 Gbps (line-rate) | 최소 | <1 µs |
# 성능 측정 예시
# 1. Baseline (MACsec 없음)
iperf3 -c 10.0.0.2 -t 30 -P 4
# 2. SW MACsec 측정
ip link add link eth0 macsec0 type macsec encrypt on
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 0123456789abcdef0123456789abcdef
ip macsec add macsec0 rx aabbccddeeff port 1 sa 0 pn 1 on \
key 00 0123456789abcdef0123456789abcdef
ip addr add 10.0.0.1/24 dev macsec0
ip link set macsec0 up
iperf3 -c 10.0.0.2 -t 30 -P 4
# 3. CPU 프로파일링 (SW 경로 병목 확인)
perf top -g -p $(pgrep iperf3)
# gcm_encrypt, aesni_gcm_enc 등이 상위에 나타남
# 4. MTU 영향 측정 (작은 패킷 vs 큰 패킷)
iperf3 -c 10.0.0.2 -t 10 -l 64 # 작은 패킷
iperf3 -c 10.0.0.2 -t 10 -l 1400 # 큰 패킷
# 작은 패킷에서 per-packet GCM 오버헤드가 두드러짐
- SW MACsec에서는 AES-NI가 필수입니다.
lscpu | grep aes로 확인하세요. - 점보 프레임(MTU 9000)을 사용하면 per-packet GCM 오버헤드 비율이 줄어 처리량이 향상됩니다.
- 25G 이상에서는 HW offload 없이는 실용적이지 않습니다.
- NUMA-aware IRQ 배치로 NIC와 동일 NUMA 노드의 CPU가 crypto를 처리하도록 하세요.
레이턴시 분석
MACsec이 추가하는 레이턴시는 주로 GCM-AES 연산 시간입니다:
| 경로 | 추가 레이턴시 | 구성 요소 |
|---|---|---|
| SW MACsec TX | ~3-8 µs | SecTAG 삽입 + GCM encrypt + skb 조작 |
| SW MACsec RX | ~3-10 µs | GCM decrypt + ICV 검증 + replay check + SecTAG 제거 |
| HW Offload TX/RX | ~0.5-2 µs | NIC 파이프라인(Pipeline) 내 처리 (wire delay에 가까움) |
| MKA MKPDU 처리 | 유저스페이스 | wpa_supplicant 처리 시간 (데이터 경로 아님) |
# 레이턴시 측정 (단방향 근사)
# sockperf 사용
sockperf ping-pong -i 10.0.0.2 -t 60 --full-rtt
# 또는 qperf 사용
# 서버: qperf
# 클라이언트: qperf 10.0.0.2 tcp_lat udp_lat
MACsec과 네트워크 네임스페이스(Namespace)
MACsec 디바이스는 네트워크 네임스페이스 간 이동이 가능합니다. 이를 활용하면 컨테이너(Container) 환경에서 MACsec 보호를 적용할 수 있습니다.
# MACsec + 네트워크 네임스페이스 예시
# 1. 기본 네임스페이스에서 MACsec 디바이스 생성
ip link add link eth0 macsec0 type macsec encrypt on
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 0123456789abcdef0123456789abcdef
ip macsec add macsec0 rx aabbccddeeff port 1 sa 0 pn 1 on \
key 00 0123456789abcdef0123456789abcdef
# 2. 네임스페이스 생성 및 MACsec 이동
ip netns add secure-ns
ip link set macsec0 netns secure-ns
# 3. 네임스페이스 내에서 IP 설정
ip netns exec secure-ns ip addr add 10.0.0.1/24 dev macsec0
ip netns exec secure-ns ip link set macsec0 up
ip netns exec secure-ns ip link set lo up
# 4. 네임스페이스 내에서 통신 테스트
ip netns exec secure-ns ping 10.0.0.2
# 주의: real_dev(eth0)는 원래 네임스페이스에 남아 있어야 합니다.
# MACsec 디바이스만 이동할 수 있습니다.
MACsec과 VLAN/Bridge 환경
MACsec과 VLAN 태깅의 순서는 중요한 설계 결정입니다. IEEE 802.1AE 표준에서는 두 가지 모드를 정의합니다.
| 모드 | 프레임 구조 | 특징 |
|---|---|---|
| VLAN 외부 MACsec (MACsec before VLAN) |
Dst|Src|SecTAG|VLAN|IP...|ICV | VLAN 태그도 암호화/무결성 보호됨. 스위치가 VLAN을 볼 수 없음. |
| VLAN 내부 MACsec (MACsec after VLAN) |
Dst|Src|VLAN|SecTAG|IP...|ICV | VLAN 태그가 평문. 스위치가 VLAN 기반 포워딩 가능. |
# Linux에서 MACsec + VLAN 구성
# 방법 1: MACsec 위에 VLAN (MACsec이 먼저, VLAN 태그 보호됨)
ip link add link eth0 macsec0 type macsec encrypt on
# (SA 설정 생략)
ip link add link macsec0 name macsec0.100 type vlan id 100
ip addr add 10.100.0.1/24 dev macsec0.100
# 방법 2: VLAN 위에 MACsec (VLAN이 먼저, 스위치가 VLAN 볼 수 있음)
ip link add link eth0 name eth0.100 type vlan id 100
ip link add link eth0.100 macsec0 type macsec encrypt on
# (SA 설정 생략)
ip addr add 10.100.0.1/24 dev macsec0
# Bridge 환경
# MACsec 디바이스를 bridge 멤버로 추가 가능
ip link add br0 type bridge
ip link set macsec0 master br0
ip link set br0 up
트러블슈팅과 디버깅(Debugging)
# === 1단계: MACsec 인터페이스 상태 확인 ===
# 인터페이스 존재 및 상태
ip link show type macsec
ip -d link show macsec0
# MACsec 상세 설정 확인
ip macsec show
# cipher suite, encrypt, protect, validate, replay 설정 확인
# === 2단계: SA 상태와 키 매칭 확인 ===
# TX/RX SA가 올바르게 설정되었는지
ip macsec show
# TX SA와 RX SA가 모두 "on" 상태인지
# 양측의 키(key ID)가 일치하는지
# AN 번호가 매칭되는지
# === 3단계: 통계로 문제 진단 ===
ip -s macsec show
# InPktsOK > 0 → 정상 수신 동작
# InPktsNotValid > 0 → ICV 검증 실패 → 키 불일치 또는 프레임 손상
# InPktsNoTag > 0 → MACsec 없는 프레임 수신 (상대가 MACsec 미설정?)
# InPktsLate > 0 → replay 윈도우 밖 → 윈도우 크기 증가 필요
# OutPktsProtected = 0 → TX SA 미설정 또는 비활성
# === 4단계: 실시간 프레임 캡처 ===
# real_dev에서 MACsec 프레임 캡처 (암호화된 상태)
tcpdump -i eth0 ether proto 0x88e5 -c 20 -vv
# macsec_dev에서 복호화된 프레임 캡처
tcpdump -i macsec0 -c 20
# MKA(EAPoL) 프레임 확인
tcpdump -i eth0 ether proto 0x888e -c 10 -vv
# === 5단계: wpa_supplicant MKA 디버깅 ===
# wpa_supplicant를 디버그 모드로 실행
wpa_supplicant -i eth0 -Dmacsec_linux -c /etc/wpa_supplicant/macsec.conf -dd
# wpa_cli로 MKA 상태 실시간 확인
wpa_cli -i eth0 status
wpa_cli -i eth0 mib
# === 6단계: ftrace로 커널 경로 추적 ===
# MACsec 함수 추적
echo 'macsec_*' > /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
# === 7단계: 일반적인 문제와 해결 ===
# 문제: 양측 ping 실패, InPktsNotValid 증가
# 원인: 키 불일치 (양측 SAK가 다름)
# 해결: CAK/CKN 또는 수동 설정 키가 양측에서 동일한지 확인
# 문제: MKA 세션이 수립되지 않음
# 원인: EAPoL 프레임이 도달하지 않음
# 해결: 중간 스위치가 EtherType 0x888E를 차단하지 않는지 확인
# 문제: HW offload 실패 ("Operation not supported")
# 원인: NIC가 요청된 cipher suite를 지원하지 않음
# 해결: ethtool -k eth0 | grep macsec 확인, SW 모드 fallback
# 문제: InPktsLate 급증
# 원인: 패킷 순서 역전이 replay 윈도우를 초과
# 해결: replay window 크기 증가 (ip link 재생성 필요)
일반적인 문제 체크리스트
| 증상 | 확인 카운터 | 가능한 원인 | 해결 방법 |
|---|---|---|---|
| 양측 통신 불가 | OutPktsProtected = 0 | TX SA 미설정 또는 비활성 | ip macsec show로 TX SA 상태 확인, on 설정 |
| 단방향만 통신 | 한쪽 InPktsOK=0 | RX SC/SA 미설정 또는 SCI 불일치 | 양측의 SCI와 RX SC 설정 확인 |
| 간헐적 패킷 손실 | InPktsLate 증가 | replay 윈도우 초과 | replay window 크기 증가 (128, 256 등) |
| 모든 패킷 drop | InPktsNotValid 증가 | 키 불일치 (SAK가 다름) | 양측의 key hex 값 동일한지 확인 |
| MKA 세션 미수립 | MACsec 인터페이스 미생성 | EAPoL 프레임 차단, CAK/CKN 불일치 | tcpdump -i eth0 ether proto 0x888e로 MKA 프레임 도달 확인 |
| HW offload 설정 실패 | RTNETLINK: Operation not supported | NIC가 MACsec offload 미지원 | ethtool -k eth0 | grep macsec 확인, SW 모드 사용 |
| MTU 관련 단편화(Fragmentation) | 정상 카운터, 큰 패킷만 실패 | SecTAG+ICV로 인한 MTU 초과 | macsec0 MTU 확인, 점보 프레임 또는 상위 MTU 감소 |
| 성능 저하 | InPktsOK 정상, 처리량 낮음 | SW 경로에서 CPU 병목 | HW offload 활성화, AES-NI 확인, IRQ affinity 조정 |
커널 로그와 동적 디버깅
# 커널 MACsec 관련 메시지 확인
dmesg | grep -i macsec
# 동적 디버그 활성화 (커널에 CONFIG_DYNAMIC_DEBUG 필요)
echo 'module macsec +p' > /sys/kernel/debug/dynamic_debug/control
dmesg -w | grep macsec
# 네트워크 이벤트 모니터링
ip monitor link type macsec
# perf로 SW 경로 병목 분석
perf record -g -a -- sleep 10
perf report --sort=comm,dso,symbol
# gcm_encrypt, aesni_gcm_enc, macsec_encrypt_finish 등 확인
# bpftrace로 MACsec TX/RX 경로 관찰
bpftrace -e 'kprobe:macsec_start_xmit { @tx = count(); }
kprobe:macsec_handle_frame { @rx = count(); }
interval:s:1 { print(@tx); print(@rx); clear(@tx); clear(@rx); }'
커널 빌드 옵션
| Kconfig 옵션 | 기본값 | 설명 |
|---|---|---|
CONFIG_MACSEC |
m (모듈) | MACsec 핵심 모듈 (macsec.ko). 이것 없이는 MACsec 사용 불가. |
CONFIG_CRYPTO_GCM |
y | GCM 모드. MACsec의 암호 스위트에 필수. |
CONFIG_CRYPTO_AES |
y | AES 블록 암호. GCM-AES에 필수. |
CONFIG_CRYPTO_AES_NI_INTEL |
m | AES-NI 하드웨어 가속. SW MACsec 성능에 결정적. |
CONFIG_CRYPTO_SEQIV |
y | 시퀀스 IV 생성. GCM nonce 관리에 필요. |
CONFIG_NET_MACSEC |
- | 일부 커널 버전에서 CONFIG_MACSEC의 별칭. |
# 현재 커널의 MACsec 관련 설정 확인
zcat /proc/config.gz 2>/dev/null | grep -i macsec
# 또는
grep -i macsec /boot/config-$(uname -r)
# MACsec 모듈 로드 확인
lsmod | grep macsec
# 수동 모듈 로드
modprobe macsec
# MACsec 모듈 정보
modinfo macsec
CONFIG_MACSEC=m으로 MACsec 모듈을 제공합니다. ip link add type macsec 시 커널이 자동으로 모듈을 로드합니다.
HW Offload 관련 드라이버 Kconfig
| 드라이버 | Kconfig | 설명 |
|---|---|---|
| mlx5 (Mellanox/NVIDIA) | CONFIG_MLX5_MACSEC |
ConnectX-6 Dx+ MACsec offload. CONFIG_MLX5_CORE 필요. |
| ice (Intel) | CONFIG_ICE |
E810 MACsec은 별도 Kconfig 없이 드라이버에 포함. |
| ocelot/felix (NXP) | CONFIG_MSCC_OCELOT_SWITCH_LIB |
LS1028A 등 NXP 스위치 ASIC의 MACsec. |
| lan966x (Microchip) | CONFIG_LAN966X_SWITCH |
LAN966x 내장 MACsec 엔진. |
유저스페이스 도구 요구사항
| 도구 | 패키지 | 최소 버전 | 용도 |
|---|---|---|---|
ip macsec |
iproute2 | 4.6+ | MACsec 디바이스/SA 수동 관리 |
wpa_supplicant |
wpa_supplicant | 2.6+ (macsec_linux 드라이버) | MKA 프로토콜 (자동 SAK 교환) |
wpa_cli |
wpa_supplicant | 2.6+ | MKA 상태 모니터링 |
ethtool |
ethtool | 5.4+ | HW offload 지원 확인 |
tcpdump |
tcpdump | 4.9+ | MACsec/EAPoL 프레임 캡처 |
# 배포판별 패키지 설치
# RHEL/CentOS/Fedora
dnf install iproute wpa_supplicant ethtool tcpdump
# Ubuntu/Debian
apt install iproute2 wpasupplicant ethtool tcpdump
# SLES/openSUSE
zypper install iproute2 wpa_supplicant ethtool tcpdump
# wpa_supplicant MACsec 드라이버 확인
wpa_supplicant -h 2>&1 | grep macsec
# drivers: ... macsec_linux ...
전체 설정 예제: 두 호스트 간 정적 키 MACsec
가장 기본적인 사용 사례로, 두 Linux 호스트가 직결 이더넷 링크로 연결된 환경에서 ip macsec만으로 MACsec을 구성하는 전체 예제입니다.
# ============================================
# 호스트 A (eth0 MAC: aa:bb:cc:dd:ee:01)
# ============================================
# 1. MACsec 디바이스 생성
ip link add link eth0 macsec0 type macsec \
encrypt on replay on window 64
# 2. TX SA 설정 (AN 0)
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 ad7a2bd03eac835a6f620fdcb506b345
# 3. RX SC 추가 (호스트 B의 MAC)
ip macsec add macsec0 rx aabbccddeeff port 1
# 4. RX SA 설정 (호스트 B와 동일한 키)
ip macsec add macsec0 rx aabbccddeeff port 1 sa 0 pn 1 on \
key 00 ad7a2bd03eac835a6f620fdcb506b345
# 5. 인터페이스 활성화 및 IP 할당
ip link set macsec0 up
ip addr add 10.0.0.1/24 dev macsec0
# ============================================
# 호스트 B (eth0 MAC: aa:bb:cc:dd:ee:ff)
# ============================================
# 1. MACsec 디바이스 생성
ip link add link eth0 macsec0 type macsec \
encrypt on replay on window 64
# 2. TX SA 설정 (AN 0, 동일 키)
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 ad7a2bd03eac835a6f620fdcb506b345
# 3. RX SC 추가 (호스트 A의 MAC)
ip macsec add macsec0 rx aabbccddeeff01 port 1
# 4. RX SA 설정
ip macsec add macsec0 rx aabbccddeeff01 port 1 sa 0 pn 1 on \
key 00 ad7a2bd03eac835a6f620fdcb506b345
# 5. 인터페이스 활성화 및 IP 할당
ip link set macsec0 up
ip addr add 10.0.0.2/24 dev macsec0
# ============================================
# 검증
# ============================================
# 호스트 A에서:
ping 10.0.0.2
ip -s macsec show
# 암호화된 프레임 확인 (eth0에서)
tcpdump -i eth0 ether proto 0x88e5 -c 5
# 복호화된 프레임 확인 (macsec0에서)
tcpdump -i macsec0 icmp -c 5
MACsec 프레임 변환 상세
MACsec은 원본 이더넷 프레임을 보호된 프레임으로 변환합니다. 이 과정에서 SecTAG(Security Tag) 삽입, 페이로드 암호화, ICV(Integrity Check Value) 추가가 순차적으로 수행됩니다. 변환 전후의 프레임 구조를 정확히 이해하면 패킷 캡처 분석과 트러블슈팅이 훨씬 수월해집니다.
암호화 모드 변환 (Encrypt + Authenticate)
기본 모드에서는 원본 페이로드 전체가 GCM-AES로 암호화되고, 프레임 끝에 ICV가 추가됩니다.
| 필드 | 원본 프레임 | MACsec 프레임 | 변화 |
|---|---|---|---|
| Dst MAC | 6바이트 | 6바이트 (그대로) | 변경 없음 |
| Src MAC | 6바이트 | 6바이트 (그대로) | 변경 없음 |
| EtherType | 원본 (0x0800 등) | 0x88E5 (MACsec) | SecTAG로 대체 |
| SecTAG | — | 8~16바이트 | 신규 삽입 |
| Payload | 평문 | 암호문 | GCM-AES 암호화 |
| 원본 EtherType | — | 암호화된 페이로드에 포함 | SecTAG 뒤에 매립 |
| ICV | — | 8~16바이트 | 신규 추가 |
| FCS | 4바이트 | 4바이트 (재계산) | 전체 프레임 기반 재계산 |
무결성 전용 모드 변환 (Authenticate Only)
macsec_integ_only=1로 설정하면 페이로드를 암호화하지 않고 무결성 검증만 수행합니다. 디버깅이나 QoS 장비가 페이로드를 검사해야 하는 환경에서 유용합니다.
# 무결성 전용 모드 설정
ip link add link eth0 macsec0 type macsec encrypt off
# encrypt off = 무결성만, encrypt on = 암호화+무결성(기본)
# tcpdump로 확인: 0x88E5이지만 페이로드는 평문
tcpdump -i eth0 -X ether proto 0x88e5 -c 1
# SecTAG의 SC bit 확인: E=0 (암호화 안 함)
GCM AAD(Additional Authenticated Data) 범위
GCM-AES 모드에서 AAD(Additional Authenticated Data, 추가 인증 데이터)에 포함되는 영역과 암호화되는 영역은 명확히 구분됩니다:
| 영역 | AAD (무결성 보호) | 암호화 | 설명 |
|---|---|---|---|
| Dst MAC + Src MAC | O | X | L2 헤더는 평문, 무결성만 보호 |
| SecTAG | O | X | 보안 태그 자체는 평문 |
| Secure Data (페이로드) | O | O (encrypt 모드) | 암호화 + 무결성 동시 보호 |
| ICV | — | — | GCM 인증 태그 출력값 |
MKA 키 교환 프로토콜 상세
MKA(MACsec Key Agreement)는 IEEE 802.1X-2010에서 정의된 키 합의 프로토콜로, EAPoL-MKA 프레임(EtherType 0x888E)을 통해 동작합니다. MKA의 핵심 동작 단계와 타이머, 상태 머신을 상세히 분석합니다.
MKA 세션 수립 단계
- 피어 발견 (Peer Discovery): 각 참여자가 주기적으로(기본 2초) MKA Hello 메시지를 전송하여 동일 CA(Connectivity Association) 멤버를 발견합니다.
- 라이브 피어 확인 (Live Peer Confirmation): 수신한 MKA PDU에서 자신의 MI(Member Identifier)를 확인하면 해당 피어를 Live Peer List에 등록합니다.
- 키 서버 선출 (Key Server Election): 키 서버 우선순위(0~255, 낮을수록 우선)와 SCI를 비교하여 키 서버를 선출합니다.
- SAK 분배 (SAK Distribution): 키 서버가 랜덤 SAK를 생성하고, KEK로 암호화(key wrap)하여 Distributed SAK 파라미터 세트로 전송합니다.
- SAK 확인 (SAK Confirmation): 수신자가 SAK를 설치하고 MKA PDU에 SAK 사용 시작을 알리면, 양쪽이 동일 SAK로 데이터를 보호합니다.
MKA 타이머와 임계값
| 타이머 | 기본값 | 설정 가능 범위 | 설명 |
|---|---|---|---|
| MKA Hello 주기 | 2초 | 1~10초 | MKA PDU 전송 간격 |
| MKA Life Time | 6초 (Hello × 3) | — | 피어 응답 없으면 삭제 |
| SAK Rekey 주기 | 무한 (PN 소진 시) | 사용자 설정 | SAK 교체 주기 |
| Bounded Hello | 500ms | — | SAK 분배 시 빠른 교환 |
| Suspend-on-Request | 비활성 | — | 키 서버 전환 시 일시 중단 |
MKA PDU 파라미터 세트
MKA PDU 구조 (EAPoL-MKA, EtherType 0x888E):
┌─────────────────────────────────────┐
│ EAPoL 헤더 (4바이트) │
│ Version=3, Type=MKA │
├─────────────────────────────────────┤
│ Basic Parameter Set (필수) │
│ - SCI (8B), MI (12B), MN (4B) │
│ - Key Server Priority, MACsec CI │
├─────────────────────────────────────┤
│ Live Peer List (가변) │
│ - 각 피어: MI (12B) + MN (4B) │
├─────────────────────────────────────┤
│ Potential Peer List (가변) │
│ - 발견했으나 미확인 피어 │
├─────────────────────────────────────┤
│ Distributed SAK (키 서버만 전송) │
│ - KEK로 래핑된 SAK │
│ - AN, Cipher Suite ID │
├─────────────────────────────────────┤
│ ICV Indicator (16바이트) │
│ - ICK로 계산한 MKA PDU 무결성 │
└─────────────────────────────────────┘
SAK 생성과 래핑
/* SAK 생성 흐름 (개념 코드) */
/* 1. 랜덤 SAK 생성 */
get_random_bytes(sak, cipher_suite_key_len); /* 16B 또는 32B */
/* 2. KEK로 SAK 래핑 (AES Key Wrap, RFC 3394) */
aes_key_wrap(kek, sak, sak_len, wrapped_sak);
/* 3. Distributed SAK 파라미터 세트 구성 */
dist_sak.an = next_association_number; /* 0~3 */
dist_sak.cipher_suite = GCM_AES_128;
memcpy(dist_sak.wrapped_sak, wrapped_sak, wrapped_len);
/* 4. MKA PDU에 포함하여 전송 */
mka_send_pdu(participant, &dist_sak);
/* 수신 측: KEK로 SAK 언래핑 후 커널에 설치 */
aes_key_unwrap(kek, wrapped_sak, wrapped_len, sak);
install_sak_to_kernel(macsec_dev, sak, an);
하드웨어 오프로드 드라이버 구현 상세
NIC 드라이버가 MACsec HW offload을 지원하려면 struct macsec_ops의 콜백을 구현하고, netdev->macsec_ops 또는 phydev->macsec_ops에 등록해야 합니다. 이 섹션에서는 드라이버 개발자 관점에서 구현 패턴을 분석합니다.
드라이버 등록 패턴
/* NIC 드라이버의 MACsec offload 등록 */
static const struct macsec_ops my_macsec_ops = {
.mdo_dev_open = my_macsec_dev_open,
.mdo_dev_stop = my_macsec_dev_stop,
.mdo_add_secy = my_macsec_add_secy,
.mdo_upd_secy = my_macsec_upd_secy,
.mdo_del_secy = my_macsec_del_secy,
.mdo_add_rxsc = my_macsec_add_rxsc,
.mdo_upd_rxsc = my_macsec_upd_rxsc,
.mdo_del_rxsc = my_macsec_del_rxsc,
.mdo_add_rxsa = my_macsec_add_rxsa,
.mdo_upd_rxsa = my_macsec_upd_rxsa,
.mdo_del_rxsa = my_macsec_del_rxsa,
.mdo_add_txsa = my_macsec_add_txsa,
.mdo_upd_txsa = my_macsec_upd_txsa,
.mdo_del_txsa = my_macsec_del_txsa,
.mdo_get_dev_stats = my_macsec_get_dev_stats,
.mdo_get_tx_sc_stats = my_macsec_get_tx_sc_stats,
.mdo_get_rx_sc_stats = my_macsec_get_rx_sc_stats,
};
/* probe 시 등록 */
static int my_nic_probe(struct pci_dev *pdev, ...)
{
...
netdev->macsec_ops = &my_macsec_ops;
netdev->features |= NETIF_F_HW_MACSEC;
...
}
오프로드 콜백 호출 흐름
| 사용자 명령 | 커널 호출 | 드라이버 콜백 | HW 동작 |
|---|---|---|---|
ip link add macsec0 | macsec_newlink() | mdo_add_secy() | SecY 컨텍스트 생성 |
ip link set macsec0 up | macsec_dev_open() | mdo_dev_open() | MACsec 엔진 활성화 |
ip macsec add tx sa 0 | macsec_add_txsa() | mdo_add_txsa() | TX SA 키 프로그래밍 |
ip macsec add rx sci | macsec_add_rxsc() | mdo_add_rxsc() | RX SC 필터 등록 |
ip macsec add rx sa 0 | macsec_add_rxsa() | mdo_add_rxsa() | RX SA 키 프로그래밍 |
ip link del macsec0 | macsec_dellink() | mdo_del_secy() | 전체 정리 |
SA 키 설치 구현 예
/* TX SA 추가 콜백 구현 예 */
static int my_macsec_add_txsa(struct macsec_context *ctx)
{
struct my_hw_priv *priv = netdev_priv(ctx->netdev);
struct macsec_tx_sa *tx_sa = ctx->sa.tx_sa;
u8 an = ctx->sa.assoc_num;
int ret;
/* 1. HW에 키 프로그래밍 */
ret = my_hw_program_key(priv,
tx_sa->key.id,
tx_sa->key.tfm, /* crypto tfm에서 키 추출 */
an,
true); /* is_tx = true */
if (ret)
return ret;
/* 2. 초기 PN(Packet Number) 설정 */
my_hw_set_pn(priv, an, tx_sa->next_pn, true);
/* 3. SA 활성화 */
if (tx_sa->active)
my_hw_enable_sa(priv, an, true);
return 0;
}
소프트웨어 vs 하드웨어 성능 심층 분석
MACsec의 성능은 소프트웨어(CPU) 처리와 하드웨어(NIC) 오프로드 간에 극적인 차이를 보입니다. AES-NI 명령어가 있는 현대 x86 CPU에서도 25Gbps 이상에서는 SW 처리의 CPU 부담이 급증합니다.
| 측정 항목 | SW MACsec (AES-NI) | HW Offload | 비고 |
|---|---|---|---|
| 1G 처리량 | ~940 Mbps | ~940 Mbps | 1G에서는 차이 미미 |
| 10G 처리량 | ~8.5 Gbps | ~9.9 Gbps | SW 15% 손실 |
| 25G 처리량 | ~16 Gbps | ~24.5 Gbps | SW 36% 손실 |
| 100G 처리량 | ~25 Gbps (병목) | ~98 Gbps | SW에서 100G 불가 |
| CPU 사용률 (10G) | ~200% (2코어) | ~5% | HW offload 40배 절감 |
| 추가 지연 (latency) | ~5~15 us | ~0.5~1 us | HW가 10배 낮음 |
| 소형 패킷(64B) PPS | ~2M pps | ~14.8M pps (10G) | SW는 per-pkt crypto 오버헤드 |
SW 경로 병목 분석
# CPU 프로파일링으로 MACsec SW 병목 확인
perf top -p $(pgrep -f iperf3) -g
# 주요 함수:
# - gcm_hash_crypt_done (GCM 인증 태그 계산)
# - aesni_gcm_enc/dec (AES-NI 암복호화)
# - macsec_encrypt_finish (SecTAG/ICV 조립)
# - skb_copy_bits (데이터 복사)
# iperf3로 MACsec 성능 벤치마크
# 서버 측:
iperf3 -s -B 10.0.0.1
# 클라이언트 측 (macsec0 인터페이스 사용):
iperf3 -c 10.0.0.1 -B 10.0.0.2 -t 30 -P 4
# -P 4: 4개 병렬 스트림으로 멀티코어 활용
# HW offload 전환 후 비교:
ip macsec offload macsec0 mac
iperf3 -c 10.0.0.1 -B 10.0.0.2 -t 30 -P 4
# CPU 사용률과 처리량 비교
XPN (Extended Packet Numbering) 성능 이점
기본 MACsec은 32비트 PN을 사용하여 약 40억 패킷 후 SAK를 교체해야 합니다. 100Gbps 링크에서 64바이트 패킷을 전송하면 약 30초만에 PN이 소진됩니다. GCM-AES-XPN은 64비트 PN을 사용하여 이 문제를 해결합니다.
| 항목 | 표준 PN (32비트) | XPN (64비트) |
|---|---|---|
| 최대 패킷 수 | 232 (~43억) | 264 (~1.8×1019) |
| 100G 64B 소진 | ~29초 | ~39,000년 |
| SAK 교체 빈도 | 매우 빈번 | 실질적으로 불필요 |
| 교체 시 패킷 손실 | 발생 가능 | 해당 없음 |
| SecTAG 크기 | 동일 (하위 32비트만 전송) | 동일 |
| 커널 지원 | 4.6+ | 5.11+ |
멀티홉 MACsec과 WAN 환경
MACsec은 원래 단일 L2 홉(포인트-투-포인트)을 보호하도록 설계되었습니다. 그러나 MPLS/VPLS 등 사업자 네트워크를 통과하는 WAN 환경이나 멀티홉 토폴로지에서도 MACsec을 적용할 수 있습니다.
멀티홉 토폴로지 패턴
| 토폴로지 | MACsec 적용 | 키 관리 | 특징 |
|---|---|---|---|
| 포인트-투-포인트 | 호스트 A ←→ 호스트 B | 단일 CA, PSK 또는 EAP | 가장 단순, 서버 간 직결 |
| 허브-스포크 | 스위치 ←→ 각 서버 | 각 포트별 독립 CA | TOR-서버 간, MACsec 지원 스위치 필수 |
| 체인 (홉-바이-홉) | A ←→ SW1 ←→ SW2 ←→ B | 각 링크별 독립 CA | 스위치에서 복호화→재암호화 |
| WAN 투명 전송 | CE A ←→ PE ←→ PE ←→ CE B | CE 간 단일 CA | 사업자 망에서 MACsec 프레임 투명 전달 |
WAN MACsec 고려사항
# WAN 환경 MACsec 설정 시 고려사항
# 1. MTU 조정: SecTAG(16B) + ICV(16B) = 32B 오버헤드
# WAN 측 MTU가 1500이면 MACsec 디바이스 MTU는 1468
ip link set eth0 mtu 1532 # 또는
ip link set macsec0 mtu 1468 # 페이로드 MTU 축소
# 2. XPN 필수: WAN 고속 링크에서 32비트 PN 소진 방지
ip link add link eth0 macsec0 type macsec \
cipher gcm-aes-xpn-128 \
sci on
# 3. Replay Window 확대: WAN 지터로 패킷 순서 변경 가능
ip link set macsec0 type macsec replay on window 256
# 4. SCI 명시적 포함: 다중 피어 환경
ip link add link eth0 macsec0 type macsec sci on
실전 구성: 포인트-투-포인트 완전 예제
두 Linux 서버 간 MACsec을 처음부터 끝까지 구성하는 완전한 예제입니다. PSK 모드와 MKA 자동 키 교환 모드 두 가지를 모두 포함합니다.
PSK 수동 설정 (MKA 없음)
#!/bin/bash
# ============================================
# MACsec PSK 수동 설정 (MKA 미사용)
# 호스트 A: eth0 = aa:bb:cc:dd:ee:01
# 호스트 B: eth0 = aa:bb:cc:dd:ee:02
# ============================================
# 공통 키 (양측 동일, 보안 채널로 교환)
KEY="0123456789abcdef0123456789abcdef"
# --- 호스트 A ---
# 1. MACsec 디바이스 생성 (GCM-AES-128, 암호화 활성)
ip link add link eth0 macsec0 type macsec \
sci on encrypt on \
cipher gcm-aes-128
# 2. TX SA 설정 (AN=0)
ip macsec add macsec0 tx sa 0 pn 1 on \
key 00 ${KEY}
# 3. RX SC 추가 (상대방 MAC + 포트)
ip macsec add macsec0 rx \
address aa:bb:cc:dd:ee:02 port 1
# 4. RX SA 설정 (상대방과 동일한 키)
ip macsec add macsec0 rx \
address aa:bb:cc:dd:ee:02 port 1 \
sa 0 pn 1 on key 00 ${KEY}
# 5. 인터페이스 활성화 및 IP 할당
ip link set macsec0 up
ip addr add 10.0.0.1/24 dev macsec0
# --- 호스트 B --- (대칭 설정, MAC 주소만 반전)
ip link add link eth0 macsec0 type macsec \
sci on encrypt on cipher gcm-aes-128
ip macsec add macsec0 tx sa 0 pn 1 on key 00 ${KEY}
ip macsec add macsec0 rx address aa:bb:cc:dd:ee:01 port 1
ip macsec add macsec0 rx address aa:bb:cc:dd:ee:01 port 1 \
sa 0 pn 1 on key 00 ${KEY}
ip link set macsec0 up
ip addr add 10.0.0.2/24 dev macsec0
스위치 연동 설정 예 (Cisco/Arista)
! ============================================
! Cisco Nexus 9000 MACsec 설정 (인터페이스 모드)
! ============================================
! 1. MACsec 키체인 설정
key chain macsec-keychain macsec
key 01
key-octet-string 0123456789abcdef0123456789abcdef
cryptographic-algorithm AES_128_CMAC
key-string 6162636465666768696a6b6c6d6e6f70
send-lifetime local 00:00:00 Jan 01 2026 infinite
! 2. MACsec 정책 설정
macsec policy my-policy
cipher-suite GCM-AES-128
key-server-priority 16
replay-protection window-size 64
! 3. 인터페이스에 MACsec 적용
interface Ethernet1/1
macsec keychain macsec-keychain policy my-policy
no shutdown
# ============================================
# Arista EOS MACsec 설정
# ============================================
! 1. MACsec 프로파일
macsec profile my-profile
cipher aes128-gcm
key 01 7 0123456789abcdef0123456789abcdef
mka key-server priority 16
! 2. 인터페이스 적용
interface Ethernet1
macsec profile my-profile
hostapd MACsec Authenticator 설정
스위치가 아닌 Linux 서버가 MACsec Authenticator 역할을 수행할 때, hostapd를 사용하여 802.1X 인증과 MKA를 동시에 처리할 수 있습니다. 이는 소프트웨어 정의 네트워크(SDN) 환경이나 저가형 스위치 없는 직결 구성에서 유용합니다.
# /etc/hostapd/macsec-auth.conf
# hostapd를 MACsec Authenticator로 설정
interface=eth0
driver=macsec_linux
# 802.1X Authenticator 모드
ieee8021x=1
eapol_version=3
eap_reauth_period=3600
# RADIUS 서버 연결
auth_server_addr=10.10.10.1
auth_server_port=1812
auth_server_shared_secret=radius_secret
# MACsec 정책
macsec_policy=1
macsec_integ_only=0
macsec_replay_protect=1
macsec_replay_window=0
# MKA 키 서버 우선순위
mka_priority=0 # 0 = 최우선 키 서버
mka_cak_length=128 # 128 또는 256비트
# hostapd 실행
hostapd -d /etc/hostapd/macsec-auth.conf
# 인증 상태 확인
hostapd_cli sta
# addr=aa:bb:cc:dd:ee:02
# flags=[AUTH][ASSOC][AUTHORIZED]
# dot1xAuthSessionId=xxx
# MKA 세션 상태
hostapd_cli mka_status
# MKA Session: active
# SAK: installed
# Key Server: yes
인증 흐름
| 단계 | 프로토콜 | 동작 |
|---|---|---|
| 1 | EAPoL | Supplicant(클라이언트)가 EAP-Start 전송 |
| 2 | EAP-TLS | hostapd가 RADIUS와 중계하여 상호 인증 |
| 3 | RADIUS | 인증 성공 → MSK(Master Session Key) 수신 |
| 4 | KDF | MSK에서 CAK + CKN 파생 |
| 5 | MKA | hostapd(키 서버)가 SAK 생성 및 분배 |
| 6 | MACsec | 양측 macsec0 인터페이스 활성화, 데이터 보호 시작 |
Session-Timeout 속성으로 재인증 주기를 설정하면 CAK가 주기적으로 갱신됩니다. 일반적으로 3600초(1시간)~86400초(24시간) 사이가 권장됩니다.
참고자료
- IEEE 802.1AE-2018 — MACsec 표준 규격을 정의하는 IEEE 공식 문서입니다.
- IEEE 802.1X-2020 — 포트 기반 네트워크 접근 제어(PNAC) 표준을 정의합니다.
- Kernel MACsec Documentation — 리눅스 커널 공식 MACsec 문서입니다.
- drivers/net/macsec.c — MACsec 커널 드라이버 소스 코드입니다.
- wpa_supplicant — MKA 프로토콜 및 MACsec 키 관리를 지원하는 인증 클라이언트입니다.
- hostapd — 802.1X 인증 서버로 MACsec 환경의 RADIUS 연동을 지원합니다.
- ip-macsec(8) man page —
ip macsec명령어의 사용법을 설명하는 매뉴얼 페이지입니다. - Open vSwitch MACsec — OVS 환경에서 MACsec을 연동하는 방법을 안내합니다.
- Intel ice 드라이버 문서 — Intel NIC의 MACsec 하드웨어 오프로드 기능을 설명합니다.
- Cisco MACsec Design Guide — 엔터프라이즈 환경에서의 MACsec 배포 설계 가이드입니다.
- RFC 3748 — EAP(Extensible Authentication Protocol) 명세를 정의합니다.
- RFC 5247 — EAP 키 관리 프레임워크를 정의합니다.
- NIST SP 800-120 — EAP 메서드에 대한 NIST 권장 사항입니다.
- NIST SP 800-38D — GCM(Galois/Counter Mode) 인증 암호화 명세입니다.