1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.libreswan;
8
9 libexec = "${pkgs.libreswan}/libexec/ipsec";
10 ipsec = "${pkgs.libreswan}/sbin/ipsec";
11
12 trim = chars: str: let
13 nonchars = filter (x : !(elem x.value chars))
14 (imap0 (i: v: {ind = i; value = v;}) (stringToCharacters str));
15 in
16 if length nonchars == 0 then ""
17 else substring (head nonchars).ind (add 1 (sub (last nonchars).ind (head nonchars).ind)) str;
18 indent = str: concatStrings (concatMap (s: [" " (trim [" " "\t"] s) "\n"]) (splitString "\n" str));
19 configText = indent (toString cfg.configSetup);
20 connectionText = concatStrings (mapAttrsToList (n: v:
21 ''
22 conn ${n}
23 ${indent v}
24
25 '') cfg.connections);
26 configFile = pkgs.writeText "ipsec.conf"
27 ''
28 config setup
29 ${configText}
30
31 ${connectionText}
32 '';
33
34in
35
36{
37
38 ###### interface
39
40 options = {
41
42 services.libreswan = {
43
44 enable = mkEnableOption "libreswan ipsec service";
45
46 configSetup = mkOption {
47 type = types.lines;
48 default = ''
49 protostack=netkey
50 nat_traversal=yes
51 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
52 '';
53 example = ''
54 secretsfile=/root/ipsec.secrets
55 protostack=netkey
56 nat_traversal=yes
57 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
58 '';
59 description = "Options to go in the 'config setup' section of the libreswan ipsec configuration";
60 };
61
62 connections = mkOption {
63 type = types.attrsOf types.lines;
64 default = {};
65 example = {
66 myconnection = ''
67 auto=add
68 left=%defaultroute
69 leftid=@user
70
71 right=my.vpn.com
72
73 ikev2=no
74 ikelifetime=8h
75 '';
76 };
77 description = "A set of connections to define for the libreswan ipsec service";
78 };
79 };
80
81 };
82
83
84 ###### implementation
85
86 config = mkIf cfg.enable {
87
88 environment.systemPackages = [ pkgs.libreswan pkgs.iproute ];
89
90 systemd.services.ipsec = {
91 description = "Internet Key Exchange (IKE) Protocol Daemon for IPsec";
92 path = [
93 "${pkgs.libreswan}"
94 "${pkgs.iproute}"
95 "${pkgs.procps}"
96 "${pkgs.nssTools}"
97 "${pkgs.iptables}"
98 "${pkgs.nettools}"
99 ];
100
101 wants = [ "network-online.target" ];
102 after = [ "network-online.target" ];
103 wantedBy = [ "multi-user.target" ];
104
105 serviceConfig = {
106 Type = "simple";
107 Restart = "always";
108 EnvironmentFile = "-${pkgs.libreswan}/etc/sysconfig/pluto";
109 ExecStartPre = [
110 "${libexec}/addconn --config ${configFile} --checkconfig"
111 "${libexec}/_stackmanager start"
112 "${ipsec} --checknss"
113 "${ipsec} --checknflog"
114 ];
115 ExecStart = "${libexec}/pluto --config ${configFile} --nofork \$PLUTO_OPTIONS";
116 ExecStop = "${libexec}/whack --shutdown";
117 ExecStopPost = [
118 "${pkgs.iproute}/bin/ip xfrm policy flush"
119 "${pkgs.iproute}/bin/ip xfrm state flush"
120 "${ipsec} --stopnflog"
121 ];
122 ExecReload = "${libexec}/whack --listen";
123 };
124
125 };
126
127 };
128
129}