diff options
author | Linnnus <[email protected]> | 2024-02-20 19:00:53 +0100 |
---|---|---|
committer | Linnnus <[email protected]> | 2024-02-20 19:01:44 +0100 |
commit | 274e08f50faffe1b8e4a760811b0a12450eae719 (patch) | |
tree | 393449e81f21b6f6b1ea7a701cef0f740cc3b757 /hosts/ahmed/cloudflare-proxy/default.nix | |
parent | 1bbdd3f63a9d8c46b1772cbf2ad9fd83d7ef213b (diff) |
Merge 'reorg' into 'main'
This patch moves in the reorganizational work done on the reorg branch,
mainly:
* Move host-specific modules into hosts/<host>/<module>
* Break up HM config
See the reorg branch for the individual commits.
Diffstat (limited to 'hosts/ahmed/cloudflare-proxy/default.nix')
-rw-r--r-- | hosts/ahmed/cloudflare-proxy/default.nix | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/hosts/ahmed/cloudflare-proxy/default.nix b/hosts/ahmed/cloudflare-proxy/default.nix new file mode 100644 index 0000000..45ccaa6 --- /dev/null +++ b/hosts/ahmed/cloudflare-proxy/default.nix @@ -0,0 +1,88 @@ +# This module adds some extra configuration useful when running behid a Cloudflare Proxy. +# Mainly, it blocks all incomming conncections on relevant ports that aren't +# coming from an official CloudFlare domain. +{ + config, + lib, + pkgs, + metadata, + ... +}: let + # TODO: What happens when these get out of date??? Huh??? You little pissbaby + fileToList = x: lib.strings.splitString "\n" (builtins.readFile x); + cfipv4 = fileToList (pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v4"; + hash = "sha256-8Cxtg7wBqwroV3Fg4DbXAMdFU1m84FTfiE5dfZ5Onns="; + }); + cfipv6 = fileToList (pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v6"; + hash = "sha256-np054+g7rQDE3sr9U8Y/piAp89ldto3pN9K+KCNMoKk="; + }); + + IPv4Whitelist = [metadata.hosts.muhammed.ipAddress]; + IPv6Whitelist = []; +in { + config = { + # Teach NGINX how to extract the proxied IP from proxied requests. + # + # See: https://nixos.wiki/wiki/Nginx#Using_realIP_when_behind_CloudFlare_or_other_CDN + services.nginx.commonHttpConfig = let + realIpsFromList = lib.strings.concatMapStringsSep "\n" (x: "set_real_ip_from ${x};"); + in '' + ${realIpsFromList cfipv4} + ${realIpsFromList cfipv6} + real_ip_header CF-Connecting-IP; + ''; + + # Block non-Cloudflare IP addresses. + networking.firewall = let + chain = "cloudflare-whitelist"; + in { + extraCommands = let + allow-interface = lib.strings.concatMapStringsSep "\n" (i: ''ip46tables --append ${chain} --in-interface ${i} --jump RETURN''); + allow-ip = cmd: lib.strings.concatMapStringsSep "\n" (r: ''${cmd} --append ${chain} --source ${r} --jump RETURN''); + in '' + # Flush the old firewall rules. This behavior mirrors the default firewall service. + # See: https://github.com/NixOS/nixpkgs/blob/ac911bf685eecc17c2df5b21bdf32678b9f88c92/nixos/modules/services/networking/firewall-iptables.nix#L59-L66 + ip46tables --delete INPUT --protocol tcp --destination-port 80 --syn --jump ${chain} 2>/dev/null || true + ip46tables --delete INPUT --protocol tcp --destination-port 443 --syn --jump ${chain} 2>/dev/null || true + ip46tables --flush ${chain} || true + ip46tables --delete-chain ${chain} || true + + # Create a chain that only allows whitelisted IPs through. + ip46tables --new-chain ${chain} + + # Allow trusted interfaces through. + ${allow-interface config.networking.firewall.trustedInterfaces} + + # Allow local whitelisted IPs through + ${allow-ip "iptables" IPv4Whitelist} + ${allow-ip "ip6tables" IPv6Whitelist} + + # Allow Cloudflare's IP ranges through. + ${allow-ip "iptables" cfipv4} + ${allow-ip "ip6tables" cfipv6} + + # Everything else is dropped. + # + # TODO: I would like to use `nixos-fw-log-refuse` here, but I keep + # running into weird issues when reloading the firewall. + # Something about the table not being deleted properly. + ip46tables --append ${chain} --jump DROP + + # Inject our chain as the first check in INPUT (before nixos-fw). + # We want to capture any new incomming TCP connections. + ip46tables --insert INPUT 1 --protocol tcp --destination-port 80 --syn --jump ${chain} + ip46tables --insert INPUT 1 --protocol tcp --destination-port 443 --syn --jump ${chain} + ''; + extraStopCommands = '' + # Clean up added rulesets (${chain}). This mirrors the behavior of the + # default firewall at the time of writing. + # + # See: https://github.com/NixOS/nixpkgs/blob/ac911bf685eecc17c2df5b21bdf32678b9f88c92/nixos/modules/services/networking/firewall-iptables.nix#L218-L219 + ip46tables --delete INPUT --protocol tcp --destination-port 80 --syn --jump ${chain} 2>/dev/null || true + ip46tables --delete INPUT --protocol tcp --destination-port 443 --syn --jump ${chain} 2>/dev/null || true + ''; + }; + }; +} |