Your Network Is Lying to You
After my server got hammered by SSH brute-force attempts at midnight, security became non-negotiable for every new setup. Firewalls, fail2ban, key-based auth — the obvious stuff was covered. But one attack vector I ignored for too long lives right at the network layer: ARP spoofing. It’s quiet, fast, and completely invisible to most standard monitoring setups.
Running a home lab, a small office network, or a VPS behind a shared hypervisor? ARP-based attacks are a genuine threat. An attacker on the same network segment can silently redirect all your traffic through their machine — reading credentials, injecting payloads, dropping packets — without triggering a single firewall rule.
Below, I’ll break down the attack, set up detection with arpwatch, and show how to block it proactively with arptables.
What ARP Spoofing Actually Does
ARP (Address Resolution Protocol) maps IP addresses to MAC addresses on a local network. When your machine wants to reach 192.168.1.1, it broadcasts an ARP request: “who has 192.168.1.1?” The router responds with its MAC address, and your machine caches that mapping.
The problem: ARP has zero authentication. Anyone on the network can send a fake ARP reply claiming any IP maps to their MAC. Your machine updates its ARP cache without question — no verification, no challenge.
Here’s the attack step by step:
- Attacker sends spoofed ARP replies to the victim: “192.168.1.1 (gateway) is at MAC AA:BB:CC:DD:EE:FF”
- Attacker simultaneously tells the gateway: “192.168.1.50 (victim) is at MAC AA:BB:CC:DD:EE:FF”
- All traffic flows through the attacker’s machine — classic Man-in-the-Middle position
- Attacker forwards packets to maintain connectivity, so the victim notices nothing unusual
Tools like arpspoof, ettercap, and bettercap can pull this off in under 30 seconds. On a busy office network with 50 machines, an attacker running bettercap can start capturing HTTP credentials within a minute of connecting. Detection and prevention are equally fast to deploy once you know the mechanics.
Setting Up arpwatch for Detection
arpwatch monitors ARP traffic and alerts you whenever a MAC-IP pairing changes. It maintains a database of known associations and flags unexpected changes — exactly what ARP spoofing triggers.
Installation
# Debian/Ubuntu
sudo apt update && sudo apt install arpwatch -y
# CentOS/RHEL/Rocky
sudo dnf install arpwatch -y
# Arch Linux
sudo pacman -S arpwatch
Basic Configuration
Most configuration happens via service flags rather than a config file. Start by checking your network interface name:
ip link show
Then edit the service configuration to monitor your interface:
# On Debian/Ubuntu, edit the default file
sudo nano /etc/default/arpwatch
# Set the interface (replace eth0 with yours)
IFACE="eth0"
ARPWATCH_OPTS="-N -p"
The -N flag disables email alerts (we’ll handle alerting separately), and -p keeps the interface out of promiscuous mode — useful when you only need to watch your own machine’s ARP activity, not the whole broadcast domain.
Want email alerts natively? Configure your system MTA and drop the -N flag. Arpwatch will email you on every “flip flop” event.
Start and Enable arpwatch
sudo systemctl enable arpwatch
sudo systemctl start arpwatch
sudo systemctl status arpwatch
Reading arpwatch Logs
Arpwatch writes to syslog. These are the event types worth knowing:
# Monitor live events
sudo journalctl -u arpwatch -f
# Or check syslog directly
sudo tail -f /var/log/syslog | grep arpwatch
Key events to watch for:
- flip flop — A MAC address for an IP switched and then switched back. This is the classic ARP spoofing signature.
- changed ethernet address — A known IP now maps to a different MAC. Could be a legitimate device swap, or an attack in progress.
- new activity — A known host reappeared after being idle.
- new station — A new device joined the network.
A real attack entry looks like this:
May 21 03:14:22 myserver arpwatch: flip flop 192.168.1.1 aa:bb:cc:dd:ee:ff (00:11:22:33:44:55) eth0
Translation: your gateway’s MAC just flipped from 00:11:22:33:44:55 to aa:bb:cc:dd:ee:ff. Time to investigate immediately.
Blocking ARP Attacks with arptables
Detection tells you something happened. Arptables lets you enforce ARP rules at the packet level — whitelist legitimate MAC-IP pairs, drop everything else.
Install arptables
# Debian/Ubuntu
sudo apt install arptables -y
# CentOS/RHEL
sudo dnf install arptables -y
View Current Rules
sudo arptables -L -v
Static ARP Entries — The Simplest Defense
Before touching arptables, reach for static ARP entries first. Hardcoding your gateway’s MAC in the ARP cache means spoofed replies can’t overwrite it:
# Find your gateway's real MAC first
arp -n 192.168.1.1
# Add a permanent static entry
sudo arp -s 192.168.1.1 00:11:22:33:44:55
# Verify it's marked permanent
arp -n
The output should show PERM next to the gateway entry. On a flat /24 network with a single gateway, this one step stops the most common MITM scenario cold.
To survive reboots, use /etc/ethers with arp -f:
# /etc/ethers format: MAC IP
echo "00:11:22:33:44:55 192.168.1.1" | sudo tee -a /etc/ethers
# Load on boot — add this to /etc/rc.local or a systemd service
sudo arp -f /etc/ethers
Enforcing Rules with arptables
For servers and managed infrastructure where the network topology is fixed, arptables gives you precise control. Accept ARP only from your known gateway, drop the rest:
# Allow ARP from your legitimate gateway only
# Replace with your actual gateway MAC and IP
sudo arptables -A INPUT --source-mac 00:11:22:33:44:55 --source-ip 192.168.1.1 -j ACCEPT
# Drop all other ARP replies claiming to be the gateway IP
sudo arptables -A INPUT --source-ip 192.168.1.1 -j DROP
Accept from the real MAC, drop anything else claiming that IP. An attacker can still send spoofed packets — your kernel just ignores them.
To stop your machine from being used as a MITM relay, restrict outbound ARP too:
# Only send ARP with your own MAC
MY_MAC=$(cat /sys/class/net/eth0/address)
sudo arptables -A OUTPUT --source-mac ! $MY_MAC -j DROP
Save and Restore Rules
# Save rules
sudo arptables-save > /etc/arptables.rules
# Restore rules on boot — add to /etc/rc.local or a systemd unit
sudo arptables-restore < /etc/arptables.rules
A Quick Detection Script
Rather than running a full daemon on lightweight machines, drop this into a cron job. It snapshots the ARP table every 2 minutes and alerts on any change:
#!/bin/bash
# arp_monitor.sh — alert on ARP cache changes
SNAPSHOT_FILE="/tmp/arp_snapshot"
CURRENT=$(arp -n | awk 'NR>1 {print $1, $3}')
if [ ! -f "$SNAPSHOT_FILE" ]; then
echo "$CURRENT" > "$SNAPSHOT_FILE"
echo "Baseline ARP snapshot saved."
exit 0
fi
DIFF=$(diff <(cat "$SNAPSHOT_FILE") <(echo "$CURRENT"))
if [ -n "$DIFF" ]; then
echo "[ALERT] ARP table changed at $(date):"
echo "$DIFF"
# Uncomment to send a Telegram or email alert here
fi
echo "$CURRENT" > "$SNAPSHOT_FILE"
# Make it executable and schedule via cron
chmod +x /usr/local/bin/arp_monitor.sh
(crontab -l; echo "*/2 * * * * /usr/local/bin/arp_monitor.sh >> /var/log/arp_monitor.log 2>&1") | crontab -
Putting It All Together
Here’s the layered setup I run on any Linux machine sitting on a shared network:
- Static ARP entries for critical hosts (gateway, DNS server, NFS server) — immediate protection, zero overhead
- arpwatch as a service — continuous monitoring, every anomaly logged to syslog
- arptables rules for servers with a fixed, known network topology
- ARP monitoring cron job for lightweight machines where a daemon is overkill
Stack as many layers as your environment warrants. More layers mean an attacker can’t stay quiet for long.
One last thing worth checking: does your switch support Dynamic ARP Inspection (DAI)? Cisco Catalyst, HP ProCurve, and most managed enterprise switches do. DAI validates ARP packets against the DHCP snooping binding table at the hardware level.
Spoofed replies get dropped before they ever reach your hosts. Enable it if you have the hardware. DAI at the switch layer combined with arpwatch and static ARP entries on the host closes almost every real-world attack angle you’ll face on a Linux network.

