blob: 8778b0364f9afa346d9eb9baf71a11aa92539442 (
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
133
|
{ config, lib, pkgs, ... }:
let
inherit (builtins) toFile;
inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList
mkIf mkEnableOption mkOption types;
cfg = config.services.strongswan;
ipsecSecrets = secrets: toFile "ipsec.secrets" (
concatMapStringsSep "\n" (f: "include ${f}") secrets
);
ipsecConf = {setup, connections, ca}:
let
# https://wiki.strongswan.org/projects/strongswan/wiki/IpsecConf
makeSections = type: sections: concatStringsSep "\n\n" (
mapAttrsToList (sec: attrs:
"${type} ${sec}\n" +
(concatStringsSep "\n" ( mapAttrsToList (k: v: " ${k}=${v}") attrs ))
) sections
);
setupConf = makeSections "config" { inherit setup; };
connectionsConf = makeSections "conn" connections;
caConf = makeSections "ca" ca;
in
builtins.toFile "ipsec.conf" ''
${setupConf}
${connectionsConf}
${caConf}
'';
strongswanConf = {setup, connections, ca, secrets}: toFile "strongswan.conf" ''
charon {
plugins {
stroke {
secrets_file = ${ipsecSecrets secrets}
}
}
}
starter {
config_file = ${ipsecConf { inherit setup connections ca; }}
}
'';
in
{
options.services.strongswan = {
enable = mkEnableOption "strongSwan";
secrets = mkOption {
type = types.listOf types.path;
default = [];
example = [ "/run/keys/ipsec-foo.secret" ];
description = ''
A list of paths to IPSec secret files. These
files will be included into the main ipsec.secrets file with
the <literal>include</literal> directive. It is safer if these
paths are absolute.
'';
};
setup = mkOption {
type = types.attrsOf types.str;
default = {};
example = { cachecrls = "yes"; strictcrlpolicy = "yes"; };
description = ''
A set of options for the ‘config setup’ section of the
<filename>ipsec.conf</filename> file. Defines general
configuration parameters.
'';
};
connections = mkOption {
type = types.attrsOf (types.attrsOf types.str);
default = {};
example = {
"%default" = {
keyexchange = "ikev2";
keyingtries = "1";
};
roadwarrior = {
auto = "add";
leftcert = "/run/keys/moonCert.pem";
leftid = "@moon.strongswan.org";
leftsubnet = "10.1.0.0/16";
right = "%any";
};
};
description = ''
A set of connections and their options for the ‘conn xxx’
sections of the <filename>ipsec.conf</filename> file.
'';
};
ca = mkOption {
type = types.attrsOf (types.attrsOf types.str);
default = {};
example = {
strongswan = {
auto = "add";
cacert = "/run/keys/strongswanCert.pem";
crluri = "http://crl2.strongswan.org/strongswan.crl";
};
};
description = ''
A set of CAs (certification authorities) and their options for
the ‘ca xxx’ sections of the <filename>ipsec.conf</filename>
file.
'';
};
};
config = with cfg; mkIf enable {
systemd.services.strongswan = {
description = "strongSwan IPSec Service";
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ kmod iproute iptables utillinux ]; # XXX Linux
wants = [ "keys.target" ];
after = [ "network.target" "keys.target" ];
environment = {
STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secrets; };
};
serviceConfig = {
ExecStart = "${pkgs.strongswan}/sbin/ipsec start --nofork";
};
};
};
}
|