forked from DGNum/infrastructure
feat(firewall): Sunset fail2ban and switch to reaction
This commit is contained in:
parent
86c1018dc8
commit
fd0aeacff4
12 changed files with 137 additions and 214 deletions
|
@ -4,7 +4,6 @@ lib.extra.mkConfig {
|
|||
enabledModules = [
|
||||
# List of modules to enable
|
||||
"dgn-backups"
|
||||
"dgn-fail2ban"
|
||||
"dgn-web"
|
||||
];
|
||||
|
||||
|
@ -32,11 +31,6 @@ lib.extra.mkConfig {
|
|||
];
|
||||
|
||||
extraConfig = {
|
||||
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
|
||||
"sshd-bruteforce"
|
||||
"sshd-timeout"
|
||||
];
|
||||
|
||||
dgn-hardware.useZfs = true;
|
||||
|
||||
services.netbird.enable = true;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
lib.extra.mkConfig {
|
||||
enabledModules = [
|
||||
# List of modules to enable
|
||||
"dgn-fail2ban"
|
||||
];
|
||||
|
||||
enabledServices = [
|
||||
|
@ -12,11 +11,6 @@ lib.extra.mkConfig {
|
|||
];
|
||||
|
||||
extraConfig = {
|
||||
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
|
||||
"sshd-bruteforce"
|
||||
"sshd-timeout"
|
||||
];
|
||||
|
||||
services.netbird.enable = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ lib.extra.mkConfig {
|
|||
enabledModules = [
|
||||
# List of modules to enable
|
||||
"dgn-backups"
|
||||
"dgn-fail2ban"
|
||||
"dgn-web"
|
||||
];
|
||||
|
||||
|
@ -22,8 +21,6 @@ lib.extra.mkConfig {
|
|||
];
|
||||
|
||||
extraConfig = {
|
||||
dgn-fail2ban.jails.sshd-preauth.enabled = true;
|
||||
|
||||
dgn-hardware.useZfs = true;
|
||||
|
||||
services.netbird.enable = true;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
lib.extra.mkConfig {
|
||||
enabledModules = [
|
||||
# List of modules to enable
|
||||
"dgn-fail2ban"
|
||||
];
|
||||
|
||||
enabledServices = [
|
||||
|
@ -14,11 +13,6 @@ lib.extra.mkConfig {
|
|||
];
|
||||
|
||||
extraConfig = {
|
||||
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
|
||||
"sshd-bruteforce"
|
||||
"sshd-timeout"
|
||||
];
|
||||
|
||||
services.netbird.enable = true;
|
||||
services.nginx.enable = true;
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
lib.extra.mkConfig {
|
||||
enabledModules = [
|
||||
# List of modules to enable
|
||||
"dgn-fail2ban"
|
||||
"dgn-web"
|
||||
];
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
lib.extra.mkConfig {
|
||||
enabledModules = [
|
||||
# List of modules to enable
|
||||
"dgn-fail2ban"
|
||||
"dgn-web"
|
||||
];
|
||||
|
||||
|
@ -14,11 +13,6 @@ lib.extra.mkConfig {
|
|||
];
|
||||
|
||||
extraConfig = {
|
||||
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
|
||||
"sshd-bruteforce"
|
||||
"sshd-timeout"
|
||||
];
|
||||
|
||||
# Restrict access to this node
|
||||
dgn-access-control.users.root = [ "thubrecht" ];
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
"dgn-acme"
|
||||
"dgn-backups"
|
||||
"dgn-console"
|
||||
"dgn-fail2ban"
|
||||
"dgn-firewall"
|
||||
"dgn-hardware"
|
||||
"dgn-netbox-agent"
|
||||
"dgn-network"
|
||||
|
@ -67,6 +67,7 @@
|
|||
[
|
||||
"age-secrets"
|
||||
"services/bupstash"
|
||||
"services/reaction"
|
||||
"services/systemd-notify"
|
||||
]
|
||||
++ nodeMeta.nix-modules
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.dgn-fail2ban;
|
||||
|
||||
settingsFormat = pkgs.formats.keyValue { };
|
||||
|
||||
configFormat = pkgs.formats.ini { };
|
||||
|
||||
jailOptions = {
|
||||
options = {
|
||||
enabled = mkOption {
|
||||
type = types.bool;
|
||||
|
||||
default = true;
|
||||
description = "Wether to enable this jail.";
|
||||
};
|
||||
|
||||
filter = mkOption {
|
||||
type = types.nullOr (types.submodule { freeformType = configFormat.type; });
|
||||
|
||||
description = "Content of the filter used for this jail.";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule { freeformType = settingsFormat.type; };
|
||||
|
||||
default = { };
|
||||
description = "Additional configuration for the jail.";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.dgn-fail2ban = {
|
||||
enable = mkEnableOption "fail2ban service.";
|
||||
|
||||
jails = mkOption {
|
||||
type = types.attrsOf (types.submodule jailOptions);
|
||||
|
||||
default = { };
|
||||
description = "Set of jails defined for fail2ban.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
dgn-fail2ban.jails = builtins.mapAttrs (_: j: j // { enabled = mkDefault false; }) (
|
||||
import ./jails.nix { }
|
||||
);
|
||||
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
|
||||
inherit (cfg) jails;
|
||||
|
||||
ignoreIP = [
|
||||
"10.0.0.0/8"
|
||||
"129.199.0.0/16"
|
||||
"172.16.0.0/12"
|
||||
"192.168.0.0/16"
|
||||
"100.64.0.0/10"
|
||||
"fd00::/8"
|
||||
];
|
||||
|
||||
bantime-increment = {
|
||||
enable = true;
|
||||
|
||||
maxtime = "48h";
|
||||
factor = "600";
|
||||
};
|
||||
|
||||
extraPackages = [ pkgs.ipset ];
|
||||
banaction = "iptables-ipset-proto6-allports";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
# Copyright Tom Hubrecht, (2023)
|
||||
#
|
||||
# Tom Hubrecht <tom@hubrecht.ovh>
|
||||
#
|
||||
# This software is a computer program whose purpose is to configure
|
||||
# machines and servers with NixOS.
|
||||
#
|
||||
# This software is governed by the CeCILL license under French law and
|
||||
# abiding by the rules of distribution of free software. You can use,
|
||||
# modify and/ or redistribute the software under the terms of the CeCILL
|
||||
# license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
# "http://www.cecill.info".
|
||||
#
|
||||
# As a counterpart to the access to the source code and rights to copy,
|
||||
# modify and redistribute granted by the license, users are provided only
|
||||
# with a limited warranty and the software's author, the holder of the
|
||||
# economic rights, and the successive licensors have only limited
|
||||
# liability.
|
||||
#
|
||||
# In this respect, the user's attention is drawn to the risks associated
|
||||
# with loading, using, modifying and/or developing or reproducing the
|
||||
# software by the user in light of its specific status of free software,
|
||||
# that may mean that it is complicated to manipulate, and that also
|
||||
# therefore means that it is reserved for developers and experienced
|
||||
# professionals having in-depth computer knowledge. Users are therefore
|
||||
# encouraged to load and test the software's suitability as regards their
|
||||
# requirements in conditions enabling the security of their systems and/or
|
||||
# data to be ensured and, more generally, to use and operate it in the
|
||||
# same conditions as regards security.
|
||||
#
|
||||
# The fact that you are presently reading this means that you have had
|
||||
# knowledge of the CeCILL license and that you accept its terms.
|
||||
|
||||
_: {
|
||||
nginx-spam = {
|
||||
filter.Definition.failregex = ''^<HOST>.*GET.*(matrix/server|\.php|admin|wp\-).* HTTP/\d.\d\" 404.*$'';
|
||||
|
||||
settings = {
|
||||
logpath = "/var/log/nginx/access.log";
|
||||
backend = "auto";
|
||||
maxretry = 500;
|
||||
findtime = 60;
|
||||
};
|
||||
};
|
||||
|
||||
postfix-bruteforce = {
|
||||
filter.Definition = {
|
||||
failregex = "warning: [\\w\\.\\-]+\\[<HOST>\\]: SASL LOGIN authentication failed.*$";
|
||||
journalmatch = "_SYSTEMD_UNIT=postfix.service";
|
||||
};
|
||||
|
||||
settings = {
|
||||
findtime = 600;
|
||||
maxretry = 1;
|
||||
};
|
||||
};
|
||||
|
||||
sshd-bruteforce = {
|
||||
filter.Definition = {
|
||||
failregex = "pam_unix\\(sshd:auth\\): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=<ADDR>.*$";
|
||||
journalmatch = "_SYSTEMD_UNIT=sshd.service";
|
||||
};
|
||||
|
||||
settings = {
|
||||
findtime = 600;
|
||||
maxretry = 1;
|
||||
};
|
||||
};
|
||||
|
||||
sshd-preauth = {
|
||||
filter.Definition = {
|
||||
failregex = "Received disconnect from <ADDR> port .* Bye Bye \\[preauth\\]$";
|
||||
journalmatch = "_SYSTEMD_UNIT=sshd.service";
|
||||
};
|
||||
|
||||
settings = {
|
||||
findtime = 600;
|
||||
maxretry = 1;
|
||||
};
|
||||
};
|
||||
|
||||
sshd-timeout = {
|
||||
filter.Definition = {
|
||||
failregex = "fatal: Timeout before authentication for <ADDR>.*$";
|
||||
journalmatch = "_SYSTEMD_UNIT=sshd.service";
|
||||
};
|
||||
|
||||
settings = {
|
||||
findtime = 600;
|
||||
maxretry = 1;
|
||||
};
|
||||
};
|
||||
}
|
87
modules/dgn-firewall/default.nix
Normal file
87
modules/dgn-firewall/default.nix
Normal file
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
name,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
length
|
||||
replicate
|
||||
splitString
|
||||
;
|
||||
|
||||
inherit (lib.lists) map;
|
||||
|
||||
c4 = "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
|
||||
|
||||
mkV4' = p: concatStringsSep "\\." (p ++ (replicate (4 - (length p)) c4));
|
||||
mkV4 = s: mkV4' (splitString "." s);
|
||||
|
||||
nft = s: [ "nft" ] ++ [ s ];
|
||||
|
||||
streams' = import ./streams.nix;
|
||||
in
|
||||
|
||||
{
|
||||
# Switch to nftables
|
||||
networking.nftables.enable = true;
|
||||
|
||||
services.reaction = {
|
||||
enable = true;
|
||||
|
||||
extraPackages = [ pkgs.nftables ];
|
||||
|
||||
runAsRoot = true;
|
||||
|
||||
logLevel = "WARN";
|
||||
|
||||
settings = {
|
||||
patterns = {
|
||||
ip = {
|
||||
regex = "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?:.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|(?:(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
|
||||
|
||||
ignoreregex = map mkV4 [
|
||||
"10" # Legacy wireguard
|
||||
"129.199" # ENS
|
||||
"100.76" # Netbird internal
|
||||
];
|
||||
|
||||
ignore = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
start = [
|
||||
(nft ''
|
||||
table inet reaction {
|
||||
set ipv4bans {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
auto-merge
|
||||
}
|
||||
set ipv6bans {
|
||||
type ipv6_addr
|
||||
flags interval
|
||||
auto-merge
|
||||
}
|
||||
chain input {
|
||||
type filter hook input priority 0
|
||||
policy accept
|
||||
ip saddr @ipv4bans drop
|
||||
ip6 saddr @ipv6bans drop
|
||||
}
|
||||
}
|
||||
'')
|
||||
];
|
||||
|
||||
stop = [ (nft "delete table inet reaction") ];
|
||||
|
||||
streams = streams'.default // (streams'.${name} or { });
|
||||
};
|
||||
};
|
||||
}
|
46
modules/dgn-firewall/streams.nix
Normal file
46
modules/dgn-firewall/streams.nix
Normal file
|
@ -0,0 +1,46 @@
|
|||
let
|
||||
act = a: [
|
||||
"nft46"
|
||||
"${a} element inet reaction ipvXbans { <ip> }"
|
||||
];
|
||||
|
||||
journalctl = u: [
|
||||
"journalctl"
|
||||
"-fn0"
|
||||
"-u"
|
||||
"${u}.service"
|
||||
];
|
||||
|
||||
ban = after: {
|
||||
ban.cmd = act "add";
|
||||
unban = {
|
||||
inherit after;
|
||||
|
||||
cmd = act "delete";
|
||||
};
|
||||
};
|
||||
|
||||
available = {
|
||||
ssh = {
|
||||
cmd = journalctl "sshd";
|
||||
|
||||
filters = {
|
||||
failedlogin = {
|
||||
regex = [
|
||||
"authentication failure;.*rhost=<ip>"
|
||||
"Connection reset by authenticating user .* <ip>"
|
||||
"Connection closed by invalid user .* <ip> port .*"
|
||||
"Failed password for .* from <ip>"
|
||||
"Invalid user .* from <ip> port .*"
|
||||
"Unable to negotiate with <ip> port .*"
|
||||
];
|
||||
actions = ban "48h";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
builtins.mapAttrs (_: builtins.foldl' (a: s: a // { ${s} = available.${s}; }) { }) {
|
||||
default = [ "ssh" ];
|
||||
}
|
|
@ -191,9 +191,9 @@
|
|||
"url": "https://git.hubrecht.ovh/hubrecht/nix-modules.git"
|
||||
},
|
||||
"branch": "main",
|
||||
"revision": "a5645b5b3bed87ce9c9d633ad20537b0edd34e74",
|
||||
"revision": "32e76ee64352587663766e1a3945a6fe0917e35d",
|
||||
"url": null,
|
||||
"hash": "1vmi9ldmc1vibw21bv1lg41mbii8v0w9k3809awyf1ikir99jbyf"
|
||||
"hash": "16vnpnby6s174y4nzb26z2pc49ba7lw7vpf6r7p4dqci92b0yg5j"
|
||||
},
|
||||
"nix-patches": {
|
||||
"type": "GitRelease",
|
||||
|
|
Loading…
Reference in a new issue