Help for bypassing cgnat with wireguard and Digital Ocean vps

Hello forum

My internet service provider is using carrier grade nat. I’m trying to bypass this with wireguard and a virtual private server with static ip. To gain access to my local server from my away from home times.

This is the tutorial I’m following: https://hacdias.com/2020/11/30/access-network-behind-cgnat

What I did so far is open port 37466 on my home router

So far my setup:

svr2 public host (aka VPS)

  # enable NAT
  networking.nat.enable = true;
  networking.nat.externalInterface = "ens3";
  networking.nat.internalInterfaces = [ "wg0" ];

  networking.wireguard.interfaces = {
    # "ens3" is the network interface name. You can name the interface arbitrarily.
     wg0 = {
      # Determines the IP address and subnet of the server's end of the tunnel interface.
      ips = [ "10.200.200.1/24" ];

      # Path to the private key file.
      privateKeyFile = "/etc/nixos/wireguard-keys/privatekey";

      # The port that WireGuard listens to. Must be accessible by the client.
      listenPort = 37466;

      # Do not forget to change eth0 to the interface that is connected to the Internet! ens3 in this case.
      postSetup = ''
	${pkgs.iptables}/bin/iptables -A FORWARD -i %i -j ACCEPT; ${pkgs.iptables}/bin/iptables -A FORWARD -o %i -j ACCEPT; ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
      '';
      postShutdown = ''
	${pkgs.iptables}/bin/iptables -D FORWARD -i %i -j ACCEPT; ${pkgs.iptables}/bin/iptables -D FORWARD -o %i -j ACCEPT; ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
      '';


      peers = [
	# This is the peer inside the local subnet we want to have access to.
	# For that to happen, you need to add your local subnet to the AllowedIPs
	# option just like I did below.

	{ # svr1 RaspberryPi
	  publicKey = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=";
	  allowedIPs = [ "10.200.200.2/32" "192.168.168.0/24" ];
	}
	{ # Cellphone
	  publicKey = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=";
	  allowedIPs = [ "10.200.200.3/32" ];
	}
      ];
    };
  };

svr1 local host

  # enable NAT
  networking.nat.enable = true;
  networking.nat.externalInterface = "eth0";
  networking.nat.internalInterfaces = [ "wg0" ];

  networking.wireguard.interfaces = {
    # "wg0" is the network interface name. You can name the interface arbitrarily.
    wg0 = {
      # Determines the IP address and subnet of the server's end of the tunnel interface.
      ips = [ "10.200.200.2/24" ];

      # Path to the private key file.
      privateKeyFile = "/etc/nixos/wireguard-keys/privatekey";

      # The port that WireGuard listens to. Must be accessible by the client.
      listenPort = 37466;

      peers = [
	# List of allowed peers.
	{ # Digital Ocean VPN
	  publicKey = "ccccccccccccccccccccccccccccccccccccccccccccccccc=";
	  # List of IPs assigned to this peer within the tunnel subnet. Used to configure routing.
	  allowedIPs = [ "0.0.0.0/0" "::/0" ];
	  endpoint = "xxx.aaa.bbb.ccc:37466";  # do not forget to put your VPS IP here
	  persistentKeepalive = 25;
	}
      ];
    };
  };

checking the setup shows:
svr1 local host:

[root@svr1:~]# wg
interface: wg0
  public key: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=
  private key: (hidden)
  listening port: 37466

peer: dddddddddddddddddddddddddddddddddddddddddddddd=
  endpoint: xxx.aaa.bbb.ccc:37466
  allowed ips: 0.0.0.0/0, ::/0
  transfer: 0 B received, 976.89 KiB sent
  persistent keepalive: every 25 seconds

svr2 public host (aka VPS)

[root@svr2:~]# wg
interface: wg0
  public key: ccccccccccccccccccccccccccccc=
  private key: (hidden)
  listening port: 37466

peer: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=
  endpoint: 194.230.158.216:38469
  allowed ips: 10.200.200.3/32, 192.168.168.0/24
  latest handshake: 9 hours, 20 minutes, 8 seconds ago
  transfer: 1.93 KiB received, 8.17 KiB sent

peer: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=
  endpoint: 194.230.158.216:37466
  allowed ips: 10.200.200.2/32
  transfer: 148 B received, 92 B sent

I also have to add those lines manually to the terminal of svr1 local host:

$ iptables -A FORWARD -i wg0-client -j ACCEPT
$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

as those settings will not be permanent I wonder how I could make them permanent the nix way?

as you can see there is no handshaking going on. I double checked all the private/public keys.

When I ping any ip from svr2 to svr1 it’s always 100% packet loss.

Would be extremely wonderful if someone could give me a hint on what I did wrong! :pray:

I can’t help you on your manual WG setup but I can say that Tailscale works very well for me for the purpose of accessing devices behind any kind of firewall and requires next to no configuration.

PS: Tailscale devs use Nix too :wink: tailscale/shell.nix at af3127711a6df3a920204623bb24e1d74df97f1b · tailscale/tailscale · GitHub

1 Like