diff options
| author | Guilhem Moulin <guilhem@fripost.org> | 2020-01-23 05:33:17 +0100 | 
|---|---|---|
| committer | Guilhem Moulin <guilhem@fripost.org> | 2020-01-25 01:57:05 +0100 | 
| commit | ee4e9e9836ad05279647b04eb1e8a3a4b0e16568 (patch) | |
| tree | d4e566a7b535f7d62e4fd6fd1a521ea6d7563d21 /roles/common | |
| parent | 7641a5d5d152db349082b1d0ec93a40888b2ef8e (diff) | |
Improve/harden fail2ban configuration.
 * Use nftables sets with a timeout
 * Start daemon with a hardened unit file and restricted Capability
   Bounding Set.  (This requires to change the log path to
   /var/log/fail2ban/*.)
 * Skip database as we don't care about persistence.
 * Refactor jail.local
Diffstat (limited to 'roles/common')
7 files changed, 135 insertions, 98 deletions
| diff --git a/roles/common/files/etc/fail2ban/action.d/nftables-allports.local b/roles/common/files/etc/fail2ban/action.d/nftables-allports.local new file mode 100644 index 0000000..3c8c030 --- /dev/null +++ b/roles/common/files/etc/fail2ban/action.d/nftables-allports.local @@ -0,0 +1,16 @@ +[Definition] +# No need to create sets and rules, these are defined globally in nftables.conf +actionstart = +actionstop = +actioncheck = + +# unbanning is taken care of by setting a timeout on the nft set already +actionunban = + +[Init] +# With banaction = *-allports there is no need for separate rule names +set_name = fail2ban +blocktype = drop + +[Init?family=inet6] +set_name = fail2ban6 diff --git a/roles/common/files/etc/fail2ban/fail2ban.local b/roles/common/files/etc/fail2ban/fail2ban.local new file mode 100644 index 0000000..53cba35 --- /dev/null +++ b/roles/common/files/etc/fail2ban/fail2ban.local @@ -0,0 +1,20 @@ +[Definition] + +# Option: logtarget +# Notes.: Set the log target. This could be a file, SYSLOG, STDERR or STDOUT. +#         Only one log target can be specified. +#         If you change logtarget from the default value and you are +#         using logrotate -- also adjust or disable rotation in the +#         corresponding configuration file +#         (e.g. /etc/logrotate.d/fail2ban on Debian systems) +# Values: [ STDOUT | STDERR | SYSLOG | SYSOUT | FILE ]  Default: STDERR +# +logtarget = /var/log/fail2ban/fail2ban.log + +# Options: dbfile +# Notes.: Set the file for the fail2ban persistent data to be stored. +#         A value of ":memory:" means database is only stored in memory +#         and data is lost when fail2ban is stopped. +#         A value of "None" disables the database. +# Values: [ None :memory: FILE ] Default: /var/lib/fail2ban/fail2ban.sqlite3 +dbfile = None diff --git a/roles/common/files/etc/fail2ban/filter.d/nextcloud.conf b/roles/common/files/etc/fail2ban/filter.d/nextcloud.conf new file mode 100644 index 0000000..22305d6 --- /dev/null +++ b/roles/common/files/etc/fail2ban/filter.d/nextcloud.conf @@ -0,0 +1,6 @@ +# Source: https://github.com/nextcloud/vm/blob/master/apps/fail2ban.sh + +[Definition] +failregex=(?:^{|,)\"message\":\"Login failed: <F-USER>.*?</F-USER> \(Remote IP: '<HOST>'\)\"(:?,|}$) +          (?:^{|,)\"message\":\"Login failed: <F-USER>.*?</F-USER> \(Remote IP: <HOST>\)\"(:?,|}$) +          (?:^{|,)\"remoteAddr\":\"<HOST>\",.*Trusted domain error diff --git a/roles/common/files/etc/fail2ban/filter.d/roundcube.conf b/roles/common/files/etc/fail2ban/filter.d/roundcube.conf deleted file mode 100644 index c8cb5d3..0000000 --- a/roles/common/files/etc/fail2ban/filter.d/roundcube.conf +++ /dev/null @@ -1,16 +0,0 @@ -[Definition] - -# Option:  failregex -# Notes.:  regex to match the password failures messages in the logfile. The -#          host must be matched by a group named "host". The tag "<HOST>" can -#          be used for standard IP/hostname matching and is only an alias for -#          (?:::f{4,6}:)?(?P<host>[\w\-.^_]+) -# Values:  TEXT -# -failregex = IMAP Error: Login failed for \S+ from <HOST>\. AUTHENTICATE \S+: Authentication failed\. - -# Option:  ignoreregex -# Notes.:  regex to ignore. If this regex matches, the line is ignored. -# Values:  TEXT -# -ignoreregex = diff --git a/roles/common/files/etc/systemd/system/fail2ban.service.d/override.conf b/roles/common/files/etc/systemd/system/fail2ban.service.d/override.conf new file mode 100644 index 0000000..e3e651f --- /dev/null +++ b/roles/common/files/etc/systemd/system/fail2ban.service.d/override.conf @@ -0,0 +1,18 @@ +[Unit] +After=nftables.service + +[Service] +# Need explicit rights to read logs as we don't grant CAP_DAC_READ_SEARCH +SupplementaryGroups=adm + +# Hardening +NoNewPrivileges=yes +ProtectSystem=strict +ReadWriteDirectories=/var/log/fail2ban +RuntimeDirectory=fail2ban +PrivateDevices=yes +ProtectControlGroups=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW diff --git a/roles/common/tasks/fail2ban.yml b/roles/common/tasks/fail2ban.yml index 84e6b7a..89427ea 100644 --- a/roles/common/tasks/fail2ban.yml +++ b/roles/common/tasks/fail2ban.yml @@ -1,37 +1,79 @@  - name: Install fail2ban    apt: pkg=fail2ban -- name: Configure fail2ban +# Log into a dedicate directory so we can use ReadWriteDirectories in +# the .service file +- name: Create directory /var/log/fail2ban +  file: path=/var/log/fail2ban +        state=directory +        owner=root group=adm +        mode=0750 + +- name: Fix fail2ban logrotate snippet +  lineinfile: dest=/etc/logrotate.d/fail2ban +              state=present +              line="/var/log/fail2ban/*.log" +              insertbefore="^[^#]*\\s{$" +  tags: +    - logrotate + +- name: Configure fail2ban (fail2ban.local) +  copy: src=etc/fail2ban/fail2ban.local +        dest=/etc/fail2ban/fail2ban.local +        owner=root group=root +        mode=0644 +  register: r1 +  notify: +    - Restart fail2ban + +- name: Configure fail2ban (jail.local)    template: src=etc/fail2ban/jail.local.j2              dest=/etc/fail2ban/jail.local              owner=root group=root              mode=0644 -  register: r1 +  register: r2    notify:      - Restart fail2ban -- name: Add roundcube filter -  copy: src=etc/fail2ban/filter.d/roundcube.conf -        dest=/etc/fail2ban/filter.d/roundcube.conf +- name: Configure fail2ban (action.d/nftables-allports.local) +  copy: src=etc/fail2ban/action.d/nftables-allports.local +        dest=/etc/fail2ban/action.d/nftables-allports.local          owner=root group=root          mode=0644 -  register: r2 -  when: "'webmail' in group_names" +  register: r3    notify:      - Restart fail2ban -- name: Add dovecot filter -  copy: src=etc/fail2ban/filter.d/dovecot.conf -        dest=/etc/fail2ban/filter.d/dovecot.conf +- name: Copy filters +  copy: src=etc/fail2ban/filter.d/ +        dest=/etc/fail2ban/filter.d/          owner=root group=root          mode=0644 -  register: r3 -  when: "'IMAP' in group_names" +  register: r4 +  notify: +    - Restart fail2ban + +- name: Create directory /etc/systemd/system/fail2ban.service.d/override.conf +  file: path=/etc/systemd/system/fail2ban.service.d +        state=directory +        owner=root group=root +        mode=0750 + +- name: Harden fail2ban.service +  copy: src=etc/systemd/system/fail2ban.service.d/override.conf +        dest=/etc/systemd/system/fail2ban.service.d/override.conf +        owner=root group=root +        mode=0644 +  register: r5    notify: +    - systemctl daemon-reload      - Restart fail2ban  - name: Start fail2ban    service: name=fail2ban state=started -  when: not (r1.changed or r2.changed or r3.changed) +  when: not (r1.changed or r2.changed or r3.changed or r4.changed or r5.changed)  - meta: flush_handlers + +- name: Delete /var/lib/fail2ban/fail2ban.sqlite3 +  file: path=/var/lib/fail2ban/fail2ban.sqlite3 state=absent diff --git a/roles/common/templates/etc/fail2ban/jail.local.j2 b/roles/common/templates/etc/fail2ban/jail.local.j2 index 618fbd7..29b004c 100644 --- a/roles/common/templates/etc/fail2ban/jail.local.j2 +++ b/roles/common/templates/etc/fail2ban/jail.local.j2 @@ -1,93 +1,44 @@  # {{ ansible_managed }}  # Do NOT edit this file directly!  [DEFAULT]  # Destination email address used solely for the interpolations in  # jail.{conf,local} configuration files.  destemail = admin@fripost.org -# Specify chain where jumps would need to be added in iptables-* actions -chain = fail2ban +# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban +# will not ban a host which matches an address in this list. Several addresses +# can be defined using space (and/or comma) separator. +ignoreip = 127.0.0.0/8, ::1, {{ ipsec_subnet }} -# Choose default action. -action = %(action_)s - -# Don't ban ourselves. -ignoreip = 127.0.0.0/8 {{ ipsec_subnet }} +banaction = nftables-allports +logpath = /var/log/fail2ban/fail2ban.log  #  # JAILS  # -[ssh] - -enabled  = true -port     = {{ ansible_port|default('22') }} -filter   = sshd -logpath  = /var/log/auth.log -maxretry = 5 - -[ssh-ddos] - -enabled  = true -port     = {{ ansible_port|default('22') }} -filter   = sshd-ddos -logpath  = /var/log/auth.log -maxretry = 2 - - -# Generic filter for pam. Has to be used with action which bans all ports -# such as iptables-allports, shorewall -[pam-generic] - -enabled   = true -# pam-generic filter can be customized to monitor specific subset of 'tty's -filter    = pam-generic -# port actually must be irrelevant but lets leave it all for some possible uses -port      = anyport -banaction = iptables-allports -logpath   = /var/log/auth.log -maxretry  = 6 +[sshd] +enabled = true -{% if 'MX' in group_names %}  [postfix] +enabled = {{ 'MX' in group_names }} -enabled  = true -port     = smtp -filter   = postfix -logpath  = /var/log/mail.log -maxretry = 10 -{% endif %} - - -{% if 'IMAP' in group_names %}  [dovecot] +enabled = {{ 'IMAP' in group_names }} -enabled = true -port    = imap2,imaps,pop3,pop3s,sieve -filter  = dovecot -logpath = /var/log/mail.log -{% endif %} - - -{% if 'MSA' in group_names %} -[sasl] - -enabled  = true -port     = submission,submissions -filter   = postfix-sasl -logpath  = /var/log/mail.warn -{% endif %} - +[postfix-sasl] +enabled  = {{ 'MSA' in group_names }} -{% if 'webmail' in group_names %} -[roundcube] +[roundcube-auth] +enabled = {{ 'webmail' in group_names }} +# XXX Bullseye: logpath = /var/log/roundcube/errors.log -enabled  = true -port     = http,https -filter   = roundcube -logpath  = /var/log/roundcube/errors -{% endif %} +[nextcloud] +enabled = {{ 'nextcloud' in group_names }} +port    = http,https +filter  = nextcloud +logpath = /var/log/nextcloud/nextcloud.log  # vim: set filetype=dosini : | 
