Reusable cnx.router.* module for the Topton 1U boxes replacing OPNsense: PPPoE WAN (optionally VLAN-tagged, AIS: 10, secret credentials incl. username), VLAN-filtering bridge, nftables NAT/firewall with MSS clamp, Kea DHCP with per-VLAN lease time, Blocky DNS, DHCPv6-PD, CrowdSec with the ZeroTier mesh whitelisted, optional Omada controller, ZFS disk. Fleet baseline rides along: admins sops group is now derived for every machine in clan.nix (secrets encrypt to it from the first vars generate) and time sync is chrony everywhere instead of systemd-timesyncd.
53 lines
1.4 KiB
Nix
53 lines
1.4 KiB
Nix
# CrowdSec security engine + nftables bouncer: parses sshd auth attempts from
|
|
# the journal and bans offending source IPs at the firewall. Log-based (no
|
|
# inline DPI) so it costs the N300 next to nothing.
|
|
{
|
|
config,
|
|
lib,
|
|
...
|
|
}:
|
|
let
|
|
cfg = config.cnx.router;
|
|
mesh = import ../mesh-hosts.nix { inherit config lib; };
|
|
in
|
|
{
|
|
config = lib.mkIf cfg.enable {
|
|
services.crowdsec = {
|
|
enable = true;
|
|
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 = [ mesh.subnet ];
|
|
};
|
|
}
|
|
];
|
|
};
|
|
};
|
|
|
|
services.crowdsec-firewall-bouncer = {
|
|
enable = true;
|
|
registerBouncer.enable = true;
|
|
settings.mode = "nftables";
|
|
};
|
|
};
|
|
}
|