2024-01-10 04:11:11 +00:00
|
|
|
# Cloudflare Tunnel is a service for accessing the network even behind a
|
|
|
|
# firewall, through outbound-only requests. It works by installing an agent on
|
|
|
|
# our machines that exposes services through Cloudflare Access (Zero Trust),
|
|
|
|
# similar to something like Tailscale.
|
|
|
|
|
|
|
|
# In this case, we're using Cloudflare Tunnel to enable SSH access over a web
|
|
|
|
# browser even when outside of my network. This is probably not the safest
|
|
|
|
# choice but I feel comfortable enough with it anyway.
|
|
|
|
|
2023-04-29 16:00:31 +00:00
|
|
|
{ config, lib, ... }:
|
|
|
|
|
|
|
|
# First time setup:
|
|
|
|
|
|
|
|
# nix-shell -p cloudflared
|
|
|
|
# cloudflared tunnel login
|
2023-06-19 12:30:30 +00:00
|
|
|
# cloudflared tunnel create <host>
|
|
|
|
# nix run github:nmasur/dotfiles#encrypt-secret > private/cloudflared-<host>.age
|
2023-04-29 16:00:31 +00:00
|
|
|
# Paste ~/.cloudflared/<id>.json
|
2023-06-19 12:30:30 +00:00
|
|
|
# Set tunnel.id = "<id>"
|
2023-04-29 16:00:31 +00:00
|
|
|
# Remove ~/.cloudflared/
|
|
|
|
|
2023-07-03 15:49:21 +00:00
|
|
|
# For SSH access:
|
|
|
|
# Cloudflare Zero Trust -> Access -> Applications -> Create Application
|
|
|
|
# Service Auth -> SSH -> Select Application -> Generate Certificate
|
|
|
|
# Set ca = "<public key>"
|
|
|
|
|
2023-06-19 12:30:30 +00:00
|
|
|
{
|
2023-04-29 16:00:31 +00:00
|
|
|
|
2023-06-19 12:30:30 +00:00
|
|
|
options.cloudflareTunnel = {
|
|
|
|
enable = lib.mkEnableOption "Use Cloudflare Tunnel";
|
|
|
|
id = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Cloudflare tunnel ID";
|
|
|
|
};
|
|
|
|
credentialsFile = lib.mkOption {
|
|
|
|
type = lib.types.path;
|
|
|
|
description = "Cloudflare tunnel credentials file (age-encrypted)";
|
|
|
|
};
|
|
|
|
ca = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Cloudflare tunnel CA public key";
|
|
|
|
};
|
|
|
|
};
|
2023-04-29 16:00:31 +00:00
|
|
|
|
2023-04-30 21:51:35 +00:00
|
|
|
config = lib.mkIf config.cloudflareTunnel.enable {
|
2023-04-29 16:00:31 +00:00
|
|
|
|
|
|
|
services.cloudflared = {
|
|
|
|
enable = true;
|
|
|
|
tunnels = {
|
2023-06-19 12:30:30 +00:00
|
|
|
"${config.cloudflareTunnel.id}" = {
|
2023-04-29 16:00:31 +00:00
|
|
|
credentialsFile = config.secrets.cloudflared.dest;
|
2024-01-10 04:11:11 +00:00
|
|
|
# Catch-all if no match (should never happen anyway)
|
2023-04-29 16:00:31 +00:00
|
|
|
default = "http_status:404";
|
2024-01-10 04:11:11 +00:00
|
|
|
# Match from ingress of any valid server name to SSH access
|
2024-04-20 13:42:06 +00:00
|
|
|
ingress = {
|
|
|
|
"*.masu.rs" = "ssh://localhost:22";
|
|
|
|
};
|
2023-04-29 16:00:31 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2024-01-10 04:11:11 +00:00
|
|
|
# Grant Cloudflare access to SSH into this server
|
2023-04-29 16:00:31 +00:00
|
|
|
environment.etc = {
|
|
|
|
"ssh/ca.pub".text = ''
|
2023-06-19 12:30:30 +00:00
|
|
|
${config.cloudflareTunnel.ca}
|
2023-04-29 16:00:31 +00:00
|
|
|
'';
|
|
|
|
|
2024-01-10 04:11:11 +00:00
|
|
|
# Must match the username portion of the email address in Cloudflare
|
|
|
|
# Access
|
2023-04-29 16:00:31 +00:00
|
|
|
"ssh/authorized_principals".text = ''
|
|
|
|
${config.user}
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2024-01-10 04:11:11 +00:00
|
|
|
# Adjust SSH config to allow access from Cloudflare's certificate
|
2023-04-29 16:00:31 +00:00
|
|
|
services.openssh.extraConfig = ''
|
|
|
|
PubkeyAuthentication yes
|
|
|
|
TrustedUserCAKeys /etc/ssh/ca.pub
|
|
|
|
Match User '${config.user}'
|
|
|
|
AuthorizedPrincipalsFile /etc/ssh/authorized_principals
|
|
|
|
# if there is no existing AuthenticationMethods
|
|
|
|
AuthenticationMethods publickey
|
|
|
|
'';
|
2024-04-20 13:42:06 +00:00
|
|
|
services.openssh.settings.Macs = [ "hmac-sha2-512" ]; # Fix for failure to find matching mac
|
2023-04-29 16:00:31 +00:00
|
|
|
|
|
|
|
# Create credentials file for Cloudflare
|
|
|
|
secrets.cloudflared = {
|
2023-06-19 12:30:30 +00:00
|
|
|
source = config.cloudflareTunnel.credentialsFile;
|
2023-04-29 16:00:31 +00:00
|
|
|
dest = "${config.secretsDirectory}/cloudflared";
|
|
|
|
owner = "cloudflared";
|
|
|
|
group = "cloudflared";
|
|
|
|
permissions = "0440";
|
|
|
|
};
|
|
|
|
systemd.services.cloudflared-secret = {
|
2024-04-20 13:42:06 +00:00
|
|
|
requiredBy = [ "cloudflared-tunnel-${config.cloudflareTunnel.id}.service" ];
|
2023-06-19 12:30:30 +00:00
|
|
|
before = [ "cloudflared-tunnel-${config.cloudflareTunnel.id}.service" ];
|
2023-04-29 16:00:31 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|