Fail2ban: Difference between revisions

From NixOS Wiki
imported>Occhioverde
Added instructions on how to create new actions and filters; added "See also" section
imported>Writer
Reduce redudant desciptions and add new information.
Line 4: Line 4:
The Fail2ban [[NixOS modules|NixOS module]] can be found under <source lang="nix" enclose="none">services.fail2ban</source>; from now on (unless differently specified), all options described are prefixed with this namespace.
The Fail2ban [[NixOS modules|NixOS module]] can be found under <source lang="nix" enclose="none">services.fail2ban</source>; from now on (unless differently specified), all options described are prefixed with this namespace.


The service can be enabled by setting <source lang="nix" enclose="none">enable</source> to <source lang="nix" enclose="none">true</source>:
The service can be enabled with the expression:
<syntaxHighlight lang=nix>
<syntaxHighlight lang=nix>
   services.fail2ban.enable = true; # Enables Fail2ban
   services.fail2ban.enable = true;
</syntaxHighlight>
</syntaxHighlight>
This will also enable a jail for sshd, which comes with NixOS.


=== Configuration ===
=== Configuration ===
The Fail2ban NixOS module exposes different parameters needed to adjust the configuration:
 
The Fail2ban NixOS module exposes different parameters for adjusting the configuration:


* The <source lang="nix" enclose="none">maxretry</source> option allows you to specify how many failures are required for an IP address to be blocked.
* The <source lang="nix" enclose="none">maxretry</source> option allows you to specify how many failures are required for an IP address to be blocked.
Line 54: Line 56:
   };
   };
</syntaxHighlight>
</syntaxHighlight>
These settings are written to <code>/etc/fail2ban/jail.local</code>, where fail2ban will use them.


== Extending Fail2ban ==
== Extending Fail2ban ==

Revision as of 22:08, 26 November 2023

Fail2ban is an intrusion prevention software. It scans through log files to find signs of malicious intent. In general, Fail2ban will update the firewall rules to reject the offending IP address for a set amount of time.

Basic Usage

The Fail2ban NixOS module can be found under services.fail2ban; from now on (unless differently specified), all options described are prefixed with this namespace.

The service can be enabled with the expression:

  services.fail2ban.enable = true;

This will also enable a jail for sshd, which comes with NixOS.

Configuration

The Fail2ban NixOS module exposes different parameters for adjusting the configuration:

  • The maxretry option allows you to specify how many failures are required for an IP address to be blocked.
  • To prevent being locked out accidentally, the 'ignoreIP' option can be used to prevent IP addresses and IP ranges from being blocked. In the example below, common LAN IP address ranges as well as the specific IP '8.8.8.8' and the address associated with the hostname "nixos.wiki" (note that the loopback addresses "127.0.0.0/8" and "::1" are added by default).
  • bantime specifies for how much time an IP address is blocked after reaching the maximum number of tries. Note that the bantime can be increased for every violation by setting bantime-increment.enable to true; the bantime increment can then be customized by specifying a formula (in Python) like ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor) with bantime-increment.formula, the multipliers with bantime-increment.multipliers, the maximum bantime with bantime-increment.maxtime and the indication to consider the bans issued throughout multiple jails with bantime-increment.overalljails
  • banaction specifies which one among the actions contained in /etc/fail2ban/action.d should be the default banning action (e.g., iptables, iptables-new, iptables-multiport, iptables-ipset-proto6-allports, shorewall, etc.)
  • extraPackages can receive a list of derivations whose outputs are needed by Fail2ban actions
  • jails contains the configuration of each Fail2ban “jail”. A jail consists of an action (such as blocking a port using iptables) that is triggered when a filter applied to a log file triggers more than a certain number of times in a certain time period. Actions are defined in /etc/fail2ban/action.d, while filters are defined in /etc/fail2ban/filter.d.
  • extraSettings can contain parameters that are automatically applied to every jail config (i.e., in the [DEFAULT] section)
  services.fail2ban = {
    enable = true;
    maxretry = 5; # Observe 5 violations before banning an IP
    ignoreIP = [
      # Whitelisting some subnets:
      "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16"
      "8.8.8.8" # Whitelists a specific IP
      "nixos.wiki" # Resolves the IP via DNS
    ];
    bantime = "24h"; # Set bantime to one day
    bantime-increment = {
      enable = true; # Enable increment of bantime after each violation
      formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)";
      multipliers = "1 2 4 8 16 32 64";
      maxtime = "168h"; # Do not ban for more than 1 week
      overalljails = true; # Calculate the bantime based on all the violations
    };
    jails = {
      apache-nohome-iptables = ''
        # Block an IP address if it accesses a non-existent
        # home directory more than 5 times in 10 minutes,
        # since that indicates that it's scanning.
        filter = apache-nohome
        action = iptables-multiport[name=HTTP, port="http,https"]
        logpath = /var/log/httpd/error_log*
        backend = auto
        findtime = 600
        bantime  = 600
        maxretry = 5
      '';
    };
  };

These settings are written to /etc/fail2ban/jail.local, where fail2ban will use them.

Extending Fail2ban

Fail2ban capabilities can be freely extended by adding new jails, filters, and actions; the first ones of them are already covered in the "Basic usage" section, while the other two need dedicated config files to be created in the /etc/fail2ban/filter.d and /etc/fail2ban/action.d folders.

In order to do this, you'll have to add a environment.etc section to your NixOS config file and specify there the contents of your custom actions and filters:

  environment.etc = {
    # Define an action that will trigger a Ntfy push notification upon the issue of every new ban
    "fail2ban/action.d/ntfy.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
      [Definition]
      norestored = true # Needed to avoid receiving a new notification after every restart
      actionban = curl -H "Title: <ip> has been banned" -d "<name> jail has banned <ip> from accessing $(hostname) after <failures> attempts of hacking the system." https://ntfy.sh/Fail2banNotifications
    '');
    # Defines a filter that detects URL probing by reading the Nginx access log
    "fail2ban/filter.d/nginx-url-probe.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
      [Definition]
      failregex = ^<HOST>.*(GET /(wp-|admin|boaform|phpmyadmin|\.env|\.git)|\.(dll|so|cfm|asp)|(\?|&)(=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000|=PHPE9568F36-D428-11d2-A769-00AA001ACF42|=PHPE9568F35-D428-11d2-A769-00AA001ACF42|=PHPE9568F34-D428-11d2-A769-00AA001ACF42)|\\x[0-9a-zA-Z]{2})
    '');
  };

The defined filters and actions can then be used in a new jail (created as seen above):

  services.fail2ban = {
    # --- snip ---
    jails = {
      ngnix-url-probe = ''
        enabled = true
        filter = nginx-url-probe
        logpath = /var/log/nginx/access.log
        action = %(action_)s[blocktype=DROP]
                 ntfy
        backend = auto # Do not forget to specify this if your jail uses a log file
        maxretry = 5
        findtime = 600
      '';
    };
  };

For more details on how to develop Fail2ban filters please see the official documentation.

See also