2023-10-17 01:16:08 +00:00
|
|
|
# TURN/STUN NAT traversal service
|
|
|
|
# commonly used to establish realtime calls with prosody, or possibly matrix/synapse
|
2023-10-17 01:16:59 +00:00
|
|
|
#
|
|
|
|
# TODO: fix tel -> xmpp:
|
|
|
|
# - "ERROR: check_stun_auth: Cannot find credentials of user <XXXMMMNNNN>"
|
2023-10-17 09:43:55 +00:00
|
|
|
#
|
|
|
|
# N.B. during operation it's NORMAL to see "error 401".
|
|
|
|
# during session creation:
|
|
|
|
# - client sends Allocate request
|
|
|
|
# - server replies error 401, providing a realm and nonce
|
|
|
|
# - client uses realm + nonce + shared secret to construct an auth key & call Allocate again
|
|
|
|
# - server replies Allocate Success Response
|
|
|
|
# - source: <https://stackoverflow.com/a/66643135>
|
2023-10-17 01:16:08 +00:00
|
|
|
{ lib, ... }:
|
|
|
|
let
|
|
|
|
# TODO: this range could be larger, but right now that's costly because each element is its own UPnP forward
|
|
|
|
# TURN port range (inclusive)
|
|
|
|
turnPortLow = 49152;
|
|
|
|
turnPortHigh = 49167;
|
|
|
|
turnPortRange = lib.range turnPortLow turnPortHigh;
|
|
|
|
in
|
|
|
|
{
|
|
|
|
sane.ports.ports = lib.mkMerge ([
|
|
|
|
{
|
|
|
|
"3478" = {
|
|
|
|
# this is the "control" port.
|
|
|
|
# i.e. no client data is forwarded through it, but it's where clients request tunnels.
|
|
|
|
protocol = [ "tcp" "udp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
visibleTo.wan = true;
|
|
|
|
description = "colin-stun-turn";
|
|
|
|
};
|
|
|
|
"5349" = {
|
|
|
|
# the other port 3478 also supports TLS/DTLS, but presumably clients wanting TLS will default 5349
|
|
|
|
protocol = [ "tcp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
visibleTo.wan = true;
|
|
|
|
description = "colin-stun-turn-over-tls";
|
|
|
|
};
|
|
|
|
}
|
|
|
|
] ++ (builtins.map
|
|
|
|
(port: {
|
|
|
|
"${builtins.toString port}" = let
|
|
|
|
count = port - turnPortLow + 1;
|
|
|
|
numPorts = turnPortHigh - turnPortLow + 1;
|
|
|
|
in {
|
|
|
|
protocol = [ "tcp" "udp" ];
|
|
|
|
visibleTo.lan = true;
|
|
|
|
visibleTo.wan = true;
|
2023-10-17 09:43:55 +00:00
|
|
|
visibleTo.ovpn = true;
|
2023-10-17 01:16:08 +00:00
|
|
|
description = "colin-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
|
|
|
|
};
|
|
|
|
})
|
|
|
|
turnPortRange
|
|
|
|
));
|
|
|
|
|
|
|
|
services.nginx.virtualHosts."turn.uninsane.org" = {
|
|
|
|
# allow ACME to procure a cert via nginx for this domain
|
|
|
|
enableACME = true;
|
|
|
|
};
|
2023-10-17 01:16:59 +00:00
|
|
|
sane.dns.zones."uninsane.org".inet = {
|
2023-10-17 09:43:55 +00:00
|
|
|
# CNAME."turn" = "servo.wan";
|
|
|
|
# CNAME."turn" = "ovpns";
|
|
|
|
# CNAME."turn" = "native";
|
|
|
|
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
|
|
|
|
A."turn" = "%AOVPNS%";
|
|
|
|
|
|
|
|
SRV."_stun._udp" = "5 50 3478 turn";
|
|
|
|
SRV."_stun._tcp" = "5 50 3478 turn";
|
|
|
|
SRV."_stuns._tcp" = "5 50 5349 turn";
|
|
|
|
SRV."_turn._udp" = "5 50 3478 turn";
|
|
|
|
SRV."_turn._tcp" = "5 50 3478 turn";
|
|
|
|
SRV."_turns._tcp" = "5 50 5349 turn";
|
2023-10-17 01:16:59 +00:00
|
|
|
};
|
2023-10-17 01:16:08 +00:00
|
|
|
|
|
|
|
sane.derived-secrets."/var/lib/coturn/shared_secret.bin" = {
|
|
|
|
encoding = "base64";
|
|
|
|
# TODO: make this not globally readable
|
|
|
|
acl.mode = "0644";
|
|
|
|
};
|
2023-10-17 09:43:55 +00:00
|
|
|
sane.fs."/var/lib/coturn/shared_secret.bin".wantedBeforeBy = [ "coturn.service" ];
|
2023-10-17 01:16:08 +00:00
|
|
|
|
2023-10-17 01:16:59 +00:00
|
|
|
# provide access to certs
|
|
|
|
users.users.turnserver.extraGroups = [ "nginx" ];
|
|
|
|
|
2023-10-17 01:16:08 +00:00
|
|
|
services.coturn.enable = true;
|
|
|
|
services.coturn.realm = "turn.uninsane.org";
|
|
|
|
services.coturn.cert = "/var/lib/acme/turn.uninsane.org/fullchain.pem";
|
|
|
|
services.coturn.pkey = "/var/lib/acme/turn.uninsane.org/key.pem";
|
2023-10-17 01:16:59 +00:00
|
|
|
services.coturn.use-auth-secret = true;
|
2023-10-17 01:16:08 +00:00
|
|
|
services.coturn.static-auth-secret-file = "/var/lib/coturn/shared_secret.bin";
|
2023-10-17 09:43:55 +00:00
|
|
|
services.coturn.lt-cred-mech = true;
|
2023-10-17 01:16:08 +00:00
|
|
|
services.coturn.min-port = turnPortLow;
|
|
|
|
services.coturn.max-port = turnPortHigh;
|
2023-10-17 09:43:55 +00:00
|
|
|
# services.coturn.secure-stun = true;
|
2023-10-17 01:16:08 +00:00
|
|
|
services.coturn.extraConfig = ''
|
2023-10-17 09:43:55 +00:00
|
|
|
verbose
|
2023-10-17 01:16:08 +00:00
|
|
|
no-multicast-peers
|
|
|
|
'';
|
|
|
|
}
|