# Intro This note describes how to connect two networks/devices/VMs over public network using Wireguard with Layer 2 support (ARP, IPv6 link-local, etc). This can also be achieved using SSH and its "tap" tunnel, however, it does not provide the same level of latency and bandwidth as full-blown VPN such as Wireguard. In addition, this note describes how to tunnel Wireguard over TCP connection. This may be of use if you encounter firewall in-between so, for instance, you can use TCP port 443 only. # Objective Let's draw a network diagram of what we would like to have in as a result. Host on private LAN Host on the Internet +---------------------------------+ +-------------------------------+ | brtun bridge | | brtun bridge | | +-------------+ | | +--------+ | | | ethX gretun |<->wg0<->udp2raw | <-Internet, TCP 443-> | udp2raw<->wg0<->| gretun | | | +-------------+ | | +--------+ | +---------------------------------+ +-------------------------------+ brtun: 192.168.0.200/24 brtun: 192.168.0.50/24 wg0: 12.12.12.2/24 wg0: 12.12.12.1/24 gretun: 12.12.12.2->12.12.12.1 gretun: 12.12.12.1->12.12.12.2 # Setting things up Distinguishing between server and client here is based on the answer to the question: who can connect to Wireguard listener socket. ## Server Generating a key: wg genkey | tee wgkeyprivs | wg pubkey > wgkeypubs Creating a Wireguard interface, setting the private key and a unique private IPv4 address: ip l a wg0 type wireguard wg set wg0 private-key ./wgkeyprivs ip a a 12.12.12.1/24 dev wg0 In case we want Wireguard over TCP, we have to decrease MTU: ip l set dev wg0 mtu 1200 Configuring peer's public key and setting interface up (you can restrict allowed-ips to the range you want): ip l set dev wg0 up wg set wg0 listen-port 51820 peer $(cat wgkeypubc) allowed-ips 0.0.0.0/0 Creating GRETAP interface which will provide Layer 2 over our Wireguard tunnel: ip l a gretun type gretap local 12.12.12.1 remote 12.12.12.2 ip l s gretun up Configuring a bridge which includes GRETAP interface. This step is in fact optional, but it allows you some flexibility: you can assign an IP address to this bridge interface and/or you can add additional interfaces to this bridge. ip l add name brtun type bridge ip l set dev brtun up ip l set gretun master brtun Let's assign an IP address from the target network to this bridge: sudo ip a a 192.168.0.51/24 dev brtun If we want Wireguard over TCP, launch UDP2RAW listener which will do its magic. You can get UDP2RAW from this Git repo: https://github.com/wangyu-/udp2raw-tunnel/releases/ ./udp2raw_amd64 -s -l YOUR_PUBLIC_IP:443 -r 127.0.0.1:51820 -a --fix-gro ## Client Client is very similar to the server described above. Generating a key: wg genkey | tee wgkeyprivc | wg pubkey > wgkeypubc Creating a Wireguard interface, setting the private key and a unique private IPv4 address: ip l a wg0 type wireguard wg set wg0 private-key ./wgkeyprivc ip a a 12.12.12.2/24 dev wg0 In case we want Wireguard over TCP, we have to decrease MTU: ip l set dev wg0 mtu 1200 Configuring peer's public key, endpoint address and setting interface up (you can restrict allowed-ips to the range you want): ip l set dev wg0 up wg set wg0 listen-port 51820 peer $(cat wgkeypubs) allowed-ips 0.0.0.0/0 endpoint YOUR_PUBLIC_IP:51820 persistent-keepalive 15 In case you want Wireguard over TCP, set endpoint address to a localhost interface: wg set wg0 listen-port 51820 peer $(cat wgkeypubs) allowed-ips 0.0.0.0/0 endpoint 127.0.0.1:7777 persistent-keepalive 15 Creating GRETAP interface which will provide Layer 2 over our Wireguard tunnel: ip l a gretun type gretap local 12.12.12.2 remote 12.12.12.1 ip l s gretun up Configuring a bridge which includes GRETAP interface. ip l add name brtun type bridge ip l set dev brtun up ip l set gretun master brtun Let's add a physical interface belonging to a LAN network to the bridge and start DHCP client: ip l set ethX master brtun dhcpcd ethX If we want Wireguard over TCP, launch UDP2RAW listener on the localhost interface which connects to the corresponding public listener. ./udp2raw_amd64 -c -l 127.0.0.1:7777 -r YOUR_PUBLIC_IP:443 -a --fix-gro # Results That's it. Now you will have Layer 2 connectivity between two separated machines over Wireguard VPN (optionally, over TCP). Enjoy your ARP and IPv6 link-local experience. # References https://notes.superlogical.ch/pages/note_wg/nolayer2/ https://lafibre.info/vpn/tunnel-gre-sur-wireguard/&prev=search&pto=aue