Skip to content

Instantly share code, notes, and snippets.

@zOrg1331
Last active October 18, 2025 11:49
Show Gist options
  • Save zOrg1331/a2a7ffb3cfe3b3b821d45d6af00cb8f6 to your computer and use it in GitHub Desktop.
Save zOrg1331/a2a7ffb3cfe3b3b821d45d6af00cb8f6 to your computer and use it in GitHub Desktop.

Revisions

  1. zOrg1331 revised this gist May 24, 2021. No changes.
  2. zOrg1331 revised this gist Feb 14, 2021. 1 changed file with 68 additions and 51 deletions.
    119 changes: 68 additions & 51 deletions wireguard_layer2.md
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,7 @@ In addition, this note describes how to tunnel Wireguard over TCP connection. Th

    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 |
    @@ -23,7 +23,7 @@ Let's draw a network diagram of what we would like to have in as a result.
    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

    @@ -32,95 +32,112 @@ Distinguishing between server and client here is based on the answer to the ques
    ## Server

    Generating a key:

    wg genkey | tee wgkeyprivs | wg pubkey > wgkeypubs
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    ./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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    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
    ```
    ./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
    * https://notes.superlogical.ch/pages/note_wg/nolayer2/
    * https://lafibre.info/vpn/tunnel-gre-sur-wireguard/&prev=search&pto=aue
  3. zOrg1331 created this gist Feb 14, 2021.
    126 changes: 126 additions & 0 deletions wireguard_layer2.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,126 @@
    # 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