summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-07-20 22:35:52 -0600
committerAlejandro Soto <alejandro@34project.org>2024-07-21 00:19:10 -0600
commitb1f3d839adc88b024e3a79d09b54a1939b78edba (patch)
tree2287680392dd32e6bda4c7e2664dc607727d79c7
parentc88f8c51c90c1e48c75047849a42ae0ed6c4aa15 (diff)
net/fail2ban: initial commit
Diffstat (limited to '')
-rw-r--r--sys/auth/openssh.nix2
-rw-r--r--sys/gitea/default.nix23
-rw-r--r--sys/home-assistant/default.nix62
-rw-r--r--sys/mail/default.nix357
-rw-r--r--sys/mta/default.nix254
-rw-r--r--sys/net/default.nix51
-rw-r--r--sys/net/fail2ban.nix31
-rw-r--r--sys/net/interfaces.nix49
-rw-r--r--sys/preset/dmz.nix2
-rw-r--r--sys/web/nginx.nix39
10 files changed, 488 insertions, 382 deletions
diff --git a/sys/auth/openssh.nix b/sys/auth/openssh.nix
index 2030682..0c23c81 100644
--- a/sys/auth/openssh.nix
+++ b/sys/auth/openssh.nix
@@ -35,7 +35,7 @@ in
enable = true;
openFirewall = true;
ports = [ 2234 ];
- startWhenNeeded = true;
+ startWhenNeeded = !config.services.fail2ban.enable;
hostKeys = map
(name: {
diff --git a/sys/gitea/default.nix b/sys/gitea/default.nix
index 6096950..69dfbc2 100644
--- a/sys/gitea/default.nix
+++ b/sys/gitea/default.nix
@@ -8,9 +8,26 @@ in
};
config = mkIf cfg.enable {
- services.gitea = {
- enable = true;
- useWizard = true;
+ environment.etc."fail2ban/filter.d/gitea.local".text = ''
+ [Definition]
+ failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
+ ignoreregex =
+ '';
+
+ services = {
+ fail2ban.jails.gitea.settings = {
+ filter = "gitea";
+ logpath = "${config.services.gitea.stateDir}/log/gitea.log";
+ maxretry = "10";
+ findtime = "3600";
+ bantime = "900";
+ action = "iptables-allports";
+ };
+
+ gitea = {
+ enable = true;
+ useWizard = true;
+ };
};
users = {
diff --git a/sys/home-assistant/default.nix b/sys/home-assistant/default.nix
index 8031d43..631ba27 100644
--- a/sys/home-assistant/default.nix
+++ b/sys/home-assistant/default.nix
@@ -8,35 +8,51 @@ in
};
config = mkIf cfg.enable {
+ # https://nathan.gs/2024/06/22/fail2ban-to-secure-ha-on-nixos/
+ environment.etc."fail2ban/filter.d/home-assistant.local".text = ''
+ [Definition]
+ failregex = ^.* \[homeassistant\.components\.http\.ban\] Login attempt or request with invalid authentication from <HOST>.*$
+
+ ignoreregex =
+
+ journalmatch = _SYSTEMD_UNIT=home-assistant.service + _COMM=home-assistant
+
+ datepattern = {^LN-BEG}
+ '';
+
local.boot.impermanence.directories = [
{ directory = "/var/lib/hass"; user = "hass"; group = "hass"; mode = "u=rwx,g=,o="; }
];
- services.home-assistant = {
- enable = true;
-
- extraComponents = [
- "met"
- "google_translate"
- "radio_browser"
- "tuya"
- "xiaomi_miio"
- ];
-
- config = {
- # Includes dependencies for a basic setup
- # https://www.home-assistant.io/integrations/default_config/
- default_config = { };
- };
+ services = {
+ fail2ban.jails.home-assistant = { };
+
+ home-assistant = {
+ enable = true;
- customComponents = with pkgs.home-assistant-custom-components; [
- dreame_vacuum
- xiaomi_miot
- ];
+ extraComponents = [
+ "met"
+ "google_translate"
+ "radio_browser"
+ "tuya"
+ "xiaomi_miio"
+ ];
- customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
- xiaomi-vacuum-map-card
- ];
+ config = {
+ # Includes dependencies for a basic setup
+ # https://www.home-assistant.io/integrations/default_config/
+ default_config = { };
+ };
+
+ customComponents = with pkgs.home-assistant-custom-components; [
+ dreame_vacuum
+ xiaomi_miot
+ ];
+
+ customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
+ xiaomi-vacuum-map-card
+ ];
+ };
};
};
}
diff --git a/sys/mail/default.nix b/sys/mail/default.nix
index 6d066eb..0a888e8 100644
--- a/sys/mail/default.nix
+++ b/sys/mail/default.nix
@@ -23,190 +23,197 @@ in
};
config = mkIf cfg.enable {
- services.dovecot2 =
- let
- cert = config.security.acme.certs.${imapHostname}.directory;
- in
- {
- enable = true;
- enablePAM = false;
- enableLmtp = true;
-
- sslServerKey = "${cert}/key.pem";
- sslServerCert = "${cert}/fullchain.pem";
-
- modules = [ pkgs.dovecot_pigeonhole ];
-
- mailUser = "vmail";
- mailGroup = "vmail";
- mailLocation = "maildir:~/mail";
- mailPlugins.perProtocol.lmtp.enable = [ "sieve" ];
-
- extraConfig =
- let
- inherit (config.networking) domain;
-
- # https://dovecot.org/list/dovecot/2019-March/115250.html
- # Otra solución posible (https://serverfault.com/a/1062274/980378):
- # auth_username_format = %{if;%d;eq;${domain};%Ln;%Lu}
- localEntry = canonical: username: ''
- ${username}:::::::user=${canonical} nopassword userdb_user=${canonical}
- '';
-
- localMailboxes =
- pkgs.writeText "local-mailboxes"
- (concatStrings
- (flatten (mapAttrsToList
- (canonical: user:
- map (localEntry canonical) ([ canonical ] ++ user.hardAliases))
- users)));
-
- localCerts =
- flatten (mapAttrsToList
- (canonical: user:
- let
- certNames = {
- inherit canonical;
- logins = [ canonical ] ++ user.hardAliases;
- };
- in
- map (flip nameValuePair certNames) user.mail.certs)
- users);
-
- vmailCerts =
- flatten (flatten (mapAttrsToList
- (domain: virtual: mapAttrsToList
- (username: user:
+ services = {
+ dovecot2 =
+ let
+ cert = config.security.acme.certs.${imapHostname}.directory;
+ in
+ {
+ enable = true;
+ enablePAM = false;
+ enableLmtp = true;
+
+ sslServerKey = "${cert}/key.pem";
+ sslServerCert = "${cert}/fullchain.pem";
+
+ modules = [ pkgs.dovecot_pigeonhole ];
+
+ mailUser = "vmail";
+ mailGroup = "vmail";
+ mailLocation = "maildir:~/mail";
+ mailPlugins.perProtocol.lmtp.enable = [ "sieve" ];
+
+ extraConfig =
+ let
+ inherit (config.networking) domain;
+
+ # https://dovecot.org/list/dovecot/2019-March/115250.html
+ # Otra solución posible (https://serverfault.com/a/1062274/980378):
+ # auth_username_format = %{if;%d;eq;${domain};%Ln;%Lu}
+ localEntry = canonical: username: ''
+ ${username}:::::::user=${canonical} nopassword userdb_user=${canonical}
+ '';
+
+ localMailboxes =
+ pkgs.writeText "local-mailboxes"
+ (concatStrings
+ (flatten (mapAttrsToList
+ (canonical: user:
+ map (localEntry canonical) ([ canonical ] ++ user.hardAliases))
+ users)));
+
+ localCerts =
+ flatten (mapAttrsToList
+ (canonical: user:
let
- address = "${username}@${domain}";
-
certNames = {
- canonical = address;
- logins = [ address ];
+ inherit canonical;
+ logins = [ canonical ] ++ user.hardAliases;
};
in
map (flip nameValuePair certNames) user.mail.certs)
- virtual.users)
- virtual));
-
- certLogins =
- pkgs.writeText "cert-logins"
- (concatStrings (flatten (mapAttrsToList
- (uuid: names: map
- (addr: ''
- ${uuid}.mail-client@nodomain,${addr}:::::::user=${names.canonical}
- '')
- names.logins)
- (listToAttrs (localCerts ++ vmailCerts)))));
-
- vmailPath = "/var/lib/vmail/%{if;%d;ne;;%Ld;${domain}}";
- in
- ''
- auth_mechanisms = plain login external
-
- ssl_ca = <${config.local.pki.ca.mail.fullchain}
- ssl_require_crl = yes
- ssl_verify_client_cert = yes
-
- # Esto descarta @domain.tld de locales explícitos, pero lo exige para los demás.
- # Implicación: locales implícitos sin dominio fallan en autenticar
- auth_username_format = %{if;%Ld;eq;${domain};%Ln;%{if;%d;ne;;%Lu;%Ln@nodomain}}
- auth_ssl_username_from_cert = yes
-
- # TODO: los defaults de nixpkgs dejan los sockets bajo
- # /run/dovecot2 con demasiados permisos rwx, arreglar
-
- service auth {
- inet_listener mta-sasl {
- port = ${toString cfg.saslPort}
- address = ${cfg.mdaListen}
+ users);
+
+ vmailCerts =
+ flatten (flatten (mapAttrsToList
+ (domain: virtual: mapAttrsToList
+ (username: user:
+ let
+ address = "${username}@${domain}";
+
+ certNames = {
+ canonical = address;
+ logins = [ address ];
+ };
+ in
+ map (flip nameValuePair certNames) user.mail.certs)
+ virtual.users)
+ virtual));
+
+ certLogins =
+ pkgs.writeText "cert-logins"
+ (concatStrings (flatten (mapAttrsToList
+ (uuid: names: map
+ (addr: ''
+ ${uuid}.mail-client@nodomain,${addr}:::::::user=${names.canonical}
+ '')
+ names.logins)
+ (listToAttrs (localCerts ++ vmailCerts)))));
+
+ vmailPath = "/var/lib/vmail/%{if;%d;ne;;%Ld;${domain}}";
+ in
+ ''
+ auth_mechanisms = plain login external
+
+ ssl_ca = <${config.local.pki.ca.mail.fullchain}
+ ssl_require_crl = yes
+ ssl_verify_client_cert = yes
+
+ # Esto descarta @domain.tld de locales explícitos, pero lo exige para los demás.
+ # Implicación: locales implícitos sin dominio fallan en autenticar
+ auth_username_format = %{if;%Ld;eq;${domain};%Ln;%{if;%d;ne;;%Lu;%Ln@nodomain}}
+ auth_ssl_username_from_cert = yes
+
+ # TODO: los defaults de nixpkgs dejan los sockets bajo
+ # /run/dovecot2 con demasiados permisos rwx, arreglar
+
+ service auth {
+ inet_listener mta-sasl {
+ port = ${toString cfg.saslPort}
+ address = ${cfg.mdaListen}
+ }
+ }
+
+ service lmtp {
+ inet_listener mta-lmtp {
+ port = ${toString cfg.lmtpPort}
+ address = ${cfg.mdaListen}
+ }
+ }
+
+ # FIXME: Esta cadena de passdbs hace que 'doveadm user lookup'
+ # falle para usuarios locales, pero todo lo demás sirve. Parece
+ # ser debido a que pam no puede enumerar.
+
+ passdb {
+ driver = static
+ args = nopassword
+
+ master = yes
+ mechanisms = external
+
+ result_success = continue-fail
+ result_failure = return-fail
+ result_internalfail = return-fail
+ }
+
+ passdb {
+ driver = passwd-file
+ args = scheme=PLAIN username_format=%{master_user},%Lu ${certLogins}
+
+ mechanisms = external
+ override_fields = nopassword
+
+ result_failure = return-fail
+ result_internalfail = return-fail
+ }
+
+ passdb {
+ driver = passwd-file
+ args = username_format=%Ln ${vmailPath}/passwd
+ }
+
+ passdb {
+ driver = passwd-file
+ args = scheme=PLAIN ${localMailboxes}
+
+ # Esta es una forma de determinar si se encontró el usuario en
+ # el passwd-file por medio de nopassword sin realmente
+ # autenticarlo. Cuidado con result_success, porque si eso se
+ # configura mal se permite inicio de sesión con cualquier
+ # contraseña (!!!).
+ result_success = continue
+ result_failure = return-fail
+ result_internalfail = return-fail
+
+ username_filter = !*@*
+ }
+
+ passdb {
+ driver = pam
+ args = dovecot2
+ username_filter = !*@*
+ #TODO: algo como 'override_fields = allow_nets=...'
}
- }
- service lmtp {
- inet_listener mta-lmtp {
- port = ${toString cfg.lmtpPort}
- address = ${cfg.mdaListen}
+ userdb {
+ driver = passwd-file
+ args = username_format=%Ln ${vmailPath}/passwd
+ override_fields = uid=vmail gid=vmail home=${vmailPath}/home/%Ln
}
- }
-
- # FIXME: Esta cadena de passdbs hace que 'doveadm user lookup'
- # falle para usuarios locales, pero todo lo demás sirve. Parece
- # ser debido a que pam no puede enumerar.
-
- passdb {
- driver = static
- args = nopassword
-
- master = yes
- mechanisms = external
-
- result_success = continue-fail
- result_failure = return-fail
- result_internalfail = return-fail
- }
-
- passdb {
- driver = passwd-file
- args = scheme=PLAIN username_format=%{master_user},%Lu ${certLogins}
-
- mechanisms = external
- override_fields = nopassword
-
- result_failure = return-fail
- result_internalfail = return-fail
- }
-
- passdb {
- driver = passwd-file
- args = username_format=%Ln ${vmailPath}/passwd
- }
-
- passdb {
- driver = passwd-file
- args = scheme=PLAIN ${localMailboxes}
-
- # Esta es una forma de determinar si se encontró el usuario en
- # el passwd-file por medio de nopassword sin realmente
- # autenticarlo. Cuidado con result_success, porque si eso se
- # configura mal se permite inicio de sesión con cualquier
- # contraseña (!!!).
- result_success = continue
- result_failure = return-fail
- result_internalfail = return-fail
-
- username_filter = !*@*
- }
-
- passdb {
- driver = pam
- args = dovecot2
- username_filter = !*@*
- #TODO: algo como 'override_fields = allow_nets=...'
- }
-
- userdb {
- driver = passwd-file
- args = username_format=%Ln ${vmailPath}/passwd
- override_fields = uid=vmail gid=vmail home=${vmailPath}/home/%Ln
- }
-
- userdb {
- driver = passwd-file
- args = ${localMailboxes}
-
- result_success = continue-ok
- result_internalfail = return-fail
- skip = found
- }
-
- userdb {
- driver = passwd
- args = blocking=no
- skip = notfound
- }
- '';
+
+ userdb {
+ driver = passwd-file
+ args = ${localMailboxes}
+
+ result_success = continue-ok
+ result_internalfail = return-fail
+ skip = found
+ }
+
+ userdb {
+ driver = passwd
+ args = blocking=no
+ skip = notfound
+ }
+ '';
+ };
+
+ fail2ban.jails.dovecot.settings = {
+ filter = "dovecot[mode=aggressive]";
+ maxretry = 3;
};
+ };
security = {
# Necesario debido a 'enablePAM = false'
diff --git a/sys/mta/default.nix b/sys/mta/default.nix
index 4d0ec91..8c261e7 100644
--- a/sys/mta/default.nix
+++ b/sys/mta/default.nix
@@ -23,137 +23,143 @@ in
};
config = mkIf cfg.enable {
- services.postfix =
- let
- cert = config.security.acme.certs.${domains.smtp.main}.directory;
- virtualDomains = filterAttrs (name: _: name != domain) virtual;
- in
- {
- enable = true;
- enableSmtp = true;
- enableSubmission = true;
- enableSubmissions = true;
-
- inherit domain;
- hostname = domains.smtp.main;
- #TODO: check_recipient_access para rechazar localhost desde afuera
- destination = [ "localhost" "$mydomain" ];
- origin = "$mydomain";
+ services = {
+ fail2ban.jails.postfix.settings = {
+ filter = "postfix[mode=aggressive]";
+ };
- networksStyle = "host";
+ opendkim = {
+ enable = true;
- sslKey = "${cert}/key.pem";
- sslCert = "${cert}/fullchain.pem";
+ group = "postfix";
+ domains = "csl:${domain}";
+ selector = "202402";
- # También es postmaster
- rootAlias = config.local.sysadmin;
+ configFile = pkgs.writeText "opendkim.conf" ''
+ UMask 007
+ '';
+ };
- extraAliases = concatStrings
- (flatten (mapAttrsToList
- (name: user: map
- (alias: ''
- ${alias}: ${name}
+ postfix =
+ let
+ cert = config.security.acme.certs.${domains.smtp.main}.directory;
+ virtualDomains = filterAttrs (name: _: name != domain) virtual;
+ in
+ {
+ enable = true;
+ enableSmtp = true;
+ enableSubmission = true;
+ enableSubmissions = true;
+
+ inherit domain;
+ hostname = domains.smtp.main;
+ #TODO: check_recipient_access para rechazar localhost desde afuera
+ destination = [ "localhost" "$mydomain" ];
+ origin = "$mydomain";
+
+ networksStyle = "host";
+
+ sslKey = "${cert}/key.pem";
+ sslCert = "${cert}/fullchain.pem";
+
+ # También es postmaster
+ rootAlias = config.local.sysadmin;
+
+ extraAliases = concatStrings
+ (flatten (mapAttrsToList
+ (name: user: map
+ (alias: ''
+ ${alias}: ${name}
+ '')
+ user.hardAliases)
+ users));
+
+ localRecipients = map
+ (user: "${user}@${domain}")
+ (attrNames (users // virtual.${domain}.users));
+
+ virtual = concatStrings (flatten (mapAttrsToList
+ (name: virtual: mapAttrsToList
+ (alias: targets: ''
+ ${alias}@${name} ${concatStringsSep ", " targets}
'')
- user.hardAliases)
- users));
-
- localRecipients = map
- (user: "${user}@${domain}")
- (attrNames (users // virtual.${domain}.users));
-
- virtual = concatStrings (flatten (mapAttrsToList
- (name: virtual: mapAttrsToList
- (alias: targets: ''
- ${alias}@${name} ${concatStringsSep ", " targets}
- '')
- virtual.aliases)
- virtual));
-
- mapFiles = {
- sender_login =
- pkgs.writeText "postfix-sender_login"
- (concatStrings (flatten (mapAttrsToList
- (username: user: map
- (alias: ''
- ${alias}@${domain} ${username}
- '')
- ([ username ] ++ user.hardAliases))
- users)));
-
- virtual_recipients =
- pkgs.writeText "postfix-virtual-recipients"
- (concatStrings (flatten (mapAttrsToList
- (virtualDomain: virtual: mapAttrsToList
- # El lado derecho de esta tabla debe existir pero nunca se usa
- (username: _: ''
- ${username}@${virtualDomain} foo
- '')
- virtual.users)
- virtualDomains)));
-
- virtual_rules =
- pkgs.writeText "postfix-virtual-rules"
- (concatStrings (flatten (mapAttrsToList
- (name: virtual: map
- (rule: ''
- /^${rule.pattern}@${name}$/ ${concatStringsSep ", " rule.targets}
- '')
- virtual.rules)
- virtual)));
- };
-
- config =
- let
- mdaTransport = "lmtp:inet:${cfg.mdaAddr}:${toString cfg.lmtpPort}";
- in
- {
- message_size_limit = toString (50 * 1048576);
-
- virtual_alias_maps = mkAfter [ "pcre:/etc/postfix/virtual_rules" ];
- virtual_mailbox_domains = attrNames virtualDomains;
- virtual_mailbox_maps = [ "hash:/etc/postfix/virtual_recipients" ];
-
- local_transport = mdaTransport;
- virtual_transport = mdaTransport;
-
- smtpd_sasl_auth_enable = true;
- smtpd_sasl_type = "dovecot";
- smtpd_sasl_path = "inet:${cfg.mdaAddr}:${toString cfg.saslPort}";
- smtpd_sasl_tls_security_options = [ "noanonymous" ];
-
- smtpd_tls_auth_only = true;
- smtpd_tls_dh1024_param_file = config.security.dhparams.params.postfix.path;
-
- smtpd_relay_restrictions = [
- "permit_mynetworks"
- "permit_sasl_authenticated"
- "reject_unauth_destination"
- ];
-
- smtpd_sender_login_maps = [ "hash:/etc/postfix/sender_login" ];
-
- smtpd_sender_restrictions = [
- "permit_mynetworks"
- "reject_sender_login_mismatch"
- "permit_sasl_authenticated"
- ];
-
- smtpd_milters = "unix:/run/opendkim/opendkim.sock";
- non_smtpd_milters = "$smtpd_milters";
- milter_default_action = "accept";
+ virtual.aliases)
+ virtual));
+
+ mapFiles = {
+ sender_login =
+ pkgs.writeText "postfix-sender_login"
+ (concatStrings (flatten (mapAttrsToList
+ (username: user: map
+ (alias: ''
+ ${alias}@${domain} ${username}
+ '')
+ ([ username ] ++ user.hardAliases))
+ users)));
+
+ virtual_recipients =
+ pkgs.writeText "postfix-virtual-recipients"
+ (concatStrings (flatten (mapAttrsToList
+ (virtualDomain: virtual: mapAttrsToList
+ # El lado derecho de esta tabla debe existir pero nunca se usa
+ (username: _: ''
+ ${username}@${virtualDomain} foo
+ '')
+ virtual.users)
+ virtualDomains)));
+
+ virtual_rules =
+ pkgs.writeText "postfix-virtual-rules"
+ (concatStrings (flatten (mapAttrsToList
+ (name: virtual: map
+ (rule: ''
+ /^${rule.pattern}@${name}$/ ${concatStringsSep ", " rule.targets}
+ '')
+ virtual.rules)
+ virtual)));
};
- };
-
- services.opendkim = {
- enable = true;
- group = "postfix";
- domains = "csl:${domain}";
- selector = "202402";
-
- configFile = pkgs.writeText "opendkim.conf" ''
- UMask 007
- '';
+ config =
+ let
+ mdaTransport = "lmtp:inet:${cfg.mdaAddr}:${toString cfg.lmtpPort}";
+ in
+ {
+ message_size_limit = toString (50 * 1048576);
+
+ virtual_alias_maps = mkAfter [ "pcre:/etc/postfix/virtual_rules" ];
+ virtual_mailbox_domains = attrNames virtualDomains;
+ virtual_mailbox_maps = [ "hash:/etc/postfix/virtual_recipients" ];
+
+ local_transport = mdaTransport;
+ virtual_transport = mdaTransport;
+
+ smtpd_sasl_auth_enable = true;
+ smtpd_sasl_type = "dovecot";
+ smtpd_sasl_path = "inet:${cfg.mdaAddr}:${toString cfg.saslPort}";
+ smtpd_sasl_tls_security_options = [ "noanonymous" ];
+
+ smtpd_tls_auth_only = true;
+ smtpd_tls_dh1024_param_file = config.security.dhparams.params.postfix.path;
+
+ smtpd_relay_restrictions = [
+ "permit_mynetworks"
+ "permit_sasl_authenticated"
+ "reject_unauth_destination"
+ ];
+
+ smtpd_sender_login_maps = [ "hash:/etc/postfix/sender_login" ];
+
+ smtpd_sender_restrictions = [
+ "permit_mynetworks"
+ "reject_sender_login_mismatch"
+ "permit_sasl_authenticated"
+ ];
+
+ smtpd_milters = "unix:/run/opendkim/opendkim.sock";
+ non_smtpd_milters = "$smtpd_milters";
+ milter_default_action = "accept";
+ };
+ };
};
security.dhparams.params.postfix = { };
diff --git a/sys/net/default.nix b/sys/net/default.nix
index 0341440..608806d 100644
--- a/sys/net/default.nix
+++ b/sys/net/default.nix
@@ -1,49 +1,6 @@
-{ lib, config, pkgs, ... }:
-with lib; let
- cfg = config.local.net;
-in
{
- options.local.net = with lib.types; {
- enable = mkEnableOption "networking stack";
-
- hostname = mkOption {
- type = str;
- };
-
- dhcpInterface = mkOption {
- type = nullOr str;
- default = null;
- };
- };
-
- config = mkIf cfg.enable {
- environment.systemPackages = [ pkgs.dhcpcd ];
-
- networking = {
- domain = mkDefault config.local.domains.host.main;
- hostName = cfg.hostname;
-
- useDHCP = false;
- enableIPv6 = true;
- useNetworkd = true;
- useHostResolvConf = false;
-
- wireguard.enable = true;
- };
-
- systemd.network.networks = mkIf (cfg.dhcpInterface != null) {
- "40-${cfg.dhcpInterface}" = {
- matchConfig.Name = cfg.dhcpInterface;
-
- networkConfig = {
- DHCP = "ipv4";
- IPv6AcceptRA = true;
- IPv6PrivacyExtensions = "kernel";
- };
-
- # make routing on this interface a dependency for network-online.target
- linkConfig.RequiredForOnline = "routable";
- };
- };
- };
+ imports = [
+ ./fail2ban.nix
+ ./interfaces.nix
+ ];
}
diff --git a/sys/net/fail2ban.nix b/sys/net/fail2ban.nix
new file mode 100644
index 0000000..6dbacd1
--- /dev/null
+++ b/sys/net/fail2ban.nix
@@ -0,0 +1,31 @@
+{ lib, config, pkgs, ... }:
+with lib; let
+ cfg = config.local.net.fail2ban;
+in
+{
+ options.local.net.fail2ban = {
+ enable = mkEnableOption "fal2ban";
+ };
+
+ config = mkIf cfg.enable {
+ services.fail2ban = {
+ enable = true;
+
+ bantime = "10m";
+
+ bantime-increment = {
+ enable = true;
+
+ maxtime = "48h";
+ rndtime = "10m";
+ overalljails = true;
+ };
+
+ #TODO: No quemar
+ ignoreIP = [
+ "10.34.0.0/16"
+ "167.114.128.142"
+ ];
+ };
+ };
+}
diff --git a/sys/net/interfaces.nix b/sys/net/interfaces.nix
new file mode 100644
index 0000000..0341440
--- /dev/null
+++ b/sys/net/interfaces.nix
@@ -0,0 +1,49 @@
+{ lib, config, pkgs, ... }:
+with lib; let
+ cfg = config.local.net;
+in
+{
+ options.local.net = with lib.types; {
+ enable = mkEnableOption "networking stack";
+
+ hostname = mkOption {
+ type = str;
+ };
+
+ dhcpInterface = mkOption {
+ type = nullOr str;
+ default = null;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = [ pkgs.dhcpcd ];
+
+ networking = {
+ domain = mkDefault config.local.domains.host.main;
+ hostName = cfg.hostname;
+
+ useDHCP = false;
+ enableIPv6 = true;
+ useNetworkd = true;
+ useHostResolvConf = false;
+
+ wireguard.enable = true;
+ };
+
+ systemd.network.networks = mkIf (cfg.dhcpInterface != null) {
+ "40-${cfg.dhcpInterface}" = {
+ matchConfig.Name = cfg.dhcpInterface;
+
+ networkConfig = {
+ DHCP = "ipv4";
+ IPv6AcceptRA = true;
+ IPv6PrivacyExtensions = "kernel";
+ };
+
+ # make routing on this interface a dependency for network-online.target
+ linkConfig.RequiredForOnline = "routable";
+ };
+ };
+ };
+}
diff --git a/sys/preset/dmz.nix b/sys/preset/dmz.nix
index c6e290e..19985e0 100644
--- a/sys/preset/dmz.nix
+++ b/sys/preset/dmz.nix
@@ -34,6 +34,8 @@ in
net = {
enable = true;
hostname = "dmz";
+
+ fail2ban.enable = true;
};
web.sites.portal.enable = true;
diff --git a/sys/web/nginx.nix b/sys/web/nginx.nix
index a971eb2..303ab4e 100644
--- a/sys/web/nginx.nix
+++ b/sys/web/nginx.nix
@@ -14,19 +14,40 @@ in
};
config = mkIf cfg.enable {
- services.nginx = {
- enable = true;
+ services = {
+ fail2ban.jails = {
+ # https://discourse.nixos.org/t/fail2ban-with-nginx-and-authelia/31419
+ nginx-botsearch.settings = {
+ # Usar log en vez de journalctl
+ # TODO: Pasar todo a systemd?
+ backend = "pyinotify";
+ logpath = "/var/log/nginx/*.log";
+ journalmatch = "";
+ };
- recommendedGzipSettings = true;
- recommendedOptimisation = true;
- recommendedProxySettings = true;
- recommendedTlsSettings = true;
+ nginx-bad-request.settings = {
+ backend = "pyinotify";
+ logpath = "/var/log/nginx/*.log";
+ journalmatch = "";
- sslDhparam = config.security.dhparams.params.nginx.path;
+ maxretry = 10;
+ };
+ };
- clientMaxBodySize = "42M";
+ nginx = {
+ enable = true;
- virtualHosts = { };
+ recommendedGzipSettings = true;
+ recommendedOptimisation = true;
+ recommendedProxySettings = true;
+ recommendedTlsSettings = true;
+
+ sslDhparam = config.security.dhparams.params.nginx.path;
+
+ clientMaxBodySize = "42M";
+
+ virtualHosts = { };
+ };
};
local.certs = listToAttrs (map