diff --git a/modules/clan/gw-router/crowdsec.nix b/modules/clan/gw-router/crowdsec.nix index f706b07..95fc8bb 100644 --- a/modules/clan/gw-router/crowdsec.nix +++ b/modules/clan/gw-router/crowdsec.nix @@ -1,59 +1,59 @@ -{ config, ... }: -let - -in { - roles.default.perInstance = break{ settings, ... }: { + roles.default.perInstance = { settings, ... }: { nixosModule = - { config, ... }: + { + config, + ... + }: let + + dir = config.clan.core.settings.directory; + instance = "zerotier"; + + networkId = builtins.readFile "${dir}/vars/shared/zerotier-network-${instance}/network-id/value"; + full = "fd" + networkId + "9993"; + hextet = i: builtins.substring (i * 4) 4 full; + subnetZtier = "${hextet 0}:${hextet 1}:${hextet 2}:${hextet 3}:${hextet 4}:${builtins.substring 20 2 full}00::/88"; in { - clan.core.vars.generators.gw-router = { - prompts.pppoe-username = { - description = "PPPoE username (from the ISP)"; - type = "hidden"; - }; - prompts.pppoe-password = { - description = "PPPoE password (from the ISP)"; - type = "hidden"; - }; - files."pppoe-username".secret = true; - files."pppoe-password".secret = true; - script = '' - user="$(cat "$prompts"/pppoe-username)" - pass="$(cat "$prompts"/pppoe-password)" - printf 'user "%s"\n' "$user" > "$out"/pppoe-username - printf '"%s" * "%s"\n' "$user" "$pass" > "$out"/pppoe-password - ''; - }; - services.pppd = { + services.crowdsec = { enable = true; - peers.wan = { - autostart = true; - config = '' - plugin pppoe.so ${pppInterface} - ifname ppp0 - file ${creds.files."pppoe-username".path} - noipdefault - defaultroute - noauth - hide-password - persist - maxfail 0 - holdoff 5 - lcp-echo-interval 15 - lcp-echo-failure 3 - +ipv6 - mtu 1492 - mru 1492 - ''; + autoUpdateService = true; + hub.collections = [ + "crowdsecurity/linux" + "crowdsecurity/sshd" + ]; + localConfig = { + acquisitions = [ + { + source = "journalctl"; + journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ]; + labels.type = "syslog"; + } + ]; + # Never ban the ZeroTier mesh — it is the only admin path to these + # boxes (no public SSH), so a false positive would lock us out. + # Parser-stage whitelist: mesh events are dropped before any scenario. + parsers.s02Enrich = [ + { + name = "cnx/mesh-whitelist"; + description = "Whitelist the ZeroTier management mesh"; + whitelist = { + reason = "ZeroTier mesh is the admin path"; + cidr = [ subnetZtier ]; + }; + } + ]; }; }; - environment.etc."ppp/chap-secrets".source = creds.files."pppoe-password".path; - environment.etc."ppp/pap-secrets".source = creds.files."pppoe-password".path; + services.crowdsec-firewall-bouncer = { + enable = true; + registerBouncer.enable = true; + settings.mode = "nftables"; + }; + }; }; }