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 ];
97
98 wants = [ "network-online.target" ];
99 after = [ "network-online.target" ];
100 wantedBy = [ "multi-user.target" ];
101
102 serviceConfig = {
103 Type = "simple";
104 Restart = "always";
105 EnvironmentFile = "-${pkgs.libreswan}/etc/sysconfig/pluto";
106 ExecStartPre = [
107 "${libexec}/addconn --config ${configFile} --checkconfig"
108 "${libexec}/_stackmanager start"
109 "${ipsec} --checknss"
110 "${ipsec} --checknflog"
111 ];
112 ExecStart = "${libexec}/pluto --config ${configFile} --nofork \$PLUTO_OPTIONS";
113 ExecStop = "${libexec}/whack --shutdown";
114 ExecStopPost = [
115 "${pkgs.iproute}/bin/ip xfrm policy flush"
116 "${pkgs.iproute}/bin/ip xfrm state flush"
117 "${ipsec} --stopnflog"
118 ];
119 ExecReload = "${libexec}/whack --listen";
120 };
121
122 };
123
124 };
125
126}