Real-World Problem: The 2:15 AM Rogue MAC Alert
At 2:15 AM last Tuesday, our SIEM triggered a severity-one alert. An unknown MAC address was sweeping our 10.100.40.0/24 management subnet at roughly 450 ARP requests per second. Ten minutes prior, interface Gi1/0/24 on our core stack (SW-CORE-02) had flapped from down to up. That drop terminated in an unmonitored third-floor conference room.
Someone had bypassed our edge firewalls simply by plugging an Ethernet patch cable into an open RJ45 wall jack. It could have been an outsourced cleaner with a drop plug or a contractor hooking up an unapproved laptop. Within 45 seconds, the rogue client pulled an IP address via DHCP and started scanning internal hosts.
Wired office networks frequently suffer from blind trust. While Wi-Fi SSIDs demand WPA3-Enterprise and rigorous MFA, physical Ethernet jacks across conference rooms and empty cubicles often sit wide open. Plug in a cable, and the switch immediately forwards your frames.
Root Cause Analysis: Why Port Security and MAC Filtering Fail
When our team analyzed how the rogue machine slipped past our perimeter controls, the weaknesses were obvious:
- MAC Filtering Fails Instantly: We used static MAC bindings on edge ports. An attacker running Wireshark or tcpdump can capture valid frames and clone an authorized MAC address in 10 seconds with
ip link set dev eth0 address 00:1a:2b:3c:4d:5e. - Sticky MAC Verifies Nothing: Switch-level sticky MAC counts addresses, but it never validates cryptographic identity or host health. Once learned, it accepts any machine presenting that header.
- Unmanaged Linux Access Bridges: Edge appliances, hypervisors, and software bridges frequently lack central authentication agents. They bridge Ethernet traffic across interfaces without checking credentials first.
Without an active challenge-response handshake at Layer 2, Ethernet bridges listen to ARP, pass DHCP requests, and expose your routing topology to any rogue device.
Solutions Compared: Locking Down the Physical Port
We tested three methods to gate physical Linux bridge ports before settling on an architecture:
Option 1: Static MAC Binding and Dynamic ARP Inspection (DAI)
DAI and DHCP snooping stop ARP poisoning, but they cannot stop a bad actor with a cloned MAC and static IP from sniffing broadcast frames. Managing static MAC lists for 350 rotating employee laptops is also an administrative nightmare.
Option 2: Captive Portals
Captive portals operate at Layer 3 and Layer 4. The port must already be online and issuing IP addresses. A scanner can still flood the broadcast domain or exploit local network stack vulnerabilities before anyone opens a browser to authenticate.
Option 3: IEEE 802.1X Port-Based Network Access Control (PNAC)
802.1X operates directly at Layer 2. The switch port starts in an unauthorized state, silently dropping all IPv4, IPv6, ARP, and DHCP packets. The interface accepts only EAPOL (Extensible Authentication Protocol over LAN) frames. Until the connecting machine authenticates against an upstream RADIUS directory, the data port stays shut.
The Solution: 802.1X Wired Authentication via hostapd
Engineers usually associate hostapd with Wi-Fi access points. However, it also includes a production-grade wired 802.1X authenticator driver. If you run a Linux-based access switch, an edge gateway, or a software bridge, hostapd can manage port authorization states while handing EAP handshakes off to FreeRADIUS or Microsoft NPS.
In our setup, 802.1X wired handshakes complete in under 90 milliseconds, keeping unauthorized devices completely isolated from the bridge.
Step 1: Install hostapd and Bridge Utilities
Install the required network packages on your Debian or Ubuntu host:
sudo apt-get update
sudo apt-get install -y hostapd bridge-utils
Step 2: Configure the Bridge and Raw Interface
Create a dedicated bridge (e.g., br0) and attach your physical port (eth1). The access interface must not hold an IP address. Keep it raw so hostapd can intercept EAPOL frames directly:
# Create the bridge and attach eth1
sudo ip link add name br0 type bridge
sudo ip link set dev eth1 master br0
sudo ip link set dev eth1 up
sudo ip link set dev br0 up
# Put eth1 into promiscuous mode for raw frame capture
sudo ip link set dev eth1 promisc on
Step 3: Configure hostapd for Wired 802.1X
Create /etc/hostapd/wired-8021x.conf. Specify driver=wired, bind the bridge, and enable 802.1X control:
# /etc/hostapd/wired-8021x.conf
# Interface wired to the wall drop or patch panel
interface=eth1
bridge=br0
# Use the wired driver instead of nl80211
driver=wired
# Enable 802.1X and standard PAE group MAC (01:80:c2:00:00:03)
ieee8021x=1
use_pae_group_addr=1
# Upstream FreeRADIUS / NPS Server
auth_server_addr=192.168.10.50
auth_server_port=1812
auth_server_shared_secret=RadSecretKey987!
# RADIUS Accounting
acct_server_addr=192.168.10.50
acct_server_port=1813
acct_server_shared_secret=RadSecretKey987!
# Handshake timers (in seconds)
quiet_period=30
reauth_period=3600
For standalone testing environments without a RADIUS server, you can authenticate locally using an internal user file:
# Standalone lab fallback
eap_user_file=/etc/hostapd/hostapd.eap_user
Populate /etc/hostapd/hostapd.eap_user with your lab credentials:
# PEAP-MSCHAPv2 test account
"sec_audit" PEAP
"sec_audit" MSCHAPV2 "Sup3rS3cur3P@ss!" [2]
Step 4: Run hostapd in the Foreground for Debugging
Before launching hostapd as a background daemon, run it with verbose debugging enabled to trace incoming EAP packets:
sudo hostapd -dd -t /etc/hostapd/wired-8021x.conf
When a client connects, inspect the EAP-Request/Identity exchange in your terminal:
eth1: IEEE 802.1X: Received EAPOL packet (34 bytes) from 00:1a:2b:3c:4d:5e
eth1: IEEE 802.1X: EAPOL-Start from 00:1a:2b:3c:4d:5e
eth1: IEEE 802.1X: Sending EAP-Request/Identity to 00:1a:2b:3c:4d:5e
eth1: IEEE 802.1X: Received EAP-Response/Identity (sec_audit)
eth1: Sending RADIUS Access-Request to 192.168.10.50:1812
eth1: Received RADIUS Access-Accept
eth1: IEEE 802.1X: 00:1a:2b:3c:4d:5e authorized
Once hostapd validates the credentials, it sets the bridge port state to forwarding. Frames begin passing normally through br0.
Step 5: Configure the Client Supplicant
On a connected Linux test laptop, configure wpa_supplicant to authenticate over the wire. Write the profile to /etc/wpa_supplicant/wired-client.conf:
# /etc/wpa_supplicant/wired-client.conf
ctrl_interface=/var/run/wpa_supplicant
ap_scan=0
network={
key_mgmt=IEEE8021X
eap=PEAP
identity="sec_audit"
password="Sup3rS3cur3P@ss!"
phase2="auth=MSCHAPV2"
}
Initialize the supplicant against your client NIC:
sudo wpa_supplicant -i eth0 -D wired -c /etc/wpa_supplicant/wired-client.conf -B
After the authentication message confirms success, grab an IP lease from the DHCP pool:
sudo dhclient eth0
If someone plugs in an unmanaged device without an active 802.1X supplicant, hostapd discards their frames. DHCP discovery packets never reach the server, and ARP requests drop at the port. The link stays up physically, but the intruder sees zero responses.
Step 6: Enable the Systemd Service
Lock in the configuration so hostapd starts on boot:
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl restart hostapd
Configuring 802.1X at the edge turns physical Ethernet drops into authenticated endpoints. Even if an attacker reaches an empty wall port in your office, the interface stays isolated until they clear cryptographic verification.

