fail2ban test
This commit is contained in:
@@ -28,6 +28,9 @@
|
|||||||
};
|
};
|
||||||
network = {
|
network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
extraHosts = ''
|
||||||
|
192.168.88.14 vault.cnst.dev
|
||||||
|
'';
|
||||||
interfaces = {
|
interfaces = {
|
||||||
"eno1" = {
|
"eno1" = {
|
||||||
allowedTCPPorts = [22 80 443];
|
allowedTCPPorts = [22 80 443];
|
||||||
|
|||||||
@@ -128,8 +128,8 @@
|
|||||||
services = {
|
services = {
|
||||||
agenix = {
|
agenix = {
|
||||||
enable = true;
|
enable = true;
|
||||||
kima = {
|
sobotka = {
|
||||||
enable = false;
|
enable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
blueman = {
|
blueman = {
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
{
|
{config, ...}: {
|
||||||
server = {
|
server = {
|
||||||
email = "adam@cnst.dev";
|
email = "adam@cnst.dev";
|
||||||
domain = "cnst.dev";
|
domain = "cnst.dev";
|
||||||
caddy = {
|
caddy = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
|
cfFail2ban = {
|
||||||
|
enable = true;
|
||||||
|
apiKeyFile = config.age.secrets.cloudflareFirewallApiKey.path;
|
||||||
|
zoneId = "0027acdfb8bbe010f55b676ad8698dfb";
|
||||||
|
};
|
||||||
vaultwarden = {
|
vaultwarden = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -121,6 +121,7 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./server
|
./server
|
||||||
./server/caddy
|
./server/caddy
|
||||||
|
./server/cfFail2ban
|
||||||
./server/vaultwarden
|
./server/vaultwarden
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ in {
|
|||||||
default = {};
|
default = {};
|
||||||
description = "Network interface configurations.";
|
description = "Network interface configurations.";
|
||||||
};
|
};
|
||||||
|
extraHosts = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
description = "Extra entries for /etc/hosts.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,6 +50,7 @@ in {
|
|||||||
enable = true;
|
enable = true;
|
||||||
inherit (cfg) interfaces;
|
inherit (cfg) interfaces;
|
||||||
};
|
};
|
||||||
|
extraHosts = cfg.extraHosts;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.NetworkManager = {
|
systemd.services.NetworkManager = {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ in {
|
|||||||
})
|
})
|
||||||
(mkIf cfg.sobotka.enable {
|
(mkIf cfg.sobotka.enable {
|
||||||
secrets = {
|
secrets = {
|
||||||
# Add sobotka specific secrets here
|
cloudflareFirewallApiKey.file = "${self}/secrets/cloudflareFirewallApiKey.age";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(mkIf cfg.toothpc.enable {
|
(mkIf cfg.toothpc.enable {
|
||||||
|
|||||||
109
modules/server/cfFail2ban/default.nix
Normal file
109
modules/server/cfFail2ban/default.nix
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# from @notthebee
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.server.cfFail2ban;
|
||||||
|
in {
|
||||||
|
options.server.cfFail2ban = {
|
||||||
|
enable = lib.mkEnableOption {
|
||||||
|
description = "Enable cloudflare fail2ban";
|
||||||
|
};
|
||||||
|
apiKeyFile = lib.mkOption {
|
||||||
|
description = "File containing your API key, scoped to Firewall Rules: Edit";
|
||||||
|
type = lib.types.str;
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
Authorization: Bearer Qj06My1wXJEzcW46QCyjFbSMgVtwIGfX63Ki3NOj79o=
|
||||||
|
'''
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
zoneId = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
jails = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
serviceName = lib.mkOption {
|
||||||
|
example = "vaultwarden";
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
failRegex = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "Login failed from IP: <HOST>";
|
||||||
|
};
|
||||||
|
ignoreRegex = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
};
|
||||||
|
maxRetry = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.fail2ban = {
|
||||||
|
enable = true;
|
||||||
|
extraPackages = [
|
||||||
|
pkgs.curl
|
||||||
|
pkgs.jq
|
||||||
|
];
|
||||||
|
|
||||||
|
jails =
|
||||||
|
lib.attrsets.mapAttrs (name: value: {
|
||||||
|
settings = {
|
||||||
|
bantime = "30d";
|
||||||
|
findtime = "1h";
|
||||||
|
enabled = true;
|
||||||
|
backend = "systemd";
|
||||||
|
journalmatch = "_SYSTEMD_UNIT=${value.serviceName}.service";
|
||||||
|
port = "http,https";
|
||||||
|
filter = "${name}";
|
||||||
|
maxretry = 3;
|
||||||
|
action = "cloudflare-token-agenix";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
cfg.jails;
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.etc = lib.attrsets.mergeAttrsList [
|
||||||
|
(lib.attrsets.mapAttrs' (
|
||||||
|
name: value: (lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
|
||||||
|
text = ''
|
||||||
|
[Definition]
|
||||||
|
failregex = ${value.failRegex}
|
||||||
|
ignoreregex = ${value.ignoreRegex}
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
)
|
||||||
|
cfg.jails)
|
||||||
|
{
|
||||||
|
"fail2ban/action.d/cloudflare-token-agenix.conf".text = let
|
||||||
|
notes = "Fail2Ban on ${config.networking.hostName}";
|
||||||
|
cfapi = "https://api.cloudflare.com/client/v4/zones/${cfg.zoneId}/firewall/access_rules/rules";
|
||||||
|
in ''
|
||||||
|
[Definition]
|
||||||
|
actionstart =
|
||||||
|
actionstop =
|
||||||
|
actioncheck =
|
||||||
|
actionunban = id=$(curl -s -X GET "${cfapi}" \
|
||||||
|
-H @${cfg.apiKeyFile} -H "Content-Type: application/json" \
|
||||||
|
| jq -r '.result[] | select(.notes == "${notes}" and .configuration.target == "ip" and .configuration.value == "<ip>") | .id')
|
||||||
|
if [ -z "$id" ]; then echo "id for <ip> cannot be found"; exit 0; fi; \
|
||||||
|
curl -s -X DELETE "${cfapi}/$id" \
|
||||||
|
-H @${cfg.apiKeyFile} -H "Content-Type: application/json" \
|
||||||
|
--data '{"cascade": "none"}'
|
||||||
|
actionban = curl -X POST "${cfapi}" -H @${cfg.apiKeyFile} -H "Content-Type: application/json" --data '{"mode":"block","configuration":{"target":"ip","value":"<ip>"},"notes":"${notes}"}'
|
||||||
|
[Init]
|
||||||
|
name = cloudflare-token-agenix
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -37,7 +37,16 @@ in {
|
|||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
services.vaultwarden = {
|
services = {
|
||||||
|
cfFail2ban = lib.mkIf config.server.cfFail2ban.enable {
|
||||||
|
jails = {
|
||||||
|
vaultwarden = {
|
||||||
|
serviceName = "vaultwarden";
|
||||||
|
failRegex = "^.*Username or password is incorrect. Try again. IP: <HOST>. Username: <F-USER>.*</F-USER>.$";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
vaultwarden = {
|
||||||
enable = true;
|
enable = true;
|
||||||
# environmentFile = config.age.secrets.vaultwarden-env.path;
|
# environmentFile = config.age.secrets.vaultwarden-env.path;
|
||||||
|
|
||||||
@@ -58,4 +67,5 @@ in {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
11
secrets/cloudflareFirewallApiKey.age
Normal file
11
secrets/cloudflareFirewallApiKey.age
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
age-encryption.org/v1
|
||||||
|
-> ssh-ed25519 t9iOEg +WyTc7ny6fCCkqYl/y6IpkxOvXqqKEKCgQaFym1ZLSE
|
||||||
|
fWBQRK/iIuPCJ4ktL0Sq9gJR8oI/vczLkDMbZr8IvNI
|
||||||
|
-> ssh-ed25519 KUYMFA BkGncK6jhjVqFPaVAzE9e2d2IXdCdatmDL6qdsD/giQ
|
||||||
|
l06NmVxHODsCOu1vWRoUpZGypsJYjSLOb1tT/lpbAi8
|
||||||
|
-> ssh-ed25519 76RhUQ i3fS2lTIKCclVln0sygcwf1CRW1uDtytLwxgvpL37Co
|
||||||
|
FwSf7i06olqD+XyvAkc6VHHEih70Gks31XYVow5teZU
|
||||||
|
-> ssh-ed25519 Jf8sqw rNEYb8GjN1xn7LSzkx9B570trzum1oT+gB+qNxPA0l4
|
||||||
|
DgX9IPNRImBz9JjSNopiCVyXWAnyFNa88fvw3LMJxBE
|
||||||
|
--- CcmMHcWD0iWgn705hfOLdqo2xpJWIdJ7y+xEHicME6g
|
||||||
|
<EFBFBD><EFBFBD><<3C>v<7F><76><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0EG<45><47><1C>4<EFBFBD><34><EFBFBD><EFBFBD>ҥ<>%̥<>e<EFBFBD><65>ji<12><><EFBFBD><06><1E>]4yP<79><50>Ӥ,<2C>z<EFBFBD><7A>`#<13><><EFBFBD>l
|
||||||
@@ -12,4 +12,5 @@ in {
|
|||||||
"gcapi.age".publicKeys = [cnst kima];
|
"gcapi.age".publicKeys = [cnst kima];
|
||||||
"cloudflare-env.age".publicKeys = [cnst kima usobotka rsobotka];
|
"cloudflare-env.age".publicKeys = [cnst kima usobotka rsobotka];
|
||||||
"vaultwarden-env.age".publicKeys = [cnst kima usobotka rsobotka];
|
"vaultwarden-env.age".publicKeys = [cnst kima usobotka rsobotka];
|
||||||
|
"cloudflareFirewallApiKey.age".publicKeys = [cnst kima usobotka rsobotka];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user