summaryrefslogtreecommitdiff
path: root/hosts/ahmed/torrenting/wireguard.nix
blob: 22d3f9c4a22462360dfbdd622a95a6e9b144b554 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# This module configures a WireGuard for qBittorrent to use.

{
  config,
  ...
}: let
  wgInterface = "wg0";
  wgPort = 51820;
in {
  # TODO: Use Peer as DNS server: https://arc.net/l/quote/axlprdca

  # Create a connection to Mullvad's WireGuard server.
  networking.wireguard.interfaces = {
    ${wgInterface} = {
      # The port to use for communication. This should also be opened in the firewall.
      ips = ["10.70.101.133/32" "fc00:bbbb:bbbb:bb01::7:6584/128"];
      privateKeyFile = config.age.secrets.mullvad-wg-key.path;
      allowedIPsAsRoutes = false;
      listenPort = wgPort;

      # Create a differente networking namespace to isolate the qBittorent
      # process. I decided not to do this because connecting the WebUI to NGINX
      # becomes a bit tricky then. I will keep it around just in case I take up
      # this issue again sometime later.
      #
      # Remember, you would also need to set NetworkNamespacePath= on
      # qBittorrent [0]. The network namespace would when be located under
      # /run/netns/${wgNamespace}.
      #
      # [0]: https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#NetworkNamespacePath=
      #
      # interfaceNamespace = wgNamespace;
      # preSetup = ''
      #   echo "Setting up namespace: ${wgNamespace}"
      #   ${pkgs.iproute2}/bin/ip netns add ${wgNamespace}
      #   ${pkgs.iproute2}/bin/ip -n ${wgNamespace} link set lo up
      # '';
      # postShutdown = ''
      #   echo "Tearing down namespace: ${wgNamespace}"
      #   ${pkgs.iproute2}/bin/ip netns del "${wgNamespace}"
      # '';

      # Since this is a client configuration, we only need a single peer: the Mullvad server.
      peers = [
        {
          # The public key of the server.
          publicKey = "/iivwlyqWqxQ0BVWmJRhcXIFdJeo0WbHQ/hZwuXaN3g=";

          # The location of the server.
          endpoint = "193.32.127.66:${toString wgPort}";

          # Which destination IPs should be directed to this ip/pubkey pair. In
          # this case, we send all packets to our only peer.
          #
          # NOTE: It is important the we either use a network namespace or set
          # `allowedIPsAsRoutes = false` as otherwise we run into the loop
          # routing problem.
          #
          # See: https://wiki.archlinux.org/title/WireGuard#Loop_routing
          # See: https://cohost.org/linuwus/post/5040530-an-unexpected-soluti
          allowedIPs = ["0.0.0.0/0" "::/0"];

          # Send keepalives messages. Important to keep NAT tables alive.
          persistentKeepalive = 25;
        }
      ];
    };
  };

  # Here we load the secret file containing this clients private key. It is
  # defined in the configuration file from Mullvad's website.
  age.secrets.mullvad-wg-key.file = ../../../secrets/mullvad-wg.key.age;

  networking.firewall = {
    # Clients and peers use the same port. I'm actually not sure we need to
    # accept incomming connections as clients participating in the wireguard
    # protocol.
    allowedUDPPorts = [wgPort];

    # This is a weird fix. Apparently the rpfilter set up as part of
    # nixos-rpfilter in the 'mangle' table will block WireGuard traffic.
    # Setting this to "loose" somehow fixes that.
    #
    # See: https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577/2?u=linnnus
    # See: https://github.com/NixOS/nixpkgs/issues/51258#issuecomment-448005659
    checkReversePath = "loose";
  };

  # Configure qBittorrent to only torrent through the wireguard interface.
  services.qbittorrent.settings = {
    Bittorrent = {
      "Session\\Interface" = wgInterface;
      "Session\\InterfaceName" = wgInterface;
    };
  };

  # We also instruct qBittorrent to wait for the wireguard interface to come
  # online. This lets us avoid an awkward interim where qBittorrent is live
  # but can't torrent anything.
  #
  # FIXME: Maybe not strictly necessary.
  systemd.services.qbittorrent.unitConfig.After = ["wireguard-${wgInterface}.target"];
}