How to Configure Declarative MACsec Encryption on Ubuntu Server Using systemd-networkd

In modern enterprise data centres and multi-tenant cloud environments, securing communication between physically linked servers is essential. While Transport Layer Security (TLS) and IPsec operate at higher protocol layers (Layers 4 and 3 respectively), unencrypted Layer 2 frames remain vulnerable to packet sniffing, ARP spoofing, man-in-the-middle interception, and VLAN hopping attacks. The IEEE 802.1AE standard, commonly known as Media Access Control Security (MACsec), provides line-rate hardware-accelerated encryption, integrity verification, and replay protection directly at the Ethernet link layer.

On Ubuntu Server, while administrators can provision transient MACsec links using ip link commands, production environments require declarative, persistent configuration that initialises automatically during boot and recovers seamlessly from link carrier flaps. The native systemd-networkd daemon provides first-class support for declarative MACsec virtual devices (.netdev) and interface bindings (.network), delivering deterministic, encrypted point-to-point links across physical network infrastructure.

Understanding MACsec Architecture and Pre-Shared Keys

MACsec operates by intercepting Ethernet frames immediately above the physical medium attachment unit, encrypting frame payloads using the Galois/Counter Mode Advanced Encryption Standard (AES-GCM-128 or AES-GCM-256), and appending an authenticated Security Tag (SecTAG) and Integrity Check Value (ICV).

Key architectural concepts in MACsec include:

  • Secure Channel Identifier (SCI): An 8-byte identifier combining the transmitting interface’s MAC address with a 16-bit port identifier, uniquely distinguishing the stream.
  • Connectivity Association (CA): A cryptographic security association shared between participating nodes. In static pre-shared key deployments, this is defined by a Connectivity Association Key Name (CKN) and a Connectivity Association Key (CAK).
  • Replay Protection: An anti-replay window mechanism ensuring that intercepted or out-of-order packets outside a declared window threshold are dropped at the driver level.

Prerequisites and Kernel Module Verification

Configuring MACsec on Ubuntu Server requires administrative root privileges, active systemd-networkd, and the macsec Linux kernel module.

Load the kernel module and verify support:

# Load macsec module into the running kernel
sudo modprobe macsec

# Verify module presence
lsmod | grep macsec

# Ensure module loads automatically across system reboots
echo "macsec" | sudo tee /etc/modules-load.d/macsec.conf

Confirm that systemd-networkd is active and managing physical interfaces on the host:

# Check networkd service status
systemctl is-active systemd-networkd

# Identify physical network interfaces
networkctl list

Assume enp3s0 represents the primary physical Ethernet adapter connecting directly to a remote peer server.

Generating Cryptographic Pre-Shared Keys (CKN and CAK)

Static MACsec configurations rely on a shared 32-character (16-byte) hexadecimal Connectivity Association Key Name (CKN) and a matching 32-character hexadecimal Connectivity Association Key (CAK).

Generate secure random keys on an administrative workstation:

# Generate 16-byte hex CKN (32 hex characters)
openssl rand -hex 16

# Generate 16-byte hex CAK (32 hex characters)
openssl rand -hex 16

Example generated key material:

  • CKN: 0123456789abcdef0123456789abcdef
  • CAK: fedcba9876543210fedcba9876543210

Both interconnected Ubuntu Server nodes must share identical CKN and CAK values.

Creating the Declarative MACsec Virtual Device (.netdev)

In systemd-networkd, virtual network devices are defined within /etc/systemd/network/*.netdev configuration files.

Create the MACsec device definition file:

sudo nano /etc/systemd/network/20-macsec0.netdev

Populate the configuration with the MACsec specification:

[NetDev]
Name=macsec0
Kind=macsec

[MACsec]
Encrypt=yes
Cipher=GCM-AES-128
ReplayWindow=1024

[MACsecReceiveChannel]
Port=1
MACAddress=52:54:00:12:34:56

[MACsecReceiveAssociation]
KeyId=0
PacketNumber=1
KeyName=0123456789abcdef0123456789abcdef
Key=fedcba9876543210fedcba9876543210

[MACsecTransmitAssociation]
KeyId=0
PacketNumber=1
KeyName=0123456789abcdef0123456789abcdef
Key=fedcba9876543210fedcba9876543210

In the [MACsecReceiveChannel] block, specify the physical MAC address of the remote peer interface. Restrict filesystem permissions on this file, as it contains cleartext cryptographic key material:

sudo chmod 600 /etc/systemd/network/20-macsec0.netdev

Binding the MACsec Device to the Physical Interface (.network)

Next, configure the underlying physical adapter to instantiate the virtual MACsec device, and assign IP addressing to the encrypted interface.

Configure the physical carrier interface in /etc/systemd/network/10-enp3s0.network:

[Match]
Name=enp3s0

[Network]
MACsec=macsec0
LinkLocalAddressing=no

Create the corresponding network profile for the virtual macsec0 device in /etc/systemd/network/25-macsec0.network:

[Match]
Name=macsec0

[Network]
Address=10.100.1.1/24

On the peer node, apply the reciprocal configuration using Address=10.100.1.2/24 and specifying Node 1’s physical MAC address in its receive channel definition.

Applying Configuration and Verifying Encrypted Traffic

Reload systemd-networkd to compile the configuration files and bring up the encrypted tunnel:

# Reload networkd configurations
sudo networkctl reload

# Re-evaluate network interfaces
networkctl status macsec0

Inspect the low-level kernel MACsec status using ip macsec show:

# Verify MACsec secure channels and active transmit associations
ip macsec show

The output confirms encryption parameters, active SCI channels, replay window status, and transmitted/received packet counts.

To verify that Ethernet payloads are completely encrypted across physical wire segments, run tcpdump on the underlying physical interface while sending traffic over macsec0:

# Capture packets on raw physical interface
sudo tcpdump -i enp3s0 -nn -e

Packets captured on enp3s0 display the 0x88e5 (IEEE 802.1AE MACsec) EtherType with encrypted ciphertext payloads, while applications bound to macsec0 exchange standard unencrypted IP packets seamlessly.

By defining MACsec declaratively with systemd-networkd, Ubuntu Server administrators deliver tamper-proof Layer 2 security with automated boot recovery and zero manual operational overhead.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.