summaryrefslogtreecommitdiff
path: root/os/kay/modules/hurricane.nix
blob: e815136219101a1160d1a9a50412cd085e7acfd8 (plain) (blame)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
{
  config,
  pkgs,
  lib,
  ...
}:

let
  iface = "hurricane";
  remote = "216.218.221.42";

  clinet = "2001:470:35:72a::2";
  server = "2001:470:35:72a::1";

  prefix64 = "2001:470:36:72a::/64";
  prefix48 = "2001:470:ee65::/48";

  makeAddr =
    prefix: host:
    let
      split = lib.strings.splitString "/" prefix;
    in
    {
      address = "${lib.head split}${host}";
      prefixLength = lib.toInt (lib.last split);
    };
in
{
  networking = {
    sits.${iface} = {
      inherit remote;
      ttl = 225;
    };
    interfaces.${iface} = {
      mtu = 1472; # 1492(ppp0) - 20
      ipv6.addresses = [
        {
          address = clinet;
          prefixLength = 64;
        }

        (makeAddr prefix64 "1")
        (makeAddr prefix48 "1")
        (makeAddr prefix48 "1337")
      ];
    };

    iproute2 = {
      enable = true;
      rttablesExtraConfig = "200 hurricane";
    };

    firewall = {
      extraCommands = "iptables -A INPUT --proto 41 --source ${remote} --jump ACCEPT";
      extraStopCommands = "iptables -D INPUT --proto 41 --source ${remote} --jump ACCEPT";
    };
  };

  sops.secrets = {
    "hurricane/username" = { };
    "hurricane/update_key" = { };
    "hurricane/tunnel_id" = { };
  };

  systemd.services."network-route-${iface}" = {
    description = "Routing configuration of ${iface}";
    wantedBy = [
      "network-setup.service"
      "network.target"
    ];
    before = [ "network-setup.service" ];
    bindsTo = [ "network-addresses-hurricane.service" ];
    after = [
      "network-pre.target"
      "network-addresses-hurricane.service"
    ];
    # restart rather than stop+start this unit to prevent the
    # network from dying during switch-to-configuration.
    stopIfChanged = false;

    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = true;
    };

    path = [ pkgs.iproute2 ];
    script = ''
      echo -n "adding route"

      ip -6 rule add from ${clinet}/64 table hurricane || exit 1
      ip -6 rule add from ${prefix64} table hurricane || exit 1
      ip -6 rule add from ${prefix48} table hurricane || exit 1

      ip -6 route add default via ${server} dev hurricane table hurricane || exit 1
    '';
    preStop = ''
      echo -n "deleting route"

      ip -6 route del default via ${server} dev hurricane table hurricane || exit 1

      ip -6 rule del from ${prefix48} table hurricane || exit 1
      ip -6 rule del from ${prefix64} table hurricane || exit 1
      ip -6 rule del from ${clinet}/64 table hurricane || exit 1
    '';
  };

  services.pppd.script."01-${iface}" = {
    runtimeInputs = with pkgs; [
      curl
      coreutils
      iproute2
      iputils
    ];
    text = ''
      wan_ip="$4"
      username="$(cat ${config.sops.secrets."hurricane/username".path})"
      update_key="$(cat ${config.sops.secrets."hurricane/update_key".path})"
      tunnel_id="$(cat ${config.sops.secrets."hurricane/tunnel_id".path})"

      auth_url="https://$username:$update_key@ipv4.tunnelbroker.net/nic/update?hostname=$tunnel_id"
      until curl --silent "$auth_url"; do
          sleep 1
      done

      while [ ! -e /sys/class/net/${iface} ]; do
          sleep 1 # make sure ${iface} is up
      done

      ip tunnel change ${iface} local "$wan_ip" mode sit
    '';
  };
}