A Linux kernel module extension for WireGuard VPN that adds TAP (Layer 2) mode support, enabling Ethernet frame tunneling over WireGuard connections.
- TAP Mode Support: Creates WireGuard interfaces in TAP mode (Layer 2) instead of just TUN mode (Layer 3)
- MAC Address Learning: Implements a MAC-to-peer mapping table with 1024 entry capacity and 300-second aging time
- Layer 2 Protocol Support: Can tunnel non-IP protocols like ARP, DHCP, and other Ethernet-based protocols
- Broadcast/Multicast Handling: Broadcast and multicast frames are sent to all peers
- Backward Compatibility: Maintains full compatibility with standard WireGuard TUN mode
- New Message Type: Adds
MESSAGE_RAW_DATA = 5for transporting Layer 2 Ethernet frames - DKMS Support: Easy installation across different kernel versions
Standard WireGuard operates at Layer 3 (IP level), which only allows tunneling of IP packets. This extension adds Layer 2 (Ethernet) tunneling capability through TAP interfaces, allowing WireGuard to bridge entire networks and tunnel non-IP protocols.
- MAC Peer Table: Hash table implementation for mapping MAC addresses to WireGuard peers
- Device Structure Extension: Added
is_tap_modeflag andmac_tablepointer tostruct wg_device - Netlink Interface: Added
WGDEVICE_A_MODEattribute (value 9) for mode configuration - Message Processing: Modified send/receive paths to handle
MESSAGE_RAW_DATApackets - Interface Creation: Extended to accept mode parameter during interface creation
- TUN Mode (default): Standard WireGuard operation, processes IP packets only
- TAP Mode: Processes Ethernet frames, learns MAC addresses, handles broadcast/multicast
WireGuard's security model is derived from two components: encryption and trust.
Encryption: WireGuard employs state-of-the-art modern cryptography. This aspect remains unchanged.
Trust: WireGuard utilizes "cryptokey routing," which associates public keys with a list of IP addresses permitted to access the tunnel. The modifications introduced by this extension currently compromise this mechanism. The method of routing traffic using MAC addresses instead of IPs introduces vulnerabilities in two directions:
- MAC Layer: A compromised peer could send arbitrary ARP packets to carry out Man-in-the-Middle (MITM) attacks.
- IP Layer: A compromised peer could send arbitrary traffic for common network reconnaissance and attacks (if routing permits).
While these attacks are also present in typical Layer 2 networks, users might still trust peers as they did before. Therefore, after applying this extension, it is necessary to enhance the security protection of the WireGuard interface or run it only within trusted networks.
- Linux kernel with WireGuard support
- Kernel headers for your current kernel version
- DKMS (Dynamic Kernel Module Support)
# Install DKMS (if not already installed)
sudo apt install dkms # Debian/Ubuntu
sudo yum install dkms # RHEL/CentOS
# Add the module to DKMS
sudo dkms add -m wireguard -v 1.0.0-tap
# Build and install the module
sudo dkms install -m wireguard -v 1.0.0-tapAlternatively, combine all steps:
sudo dkms install -m wireguard -v 1.0.0-tap --force# Check if module is properly registered
dkms status
# Verify the module version
modinfo wireguard | grep versionThe output should show version "1.0.0-tap".
If the original WireGuard module is loaded, you may need to unload it first:
sudo rmmod wireguard
sudo modprobe wireguardOr simply reboot your system.
Use the provided Python scripts to create and configure WireGuard interfaces in TAP mode:
# Create a WireGuard interface (wg0) in TAP mode
sudo python3 create_wg_interface.py wg0 1
# Or set mode after interface creation
sudo python3 set_tap_mode.py wg0 1Mode parameter: 0 for TUN mode, 1 for TAP mode.
Here's a sample WireGuard configuration file for TAP mode (wt0.conf):
[Interface]
ListenPort = 51813
Address = 10.10.1.1/24
PrivateKey = p5ftS0pbX7Vz3fNcJ8vIc9zvJQcomyguIZLt+jY7gUw=
Mtu = 1406
PreUp = python3 set_tap_mode.py %i 1 # Set to TAP mode
Table = off
[Peer]
Endpoint = 192.168.122.5:51813
PublicKey = 6A5yBErWO/7HSjsMBCc+bmzdbwoRDQYLs4OwNQS2cDo=
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 10Important: Use Table = off to prevent routing issues when using TAP mode.
# Apply the configuration
sudo wg-quick up wt0.conf-
Receiving from TAP interface:
- Ethernet frames are received from the TAP interface
- Source MAC is learned and added to the MAC peer table
- Frame is encapsulated in
MESSAGE_RAW_DATAand sent to the appropriate peer
-
Receiving from WireGuard peer:
MESSAGE_RAW_DATApackets are decapsulated- Ethernet frames are injected into the TAP interface
- Destination MAC is learned from the frame
-
Broadcast/Multicast Handling:
- Broadcast (FF:FF:FF:FF:FF:FF) and multicast frames are sent to all peers
- Received broadcast/multicast frames are injected into the local TAP interface
- MAC table size: 1024 entries (hardcoded)
- Entry aging time: 300 seconds
- Hash-based lookup for efficient MAC-to-peer mapping
- Ensure kernel headers are installed:
sudo apt install linux-headers-$(uname -r) - Check build log:
/var/lib/dkms/wireguard/1.0.0-tap/build/make.log
- Check kernel messages:
dmesg | grep wireguard - Ensure module is not blacklisted in
/etc/modprobe.d/
- DKMS modules install to
/lib/modules/$(uname -r)/updates/which has priority - If WireGuard is built into the kernel, it cannot be replaced without kernel recompilation
If Secure Boot is enabled, you may need to sign the module with your Machine Owner Key (MOK). Use the provided MOK.der and MOK.priv files if needed.
wireguard/
├── main.c - Module initialization
├── device.c - Device management with TAP mode support
├── device.h - Device structures including MAC peer table
├── messages.h - Message definitions including MESSAGE_RAW_DATA
├── receive.c - Packet reception with raw data handling
├── send.c - Packet transmission with raw data support
├── netlink.c - Netlink interface with WGDEVICE_A_MODE attribute
├── peer.c - Peer management
├── queueing.h - Queueing structures with message type field
├── Makefile - Kernel module build configuration
├── dkms.conf - DKMS configuration for distribution
├── INSTALL_DKMS.md - Detailed installation instructions
├── post_install.sh - Post-installation script
├── create_wg_interface.py - Creates WireGuard interfaces with TAP/TUN mode
├── set_tap_mode.py - Sets device mode via netlink
├── wt0.conf - Example WireGuard configuration with TAP mode
└── selftest/ - Self-test files
- MAC table size is fixed at 1024 entries
- Requires modified WireGuard module (cannot use stock WireGuard)
- TAP mode may have performance implications compared to TUN mode
Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.
This project is based on the original WireGuard implementation. Please refer to the original WireGuard license terms.
##中文文档 (Chinese Documentation)
For Chinese documentation, please see README_zh.md.
Note: This is an extension to the official WireGuard project. WireGuard is a registered trademark of Jason A. Donenfeld.