# Peering via Layer 3 Tunnel

Layer 3 tunnels encapsulate IP packets at the network layer. This is the recommended approach for most peering scenarios due to lower overhead and better performance compared to Layer 2 tunneling.

> **Layer 3 Tunnel Overview**
>
> In all examples below, replace placeholder values with your actual configuration:
>
> * `{name}` - Tunnel interface name
> * `{yourside ip}` - Your public IP address
> * `{ourside ip}` - Our endpoint IP address
> * `{yourside port}` - Your source port (WireGuard)
> * `{ourside port}` - Our destination port (WireGuard)
> * `{your tunnel ip cidr}` - Your tunnel IP/subnet
> * `{our public key}` - Our WireGuard public key
> * `{your private key}` - Your WireGuard private key

## Tunnel Profile Selection

## WireGuard

**WireGuard** is a modern, lightweight VPN protocol that provides encrypted Layer 3 tunneling. It's our recommended choice for secure peering due to its simplicity and performance.

### Wg Quick

Create a WireGuard configuration file:

```ini title="/etc/wireguard/{name}.conf"
[Interface]
Address    = {your tunnel ip cidr}
ListenPort = {yourside port}
PrivateKey = {your private key}
# Disable WireGuard's built-in routing table management when using
# an external routing daemon (e.g. BIRD, FRR)
Table = off

[Peer]
PublicKey           = {our public key}
AllowedIPs          = 0.0.0.0/0, ::/0
Endpoint            = {ourside ip}:{ourside port}
PersistentKeepalive = 25
```

### Systemd

1. Create the `.netdev` file:

```ini title="/etc/systemd/network/10-{name}.netdev"
[NetDev]
Name = {name}
Kind = wireguard

[WireGuard]
ListenPort = {yourside port}
PrivateKey = {your private key}

[WireGuardPeer]
PublicKey           = {our public key}
AllowedIPs          = 0.0.0.0/0, ::/0
Endpoint            = {ourside ip}:{ourside port}
PersistentKeepalive = 25
```

2. Configure the tunnel IP address:

```ini title="/etc/systemd/network/10-{name}.network"
[Match]
Name = {name}

[Network]
Address = {your tunnel ip cidr}
```

3. Apply the configuration:

```sh
systemctl restart systemd-networkd
```

### Enable

Enable and start the WireGuard service (wg-quick only):

```sh
systemctl enable --now wg-quick@{name}
```

## GRE Tunnel

**GRE** (Generic Routing Encapsulation) operates at Layer 3 and is suitable for routing IPv4/IPv6 traffic over an IPv4 underlay. It's simple, widely-supported, and has minimal overhead.

### Shell

```shell
ip tunnel add {name} mode gre local {yourside ip} remote {ourside ip} ttl 255
ip addr add {your tunnel ip cidr} dev {name}
ip link set dev {name} up
```

### Netplan

1. Create a Netplan configuration file:

```yaml title="/etc/netplan/10-{name}.yaml"
network:
  version: 2
  tunnels:
    { name }:
      mode: gre
      local: { yourside ip }
      remote: { ourside ip }
      ttl: 255
      addresses:
        - { your tunnel ip cidr }
```

2. Apply the configuration:

```sh
netplan apply
```

### Systemd

1. Create the `.netdev` file:

```ini title="/etc/systemd/network/10-{name}.netdev"
[NetDev]
Name = {name}
Kind = gre

[Tunnel]
Local  = {yourside ip}
Remote = {ourside ip}
TTL    = 255
```

2. Configure the tunnel IP address:

```ini title="/etc/systemd/network/10-{name}.network"
[Match]
Name = {name}

[Network]
Address = {your tunnel ip cidr}
```

3. Apply the configuration:

```sh
systemctl restart systemd-networkd
```

## SIT / ip6gre (IPv6 Tunneling)

**SIT** (Simple Internet Transition) tunnels IPv6 traffic over an IPv4 underlay and is commonly used for 6in4 connectivity.

**ip6gre** provides full GRE encapsulation for IPv6 and is preferred when you need GRE key support or multi-protocol capability.

### Sit Shell

```shell
# SIT: IPv6-in-IPv4
ip tunnel add {name} mode sit local {yourside ipv4} remote {ourside ipv4} ttl 255
ip addr add {your tunnel ipv6 cidr} dev {name}
ip link set dev {name} up
```

### Ip6gre Shell

```shell
# ip6gre: GRE over IPv4 carrying IPv6
ip tunnel add {name} mode ip6gre local {yourside ipv4} remote {ourside ipv4} ttl 255
ip addr add {your tunnel ipv6 cidr} dev {name}
ip link set dev {name} up
```

### Netplan

1. Create a Netplan configuration file:

```yaml title="/etc/netplan/10-{name}.yaml"
network:
  version: 2
  tunnels:
    { name }:
      # Use 'sit' for 6in4, or 'ip6gre' for GRE-encapsulated IPv6
      mode: sit
      local: { yourside ipv4 }
      remote: { ourside ipv4 }
      ttl: 255
      addresses:
        - { your tunnel ipv6 cidr }
```

2. Apply the configuration:

```sh
netplan apply
```

### Systemd

1. Create the `.netdev` file:

```ini title="/etc/systemd/network/10-{name}.netdev"
[NetDev]
Name = {name}
# Kind = sit   (for 6in4)
# Kind = ip6gre (for GRE over IPv4 carrying IPv6)
Kind = sit

[Tunnel]
Local  = {yourside ipv4}
Remote = {ourside ipv4}
TTL    = 255
```

2. Configure the tunnel IP address:

```ini title="/etc/systemd/network/10-{name}.network"
[Match]
Name = {name}

[Network]
Address = {your tunnel ipv6 cidr}
```

3. Apply the configuration:

```sh
systemctl restart systemd-networkd
```

## Protocol Comparison

| Protocol  | Encryption | IPv4 | IPv6 | Overhead | NAT Traversal |
| --------- | ---------- | ---- | ---- | -------- | ------------- |
| WireGuard | Yes        | ✓    | ✓    | 32 bytes | Good (UDP)    |
| GRE       | No         | ✓    | ✓    | 28 bytes | Limited       |
| SIT       | No         | N/A  | ✓    | 20 bytes | Limited       |
| ip6gre    | No         | N/A  | ✓    | 28 bytes | Limited       |

> **Protocol Selection Guide**
>
> * **WireGuard**: Best for secure peering, supports both IPv4 and IPv6
> * **GRE**: Simple, widely-supported, good for IPv4 peering
> * **SIT/ip6gre**: Use when you only need IPv6 transport over IPv4

## MTU Considerations

Layer 3 tunnels add overhead to each packet. Adjust your MTU accordingly:

| Protocol  | Overhead | Recommended MTU |
| --------- | -------- | --------------- |
| WireGuard | 32 bytes | 1468            |
| GRE       | 28 bytes | 1472            |
| SIT       | 20 bytes | 1480            |
| ip6gre    | 28 bytes | 1472            |

Example for WireGuard:

```sh
ip link set dev {name} mtu 1468
```

## Next Steps

Once you have configured the tunnel:

1. Verify connectivity using `ping` or `traceroute`
2. Configure your BGP daemon (BIRD, FRR, etc.) to use the tunnel interface
3. [Contact us](/docs/about#contact-us) to finalize the peering session

> After successfully setting up the tunnel, contact us to finalize the peering session with AS203314.

---

## License and attribution

- **Canonical source:** [View the human-readable HTML page](https://hatsnet.io/docs/peering/via-layer3-tunnel).
- **Original documentation:** © Hats Network Inc., licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
- **Full terms:** [Content and Data License](https://hatsnet.io/docs/legal/content-and-data-license) — includes attribution requirements, third-party material, trademarks, source code and other exclusions.
