sixnix

NixOS module for IPv6 networking with WireGuard tunnels and optional BGP failover.

Motivation

My ISP gives me a single /64 and it's dynamically assigned. Can't have multiple networks with functional autoconfiguration. Tunnel brokers like Hurricane Electric would work but my ISP uses CGNAT which makes that setup tricky if not impossible. They also do not have any exit nodes in the region I want.

Linode provides a routed /56 for free with their cheapest $5/month VPS. That's 256 /64 subnets. You get 1TB traffic at 1Gbit (40Gbit input but that's kind of irrelevant for our use case). Good enough.

Solution 1: Simple WireGuard setup

Just a plain WireGuard tunnel to route the /56 to your home network.

With a /56 you can carve out a /60 for WireGuard endpoints and you're left with 15 /60 subnets. Share it with friends!

Client subnet WireGuard subnet
2001:db8::/60 2001:db8:0:f0::a/127 1
2001:db8:0:10::/60 2001:db8:0:f1::a/127 2
2001:db8:0:20::/60 2001:db8:0:f2::a/127 3
2001:db8:0:30::/60 2001:db8:0:f3::a/127 4
2001:db8:0:40::/60 2001:db8:0:f4::a/127 5
2001:db8:0:50::/60 2001:db8:0:f5::a/127 6
2001:db8:0:60::/60 2001:db8:0:f6::a/127 7
2001:db8:0:70::/60 2001:db8:0:f7::a/127 8
2001:db8:0:80::/60 2001:db8:0:f8::a/127 9
2001:db8:0:90::/60 2001:db8:0:f9::a/127 10
2001:db8:0:a0::/60 2001:db8:0:fa::a/127 11
2001:db8:0:b0::/60 2001:db8:0:fb::a/127 12
2001:db8:0:c0::/60 2001:db8:0:fc::a/127 13
2001:db8:0:d0::/60 2001:db8:0:fd::a/127 14
2001:db8:0:e0::/60 2001:db8:0:fe::a/127 15

Basic configuration

{
  inputs.sixnix.url = "git+https://code.planet-express.in/konarak/sixnix.git";

  outputs = { nixpkgs, sixnix, ... }: {
    nixosConfigurations.tunnel-server = nixpkgs.lib.nixosSystem {
      modules = [
        sixnix.nixosModules.default
        {
          sixnix = {
            enable = true;
            hostname = "tunnel-server";
            domain = "example.com";
          };

          wireguard.interfaces = [{
            interface = "wg0";
            serverPort = 51820;
            serverAddress = "2001:db8:a7c4:0:f0::a/127";
            clientAddress = "2001:db8:a7c4:0:f0::b/127";
            clientSubnet = "2001:db8:a7c4::/60";
            serverPrivateKeyFile = "/run/secrets/wg0-server-private";
            clientPublicKeyFile = "/run/secrets/wg0-client-public";
          }];
        }
      ];
    };
  };
}

How it works:

  • Your router uses the ISP-provided IPv6 to connect to the WireGuard server
  • Interfaces get /64s from the delegated /60 with router advertisement enabled
  • All traffic from clients goes out to the internet via Linode

Solution 2: BGP failover (ultra advanced)

Want redundancy? Run two Linodes in the same datacenter and use BGP to share a single /56 between them. If one server goes down, BGP automatically fails over to the other.

Cost: $10/month + tax for two Linodes with pooled 2TB bandwidth quota.

BGP configuration

{
  sixnix = {
    enable = true;
    hostname = "tunnel-primary";
    domain = "example.com";

    bgp = {
      enable = true;
      peers = [
        "2001:db8:9f2b::1"  # BGP peer addresses (e.g., Linode route servers)
        "2001:db8:9f2b::2"
        "2001:db8:9f2b::3"
        "2001:db8:9f2b::4"
      ];
      advertisedSubnets = [ "2001:db8:a7c4::/56" ];
      routeMap = "primary";  # or "secondary" for the backup server
    };
  };

  wireguard.interfaces = [{
    interface = "wg0";
    serverPort = 51820;
    serverAddress = "2001:db8:a7c4:0:f0::a/127";
    clientAddress = "2001:db8:a7c4:0:f0::b/127";
    clientSubnet = "2001:db8:a7c4::/60";
    serverPrivateKeyFile = "/run/secrets/wg0-server-private";
    clientPublicKeyFile = "/run/secrets/wg0-client-public";
  }];
}

The BGP setup creates:

  • A shared dummy interface with a VIP that both servers announce
  • Route servers configured automatically based on datacenter ID
  • Blackhole routes for the advertised subnet
  • Primary/secondary route maps for failover priority

Notes

  • BGP peers and advertised subnets are fully configurable
  • The FRR configuration template may need adjustments for providers other than Linode (AS numbers, communities, etc.)
  • For Linode: use route servers 2600:3c0f:<dcId>:34::{1,2,3,4} where <dcId> is your datacenter ID (e.g., 25 for in-maa)
  • See Linode's BGP documentation for more details
  • See modules/network.nix and modules/wireguard.nix for all available options
Description
No description provided
Readme 64 KiB
Languages
Nix 100%