4、MACsec配置实战:Linux下MACsec配置、密钥协商、VLAN集成
好,咱们直接进入正题。MACsec 这东西,说白了就是在以太网帧的尾巴上贴个「安全封条」。你想想看,车载网络里那么多 ECU 在一条总线上喊话,万一哪个节点被篡改了,那可不是闹着玩的。我当年在做一个 T-Box 项目时,就遇到过隔壁实验室的测试设备误发报文,差点把网关搞死机。从那以后,我对链路层加密就特别上心。
4.1 环境准备:你需要什么?
在动手之前,先把家伙事儿备齐。我个人习惯用 Ubuntu 20.04 或更新的版本,内核至少 5.0 以上。为什么?因为老内核的 MACsec 支持有坑,我踩过。
- 硬件:两台 Linux 主机,或者一台主机加一个虚拟机。网卡得支持 MACsec 卸载功能(比如 Intel i210、i350),否则性能会打折扣。
- 软件:安装
wpasupplicant和libnl-3-dev。命令很简单:sudo apt install wpasupplicant。 - 内核模块:确认
macsec模块已加载。lsmod | grep macsec看看,没有的话就sudo modprobe macsec。
CONFIG_MACSEC 打开。我有一回忘了,折腾了半天才发现模块没编进去。
4.2 手动配置:先跑通再说
咱们先从最原始的方式开始——手动配置密钥。这种方式不依赖任何密钥协商协议,适合调试和验证。
4.2.1 创建 MACsec 设备
假设你的物理网卡是 eth0,IP 是 192.168.1.10/24。我们要在上面创建一个 MACsec 虚拟接口。
# 在主机 A 上
sudo ip link add link eth0 macsec0 type macsec cipher default
sudo ip link set macsec0 up
sudo ip addr add 192.168.1.10/24 dev macsec0
# 在主机 B 上(假设物理网卡也是 eth0,IP 192.168.1.20/24)
sudo ip link add link eth0 macsec0 type macsec cipher default
sudo ip link set macsec0 up
sudo ip addr add 192.168.1.20/24 dev macsec0
嗯,这里要注意:cipher default 默认是 GCM-AES-128。如果你需要 256 位密钥,可以改成 cipher gcm-aes-256。不过车载场景下 128 位已经够用了,别过度设计。
4.2.2 配置安全通道和关联
MACsec 的核心概念是「安全通道(SC)」和「安全关联(SA)」。一个 SC 包含多个 SA,每个 SA 对应一个密钥。咱们先创建一个 SC,再往里塞一个 SA。
# 主机 A 上:配置发送端
sudo ip macsec add macsec0 tx sa 0 pn 1 on key 01 1234567890abcdef1234567890abcdef
sudo ip macsec set macsec0 tx sa 0
# 主机 A 上:配置接收端(对端是 B,MAC 地址假设为 aa:bb:cc:dd:ee:ff)
sudo ip macsec add macsec0 rx port 1 address aa:bb:cc:dd:ee:ff
sudo ip macsec add macsec0 rx port 1 address aa:bb:cc:dd:ee:ff sa 0 pn 1 on key 01 1234567890abcdef1234567890abcdef
等等,别急着复制。你得把 aa:bb:cc:dd:ee:ff 换成主机 B 的真实 MAC 地址。怎么查?ip link show eth0 就能看到。
主机 B 上的配置是对称的,只是 MAC 地址要换成主机 A 的。
1234567890abcdef1234567890abcdef 只是演示,生产环境必须用随机数生成器产生。我曾经见过有人把密钥写在脚本里,结果代码泄露了……嗯,不说了。
4.2.3 验证连通性
配置完后,从主机 A ping 主机 B 的 MACsec 接口 IP:
ping -c 4 192.168.1.20
如果能通,恭喜你,MACsec 已经跑起来了。你可以用 ip -s macsec show 查看加密统计信息。看看 InPktsDecrypted 和 OutPktsEncrypted 是不是在增长。
4.3 密钥协商:用 wpa_supplicant 实现 802.1X
手动配密钥太累了,而且密钥不会自动更新。在车载环境里,你不可能让维修工去敲命令行换密钥。所以我们需要 802.1X 密钥协商。
这里我用 wpa_supplicant 来扮演 supplicant 角色。它本来是为 Wi-Fi 设计的,但也能驱动 MACsec。
4.3.1 配置 wpa_supplicant
创建一个配置文件 /etc/wpa_supplicant/macsec0.conf:
network={
key_mgmt=IEEE8021X
eap=MD5
identity="user1"
password="secret123"
macsec_policy=1
macsec_integ_only=0
mka_cak=00112233445566778899aabbccddeeff
mka_ckn=abcdef1234567890
}
这里 mka_cak 是 Connectivity Association Key,mka_ckn 是 Key Name。这两个参数在预共享密钥模式下是必须的。如果是用 RADIUS 服务器,就不需要手动指定了。
4.3.2 启动 wpa_supplicant
sudo wpa_supplicant -i macsec0 -c /etc/wpa_supplicant/macsec0.conf -D macsec_linux
加上 -d 参数可以看调试信息。如果看到 MKA: Key server elected 之类的日志,说明密钥协商成功了。
这时候你再 ping 一下,流量就已经是加密的了。而且密钥会定期刷新,默认是每 2 小时一次。你可以通过 mka_life_time 参数调整。
4.4 VLAN 集成:让 MACsec 和 VLAN 共存
车载网络里 VLAN 很常见,比如把摄像头流量和诊断流量隔离开。那 MACsec 和 VLAN 怎么一起用?顺序很重要。
我建议的架构是:先做 VLAN,再做 MACsec。也就是说,在物理网卡上创建 VLAN 子接口,然后在 VLAN 子接口上创建 MACsec 设备。
4.4.1 创建 VLAN 接口
# 在物理网卡 eth0 上创建 VLAN 100
sudo ip link add link eth0 name eth0.100 type vlan id 100
sudo ip link set eth0.100 up
4.4.2 在 VLAN 上叠加 MACsec
# 在 eth0.100 上创建 MACsec 接口
sudo ip link add link eth0.100 macsec0.100 type macsec cipher default
sudo ip link set macsec0.100 up
sudo ip addr add 10.0.100.1/24 dev macsec0.100
这样,VLAN 标签在 MACsec 加密之前就已经打上了。接收端会先解密,再剥离 VLAN 标签。你想想看,如果反过来,先加密再打 VLAN 标签,那交换机就看不到 VLAN 信息了,没法做转发。
| 方案 | 封装顺序 | 适用场景 |
|---|---|---|
| VLAN over MACsec | 先加密,再打 VLAN 标签 | 交换机需要看到 VLAN 信息做转发 |
| MACsec over VLAN | 先打 VLAN 标签,再加密 | 需要端到端加密,交换机只做透传 |
我个人更推荐 MACsec over VLAN,因为加密是在终端设备上完成的,中间交换机不需要知道密钥,安全性更高。
4.5 性能调优:别让加密拖慢车速
MACsec 加密会消耗 CPU 资源。在车载环境下,ECU 的算力通常有限。我建议做几件事:
- 开启硬件卸载:如果网卡支持,用
ethtool -K eth0 macsec-hw-offload on开启。实测能降低 60% 的 CPU 占用。 - 调整 MTU:MACsec 会增加 32 字节的开销(SecTAG + ICV)。所以物理网卡的 MTU 要设成 1532,否则大包会被分片。
- 使用 GCM-AES-128:256 位密钥虽然更安全,但性能下降明显。车载内部网络,128 位足够了。
嗯,差不多就这些。MACsec 配置其实不复杂,但细节很多。你只要记住:密钥别硬编码、VLAN 顺序别搞反、硬件卸载能开就开。做到这三点,基本不会出大问题。