fix(teal.headscale): Allow access to the internet
Previously internet access was denied by ACLs, so even if you did set up
an exit node no traffic would flow.
In Tailscale there's a thing called "autogroup:internet", which is a
list of all the IP addresses in the internet. That's awesome, but sadly
it's not yet supported in headscale (it's in the upcoming release)
We can define our own internet. We can't use builtin groups (because
they're IPs not users) and we can't use builtin hosts (because there's
no way I could find to specify multiple prefixes for a host), however
Nix comes to our rescue and gives us the ability to define a list and
map over it.
There's one more cursed hack: the IPv6 address space uses colons (::) to
denote separators. Unfortunately, including the address as-is leaves us
with a mixup where headscale interprets part of the address as a port,
considers the ACLs broken and refuses to start. Luckily, as there's only
one affected address we can pretty easily define a host for it, which
solves the issue as the parsing happens earlier... yay..?
Change-Id: Id4d51cd6b358a6cd150d7221087564882efd4e2c
Reviewed-on: https://git.clicks.codes/c/Infra/NixFiles/+/754
Tested-by: Skyler Grey <minion@clicks.codes>
Reviewed-by: Samuel Shuert <coded@clicks.codes>
diff --git a/systems/x86_64-linux/teal/default.nix b/systems/x86_64-linux/teal/default.nix
index f7627c5..e092b7c 100644
--- a/systems/x86_64-linux/teal/default.nix
+++ b/systems/x86_64-linux/teal/default.nix
@@ -48,50 +48,109 @@
config.clicks.secrets."${lib.clicks.secrets.name ./headscale.sops.json}".paths.noise_private_key;
private_key_path =
config.clicks.secrets."${lib.clicks.secrets.name ./headscale.sops.json}".paths.private_key;
- acl = {
- groups."group:users" = [
- "minion"
- "coded"
- "pineafan"
- ];
- groups."group:areas" = [
- # Some phonetic alphabet names are excluded here to avoid confusing
- # them with given names
- "alpha"
- "bravo"
- "delta"
- "echo"
- "foxtrot"
- "golf"
- "hotel"
- "india"
- "kilo"
- "lima"
- "november"
- "papa"
- "quebec"
- "sierra"
- "tango"
- "uniform"
- "whiskey"
- "xray"
- "yankee"
- "zulu"
- ];
+ acl =
+ let
+ internet = [
+ "0.0.0.0/5"
+ "8.0.0.0/7"
+ "11.0.0.0/8"
+ "12.0.0.0/6"
+ "16.0.0.0/4"
+ "32.0.0.0/3"
+ "64.0.0.0/3"
+ "96.0.0.0/6"
+ "100.0.0.0/10"
+ "100.128.0.0/9"
+ "101.0.0.0/8"
+ "102.0.0.0/7"
+ "104.0.0.0/5"
+ "112.0.0.0/4"
+ "128.0.0.0/3"
+ "160.0.0.0/5"
+ "168.0.0.0/8"
+ "169.0.0.0/9"
+ "169.128.0.0/10"
+ "169.192.0.0/11"
+ "169.224.0.0/12"
+ "169.240.0.0/13"
+ "169.248.0.0/14"
+ "169.252.0.0/15"
+ "169.255.0.0/16"
+ "170.0.0.0/7"
+ "172.0.0.0/12"
+ "172.32.0.0/11"
+ "172.64.0.0/10"
+ "172.128.0.0/9"
+ "173.0.0.0/8"
+ "174.0.0.0/7"
+ "176.0.0.0/4"
+ "192.0.0.0/9"
+ "192.128.0.0/11"
+ "192.160.0.0/13"
+ "192.169.0.0/16"
+ "192.170.0.0/15"
+ "192.172.0.0/14"
+ "192.176.0.0/12"
+ "192.192.0.0/10"
+ "193.0.0.0/8"
+ "194.0.0.0/7"
+ "196.0.0.0/6"
+ "200.0.0.0/5"
+ "208.0.0.0/4"
+ "224.0.0.0/3"
+ "ipv6-internet"
+ # A nasty hack used because ipv6 colons were messing with dst
+ # ports
+ ]; # Should be replaceable with autogroup:internet in next release
+ in
+ {
+ groups."group:users" = [
+ "minion"
+ "coded"
+ "pineafan"
+ ];
+ groups."group:areas" = [
+ # Some phonetic alphabet names are excluded here to avoid confusing
+ # them with given names
+ "alpha"
+ "bravo"
+ "delta"
+ "echo"
+ "foxtrot"
+ "golf"
+ "hotel"
+ "india"
+ "kilo"
+ "lima"
+ "november"
+ "papa"
+ "quebec"
+ "sierra"
+ "tango"
+ "uniform"
+ "whiskey"
+ "xray"
+ "yankee"
+ "zulu"
+ ];
+ hosts.ipv6-internet = "2000::/3";
- acls = [
- {
- action = "accept";
- src = [ "group:users" ];
- dst = [ "group:users:*" "group:areas:*" ];
- }
- {
- action = "accept";
- src = [ "group:areas" ];
- dst = [ "group:areas:*" ];
- }
- ];
- };
+ acls = [
+ {
+ action = "accept";
+ src = [ "group:users" ];
+ dst = [
+ "group:users:*"
+ "group:areas:*"
+ ] ++ (lib.forEach internet (host: "${host}:*"));
+ }
+ {
+ action = "accept";
+ src = [ "group:areas" ];
+ dst = [ "group:areas:*" ];
+ }
+ ];
+ };
};
};