vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / coturn.nix
blob40c157d1006e39b2f236b1730dca4bb07b706477
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.coturn;
4   pidfile = "/run/turnserver/turnserver.pid";
5   configFile = pkgs.writeText "turnserver.conf" ''
6 listening-port=${toString cfg.listening-port}
7 tls-listening-port=${toString cfg.tls-listening-port}
8 alt-listening-port=${toString cfg.alt-listening-port}
9 alt-tls-listening-port=${toString cfg.alt-tls-listening-port}
10 ${lib.concatStringsSep "\n" (map (x: "listening-ip=${x}") cfg.listening-ips)}
11 ${lib.concatStringsSep "\n" (map (x: "relay-ip=${x}") cfg.relay-ips)}
12 min-port=${toString cfg.min-port}
13 max-port=${toString cfg.max-port}
14 ${lib.optionalString cfg.lt-cred-mech "lt-cred-mech"}
15 ${lib.optionalString cfg.no-auth "no-auth"}
16 ${lib.optionalString cfg.use-auth-secret "use-auth-secret"}
17 ${lib.optionalString (cfg.static-auth-secret != null) ("static-auth-secret=${cfg.static-auth-secret}")}
18 ${lib.optionalString (cfg.static-auth-secret-file != null) ("static-auth-secret=#static-auth-secret#")}
19 realm=${cfg.realm}
20 ${lib.optionalString cfg.no-udp "no-udp"}
21 ${lib.optionalString cfg.no-tcp "no-tcp"}
22 ${lib.optionalString cfg.no-tls "no-tls"}
23 ${lib.optionalString cfg.no-dtls "no-dtls"}
24 ${lib.optionalString cfg.no-udp-relay "no-udp-relay"}
25 ${lib.optionalString cfg.no-tcp-relay "no-tcp-relay"}
26 ${lib.optionalString (cfg.cert != null) "cert=${cfg.cert}"}
27 ${lib.optionalString (cfg.pkey != null) "pkey=${cfg.pkey}"}
28 ${lib.optionalString (cfg.dh-file != null) ("dh-file=${cfg.dh-file}")}
29 no-stdout-log
30 syslog
31 pidfile=${pidfile}
32 ${lib.optionalString cfg.secure-stun "secure-stun"}
33 ${lib.optionalString cfg.no-cli "no-cli"}
34 cli-ip=${cfg.cli-ip}
35 cli-port=${toString cfg.cli-port}
36 ${lib.optionalString (cfg.cli-password != null) ("cli-password=${cfg.cli-password}")}
37 ${cfg.extraConfig}
38 '';
39 in {
40   options = {
41     services.coturn = {
42       enable = lib.mkEnableOption "coturn TURN server";
43       listening-port = lib.mkOption {
44         type = lib.types.int;
45         default = 3478;
46         description = ''
47           TURN listener port for UDP and TCP.
48           Note: actually, TLS and DTLS sessions can connect to the
49           "plain" TCP and UDP port(s), too - if allowed by configuration.
50         '';
51       };
52       tls-listening-port = lib.mkOption {
53         type = lib.types.int;
54         default = 5349;
55         description = ''
56           TURN listener port for TLS.
57           Note: actually, "plain" TCP and UDP sessions can connect to the TLS and
58           DTLS port(s), too - if allowed by configuration. The TURN server
59           "automatically" recognizes the type of traffic. Actually, two listening
60           endpoints (the "plain" one and the "tls" one) are equivalent in terms of
61           functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
62           For secure TCP connections, we currently support SSL version 3 and
63           TLS version 1.0, 1.1 and 1.2.
64           For secure UDP connections, we support DTLS version 1.
65         '';
66       };
67       alt-listening-port = lib.mkOption {
68         type = lib.types.int;
69         default = cfg.listening-port + 1;
70         defaultText = lib.literalExpression "listening-port + 1";
71         description = ''
72           Alternative listening port for UDP and TCP listeners;
73           default (or zero) value means "listening port plus one".
74           This is needed for RFC 5780 support
75           (STUN extension specs, NAT behavior discovery). The TURN Server
76           supports RFC 5780 only if it is started with more than one
77           listening IP address of the same family (IPv4 or IPv6).
78           RFC 5780 is supported only by UDP protocol, other protocols
79           are listening to that endpoint only for "symmetry".
80         '';
81       };
82       alt-tls-listening-port = lib.mkOption {
83         type = lib.types.int;
84         default = cfg.tls-listening-port + 1;
85         defaultText = lib.literalExpression "tls-listening-port + 1";
86         description = ''
87           Alternative listening port for TLS and DTLS protocols.
88         '';
89       };
90       listening-ips = lib.mkOption {
91         type = lib.types.listOf lib.types.str;
92         default = [];
93         example = [ "203.0.113.42" "2001:DB8::42" ];
94         description = ''
95           Listener IP addresses of relay server.
96           If no IP(s) specified in the config file or in the command line options,
97           then all IPv4 and IPv6 system IPs will be used for listening.
98         '';
99       };
100       relay-ips = lib.mkOption {
101         type = lib.types.listOf lib.types.str;
102         default = [];
103         example = [ "203.0.113.42" "2001:DB8::42" ];
104         description = ''
105           Relay address (the local IP address that will be used to relay the
106           packets to the peer).
107           Multiple relay addresses may be used.
108           The same IP(s) can be used as both listening IP(s) and relay IP(s).
110           If no relay IP(s) specified, then the turnserver will apply the default
111           policy: it will decide itself which relay addresses to be used, and it
112           will always be using the client socket IP address as the relay IP address
113           of the TURN session (if the requested relay address family is the same
114           as the family of the client socket).
115         '';
116       };
117       min-port = lib.mkOption {
118         type = lib.types.int;
119         default = 49152;
120         description = ''
121           Lower bound of UDP relay endpoints
122         '';
123       };
124       max-port = lib.mkOption {
125         type = lib.types.int;
126         default = 65535;
127         description = ''
128           Upper bound of UDP relay endpoints
129         '';
130       };
131       lt-cred-mech = lib.mkOption {
132         type = lib.types.bool;
133         default = false;
134         description = ''
135           Use long-term credential mechanism.
136         '';
137       };
138       no-auth = lib.mkOption {
139         type = lib.types.bool;
140         default = false;
141         description = ''
142           This option is opposite to lt-cred-mech.
143           (TURN Server with no-auth option allows anonymous access).
144           If neither option is defined, and no users are defined,
145           then no-auth is default. If at least one user is defined,
146           in this file or in command line or in usersdb file, then
147           lt-cred-mech is default.
148         '';
149       };
150       use-auth-secret = lib.mkOption {
151         type = lib.types.bool;
152         default = false;
153         description = ''
154           TURN REST API flag.
155           Flag that sets a special authorization option that is based upon authentication secret.
156           This feature can be used with the long-term authentication mechanism, only.
157           This feature purpose is to support "TURN Server REST API", see
158           "TURN REST API" link in the project's page
159           https://github.com/coturn/coturn/
161           This option is used with timestamp:
163           usercombo -> "timestamp:userid"
164           turn user -> usercombo
165           turn password -> base64(hmac(secret key, usercombo))
167           This allows TURN credentials to be accounted for a specific user id.
168           If you don't have a suitable id, the timestamp alone can be used.
169           This option is just turning on secret-based authentication.
170           The actual value of the secret is defined either by option static-auth-secret,
171           or can be found in the turn_secret table in the database.
172         '';
173       };
174       static-auth-secret = lib.mkOption {
175         type = lib.types.nullOr lib.types.str;
176         default = null;
177         description = ''
178           'Static' authentication secret value (a string) for TURN REST API only.
179           If not set, then the turn server
180           will try to use the 'dynamic' value in turn_secret table
181           in user database (if present). The database-stored  value can be changed on-the-fly
182           by a separate program, so this is why that other mode is 'dynamic'.
183         '';
184       };
185       static-auth-secret-file = lib.mkOption {
186         type = lib.types.nullOr lib.types.str;
187         default = null;
188         description = ''
189           Path to the file containing the static authentication secret.
190         '';
191       };
192       realm = lib.mkOption {
193         type = lib.types.str;
194         default = config.networking.hostName;
195         defaultText = lib.literalExpression "config.networking.hostName";
196         example = "example.com";
197         description = ''
198           The default realm to be used for the users when no explicit
199           origin/realm relationship was found in the database, or if the TURN
200           server is not using any database (just the commands-line settings
201           and the userdb file). Must be used with long-term credentials
202           mechanism or with TURN REST API.
203         '';
204       };
205       cert = lib.mkOption {
206         type = lib.types.nullOr lib.types.str;
207         default = null;
208         example = "/var/lib/acme/example.com/fullchain.pem";
209         description = ''
210           Certificate file in PEM format.
211         '';
212       };
213       pkey = lib.mkOption {
214         type = lib.types.nullOr lib.types.str;
215         default = null;
216         example = "/var/lib/acme/example.com/key.pem";
217         description = ''
218           Private key file in PEM format.
219         '';
220       };
221       dh-file = lib.mkOption {
222         type = lib.types.nullOr lib.types.str;
223         default = null;
224         description = ''
225           Use custom DH TLS key, stored in PEM format in the file.
226         '';
227       };
228       secure-stun = lib.mkOption {
229         type = lib.types.bool;
230         default = false;
231         description = ''
232           Require authentication of the STUN Binding request.
233           By default, the clients are allowed anonymous access to the STUN Binding functionality.
234         '';
235       };
236       no-cli = lib.mkOption {
237         type = lib.types.bool;
238         default = false;
239         description = ''
240           Turn OFF the CLI support.
241         '';
242       };
243       cli-ip = lib.mkOption {
244         type = lib.types.str;
245         default = "127.0.0.1";
246         description = ''
247           Local system IP address to be used for CLI server endpoint.
248         '';
249       };
250       cli-port = lib.mkOption {
251         type = lib.types.int;
252         default = 5766;
253         description = ''
254           CLI server port.
255         '';
256       };
257       cli-password = lib.mkOption {
258         type = lib.types.nullOr lib.types.str;
259         default = null;
260         description = ''
261           CLI access password.
262           For the security reasons, it is recommended to use the encrypted
263           for of the password (see the -P command in the turnadmin utility).
264         '';
265       };
266       no-udp = lib.mkOption {
267         type = lib.types.bool;
268         default = false;
269         description = "Disable UDP client listener";
270       };
271       no-tcp = lib.mkOption {
272         type = lib.types.bool;
273         default = false;
274         description = "Disable TCP client listener";
275       };
276       no-tls = lib.mkOption {
277         type = lib.types.bool;
278         default = false;
279         description = "Disable TLS client listener";
280       };
281       no-dtls = lib.mkOption {
282         type = lib.types.bool;
283         default = false;
284         description = "Disable DTLS client listener";
285       };
286       no-udp-relay = lib.mkOption {
287         type = lib.types.bool;
288         default = false;
289         description = "Disable UDP relay endpoints";
290       };
291       no-tcp-relay = lib.mkOption {
292         type = lib.types.bool;
293         default = false;
294         description = "Disable TCP relay endpoints";
295       };
296       extraConfig = lib.mkOption {
297         type = lib.types.lines;
298         default = "";
299         description = "Additional configuration options";
300       };
301     };
302   };
304   config = lib.mkIf cfg.enable (lib.mkMerge ([
305     { assertions = [
306       { assertion = cfg.static-auth-secret != null -> cfg.static-auth-secret-file == null ;
307         message = "static-auth-secret and static-auth-secret-file cannot be set at the same time";
308       }
309     ];}
311     {
312       users.users.turnserver =
313         { uid = config.ids.uids.turnserver;
314           group = "turnserver";
315           description = "coturn TURN server user";
316         };
317       users.groups.turnserver =
318         { gid = config.ids.gids.turnserver;
319           members = [ "turnserver" ];
320         };
322       systemd.services.coturn = let
323         runConfig = "/run/coturn/turnserver.cfg";
324       in {
325         description = "coturn TURN server";
326         after = [ "network-online.target" ];
327         wants = [ "network-online.target" ];
328         wantedBy = [ "multi-user.target" ];
330         unitConfig = {
331           Documentation = "man:coturn(1) man:turnadmin(1) man:turnserver(1)";
332         };
334         preStart = ''
335           cat ${configFile} > ${runConfig}
336           ${lib.optionalString (cfg.static-auth-secret-file != null) ''
337             ${pkgs.replace-secret}/bin/replace-secret \
338               "#static-auth-secret#" \
339               ${cfg.static-auth-secret-file} \
340               ${runConfig}
341           '' }
342           chmod 640 ${runConfig}
343         '';
344         serviceConfig = {
345           Type = "simple";
346           ExecStart = "${pkgs.coturn}/bin/turnserver -c ${runConfig}";
347           RuntimeDirectory = "turnserver";
348           User = "turnserver";
349           Group = "turnserver";
350           AmbientCapabilities =
351             lib.mkIf (
352               cfg.listening-port < 1024 ||
353               cfg.alt-listening-port < 1024 ||
354               cfg.tls-listening-port < 1024 ||
355               cfg.alt-tls-listening-port < 1024 ||
356               cfg.min-port < 1024
357             ) "cap_net_bind_service";
358           Restart = "on-abort";
359         };
360       };
361     systemd.tmpfiles.rules = [
362       "d  /run/coturn 0700 turnserver turnserver - -"
363     ];
364   }]));