summary refs log tree commit diff
path: root/nixos/modules/services/networking/libreswan.nix
blob: 280158b89f61bc9f5fbd79a16ada0b631f5a0236 (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
{ config, lib, pkgs, ... }:

with lib;

let

  cfg = config.services.libreswan;

  libexec = "${pkgs.libreswan}/libexec/ipsec";
  ipsec = "${pkgs.libreswan}/sbin/ipsec";

  trim = chars: str: let
      nonchars = filter (x : !(elem x.value chars))
                  (imap0 (i: v: {ind = i; value = v;}) (stringToCharacters str));
    in
      if length nonchars == 0 then ""
      else substring (head nonchars).ind (add 1 (sub (last nonchars).ind (head nonchars).ind)) str;
  indent = str: concatStrings (concatMap (s: ["  " (trim [" " "\t"] s) "\n"]) (splitString "\n" str));
  configText = indent (toString cfg.configSetup);
  connectionText = concatStrings (mapAttrsToList (n: v:
    ''
      conn ${n}
      ${indent v}

    '') cfg.connections);
  configFile = pkgs.writeText "ipsec.conf"
    ''
      config setup
      ${configText}

      ${connectionText}
    '';

in

{

  ###### interface

  options = {

    services.libreswan = {

      enable = mkEnableOption "libreswan ipsec service";

      configSetup = mkOption {
        type = types.lines;
        default = ''
            protostack=netkey
            nat_traversal=yes
            virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:100.64.0.0/10,%v6:fd00::/8,%v6:fe80::/10
        '';
        example = ''
            secretsfile=/root/ipsec.secrets
            protostack=netkey
            nat_traversal=yes
            virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:100.64.0.0/10,%v6:fd00::/8,%v6:fe80::/10
        '';
        description = "Options to go in the 'config setup' section of the libreswan ipsec configuration";
      };

      connections = mkOption {
        type = types.attrsOf types.lines;
        default = {};
        example = {
          myconnection = ''
            auto=add
            left=%defaultroute
            leftid=@user

            right=my.vpn.com

            ikev2=no
            ikelifetime=8h
          '';
        };
        description = "A set of connections to define for the libreswan ipsec service";
      };
    };

  };


  ###### implementation

  config = mkIf cfg.enable {

    environment.systemPackages = [ pkgs.libreswan pkgs.iproute ];

    systemd.services.ipsec = {
      description = "Internet Key Exchange (IKE) Protocol Daemon for IPsec";
      path = [
        "${pkgs.libreswan}"
        "${pkgs.iproute}"
        "${pkgs.procps}"
        "${pkgs.nssTools}"
        "${pkgs.iptables}"
        "${pkgs.nettools}"
      ];

      wants = [ "network-online.target" ];
      after = [ "network-online.target" ];
      wantedBy = [ "multi-user.target" ];

      serviceConfig = {
        Type = "simple";
        Restart = "always";
        EnvironmentFile = "-${pkgs.libreswan}/etc/sysconfig/pluto";
        ExecStartPre = [
          "${libexec}/addconn --config ${configFile} --checkconfig"
          "${libexec}/_stackmanager start"
          "${ipsec} --checknss"
          "${ipsec} --checknflog"
        ];
        ExecStart = "${libexec}/pluto --config ${configFile} --nofork \$PLUTO_OPTIONS";
        ExecStop = "${libexec}/whack --shutdown";
        ExecStopPost = [
          "${pkgs.iproute}/bin/ip xfrm policy flush"
          "${pkgs.iproute}/bin/ip xfrm state flush"
          "${ipsec} --stopnflog"
        ];
        ExecReload = "${libexec}/whack --listen";
      };

    };

  };

}