Initial role commit
This commit is contained in:
405
README.md
405
README.md
@@ -1,3 +1,404 @@
|
||||
# ansible-role-fail2ban
|
||||
# Ansible Role: fail2ban
|
||||
|
||||
An Ansible role for installing and configuring fail2ban.
|
||||
An Ansible role for installing and configuring fail2ban on Linux systems. This role provides flexible configuration options for fail2ban's main settings, jail configurations, and custom filters/actions.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Ansible 2.9 or higher
|
||||
- Target systems: Debian/Ubuntu or RHEL-based distributions
|
||||
- Python 3 on target hosts
|
||||
|
||||
## Role Variables
|
||||
|
||||
### Default Variables
|
||||
|
||||
Available variables are listed below, along with default values (see `defaults/main.yaml`):
|
||||
|
||||
```yaml
|
||||
# Packages to install
|
||||
fail2ban_dependencies:
|
||||
- fail2ban
|
||||
- python3-systemd
|
||||
|
||||
# Service configuration
|
||||
fail2ban_service: fail2ban
|
||||
fail2ban_loglevel: INFO
|
||||
fail2ban_logtarget: /var/log/fail2ban.log
|
||||
|
||||
# Default jail settings
|
||||
fail2ban_ignoreself: "true"
|
||||
fail2ban_ignoreips:
|
||||
- 127.0.0.1/8
|
||||
- ::1
|
||||
fail2ban_bantime: 10m
|
||||
fail2ban_findtime: 10m
|
||||
fail2ban_maxretry: 5
|
||||
fail2ban_backend: auto
|
||||
```
|
||||
|
||||
### Important Default Settings to Configure
|
||||
|
||||
Before deploying to production, consider adjusting these critical settings:
|
||||
|
||||
1. **IP Whitelist** (`fail2ban_ignoreips`): Add your management IPs to prevent lockouts
|
||||
2. **Ban Duration** (`fail2ban_bantime`): Default is 10 minutes; consider longer for production (1h, 24h, 1w)
|
||||
3. **Max Retry** (`fail2ban_maxretry`): Default is 5 attempts; lower for stricter security
|
||||
4. **Find Time Window** (`fail2ban_findtime`): Default is 10 minutes; adjust based on your threat model
|
||||
5. **Backend** (`fail2ban_backend`): Set to `systemd` for systemd-based distros for better performance
|
||||
|
||||
### Custom Configuration Variables
|
||||
|
||||
#### Using the INI Module Format
|
||||
|
||||
You can add custom configuration to `fail2ban.local` and `jail.local` by defining options in the INI module format:
|
||||
|
||||
```yaml
|
||||
# Additional fail2ban.local configuration
|
||||
fail2ban_configuration: []
|
||||
- option: loglevel # The INI option name
|
||||
value: "DEBUG" # The value to set
|
||||
section: Definition # The INI section
|
||||
|
||||
# Additional jail.local configuration
|
||||
fail2ban_jail_configuration:
|
||||
- option: destemail
|
||||
value: "admin@example.com"
|
||||
section: DEFAULT
|
||||
- option: sender
|
||||
value: "fail2ban@example.com"
|
||||
section: DEFAULT
|
||||
- option: action
|
||||
value: "%(action_mwl)s"
|
||||
section: DEFAULT
|
||||
```
|
||||
|
||||
**INI Format Explanation:**
|
||||
- `section`: The configuration section in the INI file (e.g., `DEFAULT`, `Definition`, `sshd`)
|
||||
- `option`: The configuration parameter name
|
||||
- `value`: The value to assign (must be a string, number, or boolean)
|
||||
|
||||
This format allows you to set any fail2ban configuration option without modifying the role itself.
|
||||
|
||||
### Debian-Specific Configuration
|
||||
|
||||
#### SSH Service Name Issue
|
||||
|
||||
On Debian systems, there's a common issue where fail2ban's default SSH jail doesn't work out of the box. The problem:
|
||||
|
||||
- fail2ban's default configuration expects the service to be named `sshd`
|
||||
- On many Debian systems, the actual systemd service is named `ssh.service` (not `sshd.service`)
|
||||
- When using the `systemd` backend, fail2ban looks for logs from the `sshd` service and finds nothing
|
||||
- Result: **SSH protection silently fails** - no errors, but no banning occurs
|
||||
|
||||
#### The Solution
|
||||
|
||||
This role provides the `fail2ban_default_debian_jail_configuration` variable to override Debian's default jail settings:
|
||||
```yaml
|
||||
fail2ban_default_debian_jail_configuration:
|
||||
- option: backend
|
||||
value: systemd
|
||||
section: sshd
|
||||
- option: journalmatch
|
||||
value: "_SYSTEMD_UNIT=ssh.service" # Use ssh.service instead of sshd.service
|
||||
section: sshd
|
||||
```
|
||||
|
||||
This configuration:
|
||||
- Explicitly sets the backend to `systemd` for better performance
|
||||
- Corrects the journal match to look for `ssh.service` instead of the default `sshd.service`
|
||||
- Is applied only on Debian systems (via `when: ansible_facts['distribution'] == 'Debian'`)
|
||||
|
||||
#### Usage Example
|
||||
```yaml
|
||||
- hosts: debian_servers
|
||||
become: yes
|
||||
roles:
|
||||
- role: fail2ban
|
||||
vars:
|
||||
fail2ban_backend: systemd
|
||||
|
||||
# Fix SSH jail on Debian
|
||||
fail2ban_default_debian_jail_configuration:
|
||||
- option: backend
|
||||
value: systemd
|
||||
section: sshd
|
||||
- option: journalmatch
|
||||
value: "_SYSTEMD_UNIT=ssh.service"
|
||||
section: sshd
|
||||
|
||||
fail2ban_jails:
|
||||
- name: sshd
|
||||
enabled: true
|
||||
maxretry: 3
|
||||
bantime: 1h
|
||||
```
|
||||
|
||||
> [!NOTE] This only affects the default SSH jail in `/etc/fail2ban/jail.d/defaults-debian.conf`. If you're defining custom SSH jails using `fail2ban_jails`, make sure to specify the correct `journalmatch` or `logpath` for your system.
|
||||
|
||||
#### Verifying SSH Protection is Working
|
||||
|
||||
After applying the role, verify fail2ban is monitoring SSH:
|
||||
```bash
|
||||
# Check if the sshd jail is active
|
||||
sudo fail2ban-client status sshd
|
||||
|
||||
# Check what logs fail2ban is monitoring
|
||||
sudo fail2ban-client get sshd logpath
|
||||
|
||||
# Test with a failed login and check
|
||||
sudo fail2ban-client status sshd
|
||||
```
|
||||
|
||||
If you see "Currently banned: 0" and "Total banned: 0" after several failed login attempts, the jail may not be configured correctly for your system's SSH service name.
|
||||
|
||||
### Creating Custom Jails
|
||||
|
||||
#### Method 1: Define Jails as Dictionaries (Recommended for Simple Jails)
|
||||
|
||||
Create custom jails by defining them as dictionaries. This method uses a Jinja2 template to generate jail files:
|
||||
|
||||
```yaml
|
||||
fail2ban_jails:
|
||||
- name: sshd # Jail name (required)
|
||||
enabled: true # Enable/disable jail
|
||||
port: ssh # Service port(s)
|
||||
logpath: /var/log/auth.log # Log file to monitor
|
||||
maxretry: 3 # Override default maxretry
|
||||
bantime: 1h # Override default bantime
|
||||
findtime: 10m # Override default findtime
|
||||
banaction: iptables-multiport # Ban action to use
|
||||
filter: sshd # Filter to use
|
||||
```
|
||||
|
||||
**Common jail parameters:**
|
||||
- `name`: Jail identifier (required)
|
||||
- `enabled`: true/false
|
||||
- `port`: Service port (ssh, http, https, etc.)
|
||||
- `filter`: Filter name (must exist in filter.d/)
|
||||
- `logpath`: Path to log file(s) to monitor
|
||||
- `maxretry`: Number of failures before ban
|
||||
- `findtime`: Time window for counting failures
|
||||
- `bantime`: Duration of ban
|
||||
- `banaction`: Action to execute on ban
|
||||
- `action`: Full action with parameters
|
||||
|
||||
#### Method 2: Copy Complete Jail Files (For Complex Configurations)
|
||||
|
||||
For more complex jail configurations that require specific options not supported by the template, copy complete jail files:
|
||||
|
||||
```yaml
|
||||
# Path to directory containing custom jail files
|
||||
fail2ban_jails_path: "{{ playbook_dir }}/files/fail2ban/jails"
|
||||
```
|
||||
|
||||
Place your `.conf` or `.local` files in the specified directory. They will be copied to `/etc/fail2ban/jail.d/`.
|
||||
|
||||
### Custom Filters and Actions
|
||||
|
||||
#### Copying Custom Filters
|
||||
|
||||
Define custom filters for application-specific log patterns:
|
||||
|
||||
```yaml
|
||||
# Path to directory containing custom filter files
|
||||
fail2ban_filters_path: "{{ playbook_dir }}/files/fail2ban/filters"
|
||||
```
|
||||
|
||||
Place your filter `.conf` files in the specified directory. They will be copied to `/etc/fail2ban/filter.d/`.
|
||||
|
||||
**Example custom filter** (`files/fail2ban/filters/myapp.conf`):
|
||||
```ini
|
||||
[Definition]
|
||||
failregex = ^<HOST> .* "POST /login HTTP/.*" 401
|
||||
^Authentication failure for .* from <HOST>
|
||||
ignoreregex =
|
||||
```
|
||||
|
||||
#### Copying Custom Actions
|
||||
|
||||
Define custom actions for specific ban/unban behaviors:
|
||||
|
||||
```yaml
|
||||
# Path to directory containing custom action files
|
||||
fail2ban_actions_path: "files/fail2ban/actions"
|
||||
```
|
||||
|
||||
Place your action `.conf` files in the specified directory. They will be copied to `/etc/fail2ban/action.d/`.
|
||||
|
||||
To see an example of a custom action, I've included a [ufw-docker action](files/actions/ufw-docker.conf) with the role as I use it frequently. It is an enhanced UFW action that provides additional protection for Docker environments. To use it, just set `fail2ban_actions_path` to `actions`.
|
||||
|
||||
> [!WARNING]
|
||||
> For this action to work properly, you'll need to configure UFW to work properly with Docker, either manually or using the [ufw-docker](https://github.com/chaifeng/ufw-docker) script.
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
|
||||
## Example Playbook
|
||||
|
||||
### Basic Usage with Recommended Defaults
|
||||
|
||||
```yaml
|
||||
- hosts: servers
|
||||
become: yes
|
||||
roles:
|
||||
- role: fail2ban
|
||||
vars:
|
||||
# Add your management IPs to prevent lockouts
|
||||
fail2ban_ignoreips:
|
||||
- 127.0.0.1/8
|
||||
- ::1
|
||||
- 10.0.0.0/8 # Your private network
|
||||
|
||||
|
||||
# Stricter default settings
|
||||
fail2ban_bantime: 1h
|
||||
fail2ban_maxretry: 3
|
||||
fail2ban_backend: systemd
|
||||
```
|
||||
|
||||
### Custom Configuration with INI Format
|
||||
|
||||
The role uses the `ini_file` module to edit the default configuration files. You may override or add to this configuration:
|
||||
|
||||
```yaml
|
||||
- hosts: servers
|
||||
become: yes
|
||||
roles:
|
||||
- role: fail2ban
|
||||
vars:
|
||||
# Override fail2ban.conf base settings using INI format
|
||||
fail2ban_configuration:
|
||||
- option: loglevel
|
||||
value: "NOTICE"
|
||||
section: Definition
|
||||
- option: logtarget
|
||||
value: "SYSLOG"
|
||||
section: Definition
|
||||
|
||||
# Configure jail.conf email notifications
|
||||
fail2ban_jail_configuration:
|
||||
- option: destemail
|
||||
value: "security@example.com"
|
||||
section: DEFAULT
|
||||
- option: sender
|
||||
value: "fail2ban@example.com"
|
||||
section: DEFAULT
|
||||
- option: action
|
||||
value: "%(action_mwl)s" # Mail with logs
|
||||
section: DEFAULT
|
||||
```
|
||||
|
||||
### Creating Custom Jails with Dictionaries
|
||||
|
||||
```yaml
|
||||
- hosts: servers
|
||||
become: yes
|
||||
roles:
|
||||
- role: fail2ban
|
||||
vars:
|
||||
fail2ban_bantime: 1h
|
||||
fail2ban_maxretry: 3
|
||||
|
||||
fail2ban_jails:
|
||||
# SSH protection
|
||||
- name: sshd
|
||||
enabled: true
|
||||
port: ssh
|
||||
logpath: /var/log/auth.log
|
||||
maxretry: 3
|
||||
bantime: 24h
|
||||
|
||||
# Nginx authentication failures
|
||||
- name: nginx-http-auth
|
||||
enabled: true
|
||||
port: http,https
|
||||
logpath: /var/log/nginx/error.log
|
||||
|
||||
# Recidive jail for repeat offenders
|
||||
- name: recidive
|
||||
enabled: true
|
||||
maxretry: 3
|
||||
findtime: 1w
|
||||
bantime: 30d
|
||||
logpath: /var/log/fail2ban.log
|
||||
```
|
||||
|
||||
### Using Complete Jail Files for Complex Configurations
|
||||
|
||||
```yaml
|
||||
- hosts: servers
|
||||
become: yes
|
||||
roles:
|
||||
- role: fail2ban
|
||||
vars:
|
||||
# Use dictionaries for simple jails
|
||||
fail2ban_jails:
|
||||
- name: sshd
|
||||
enabled: true
|
||||
maxretry: 3
|
||||
|
||||
# For complex jails, copy complete jail files
|
||||
fail2ban_jails_path: "{{ playbook_dir }}/files/fail2ban/jails"
|
||||
|
||||
```
|
||||
|
||||
## Role Tasks
|
||||
|
||||
This role performs the following tasks:
|
||||
|
||||
1. Installs fail2ban and required dependencies
|
||||
2. Configures `fail2ban.local` with base and custom settings
|
||||
3. Configures `jail.local` with default jail parameters
|
||||
4. Configures Debian-specific jail settings (when applicable)
|
||||
5. Copies custom filter configurations (if provided)
|
||||
6. Copies custom action configurations (if provided)
|
||||
7. Copies or generates jail configurations
|
||||
8. Starts and enables the fail2ban service
|
||||
|
||||
## Handlers
|
||||
|
||||
- `Restart fail2ban`: Restarts the fail2ban service when configuration changes are made
|
||||
|
||||
## File Organization
|
||||
|
||||
Organize your custom files in the following structure:
|
||||
|
||||
```
|
||||
playbook_directory/
|
||||
├── files/
|
||||
│ └── fail2ban/
|
||||
│ ├── filters/
|
||||
│ │ ├── myapp.conf
|
||||
│ │ └── custom-filter.conf
|
||||
│ ├── actions/
|
||||
│ │ ├── slack-notify.conf
|
||||
│ │ └── custom-action.conf
|
||||
│ └── jails/
|
||||
│ └── complex-jail.local
|
||||
├── roles/
|
||||
│ └── fail2ban/
|
||||
└── playbook.yml
|
||||
```
|
||||
|
||||
## Tips and Best Practices
|
||||
|
||||
1. **Always whitelist management IPs** in `fail2ban_ignoreips` to prevent lockouts
|
||||
2. **Start with lenient settings** (higher maxretry, shorter bantime) and adjust based on logs
|
||||
3. **Use systemd backend** when available for better performance: `fail2ban_backend: systemd`
|
||||
4. **Monitor fail2ban logs** at `/var/log/fail2ban.log` to tune your rules
|
||||
5. **Test custom filters** before deploying to production using `fail2ban-regex`
|
||||
6. **Use dictionaries for simple jails**, copy files for complex ones requiring specific options
|
||||
7. **Keep custom filters and actions in version control** alongside your playbooks
|
||||
|
||||
## Testing Custom Filters
|
||||
|
||||
Test your custom filters before deployment:
|
||||
|
||||
```bash
|
||||
fail2ban-regex /var/log/myapp.log /etc/fail2ban/filter.d/myapp.conf
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user