diff --git a/defaults/main.yml b/defaults/main.yml index c416f4598dae184296d7b8967f345efe37da9939..9493fbcf855807b1fd6161b2aa7dcf8d3653419b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,5 +1,5 @@ --- -server_security__manage_mail: 'enabled' +server_security__manage_mail: "enabled" default_maintenance_email: "maintenance@example.org" default_smtp_server: "smtp.example.org" default_sshd_port: 10022 diff --git a/handlers/main.yml b/handlers/main.yml index eb83c91390d3a3653e6548ba5f2f034e9053ff58..f5f5580632109ed3939844682777ed2a17ed7a96 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,27 +1,27 @@ --- -- name: Restore iptables +- name: "restore iptables" ansible.builtin.service: - name: netfilter-persistent - state: restarted + name: netfilter-persistent + state: restarted -- name: Restart fail2ban +- name: "restart fail2ban" ansible.builtin.service: - name: fail2ban - state: restarted + name: fail2ban + state: restarted -- name: Restart docker +- name: "restart docker" ansible.builtin.service: - name: docker - state: restarted + name: docker + state: restarted when: inventory_hostname in groups.docker -- name: Restart auditd +- name: "restart auditd" ansible.builtin.service: - name: auditd - state: restarted + name: auditd + state: restarted -- name: Restart rsyslog +- name: "restart rsyslog" ansible.builtin.service: - name: rsyslog - state: restarted + name: rsyslog + state: restarted diff --git a/meta/main.yml b/meta/main.yml index 9db171b3a4f38fa14066969e13073881c9317ce7..13277fe1d91229130201faa2bdf59d4805ca476e 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,19 +1,21 @@ --- galaxy_info: - author: lefilament - description: This role installs and configures security on servers (iptables, fail2ban, auditd) - company: Le Filament (https://le-filament.com) - license: AGPL-3.0-or-later - min_ansible_version: "2.1" - platforms: - - name: Ubuntu - versions: - - xenial - - bionic - - focal - galaxy_tags: - - iptables - - fail2ban - - auditd - - security - - firewall + author: "lefilament" + description: "This role installs and configures security on servers (iptables, fail2ban, auditd)" + company: "Le Filament (https://le-filament.com)" + license: "AGPL-3.0-or-later" + min_ansible_version: "2.1" + platforms: + - name: "Ubuntu" + versions: + - "jammy" + - "noble" + - name: "Debian" + versions: + - "bookworm" + galaxy_tags: + - "iptables" + - "fail2ban" + - "auditd" + - "security" + - "firewall" diff --git a/tasks/mail.yml b/tasks/mail.yml index 3b820e1716e09fe12657872346961c360478ac18..09c682cab8f1380449e38dd83b9b1fddb167dbc6 100644 --- a/tasks/mail.yml +++ b/tasks/mail.yml @@ -1,29 +1,32 @@ --- -- name: Remove mail packages not necessary +- name: "Remove mail packages not necessary" ansible.builtin.apt: - name: [bsd-mailx mailutils postfix] - autoremove: true - state: absent + name: + - "bsd-mailx" + - "mailutils" + - "postfix" + state: absent + autoremove: true when: ansible_os_family == "Debian" -- name: Check that ssmtp is installed +- name: "Check that ssmtp is installed" ansible.builtin.package: - name: ssmtp + name: "ssmtp" state: present -- name: Check that sendmail redirects to ssmtp +- name: "Check that sendmail redirects to ssmtp" ansible.builtin.file: - src: ssmtp - dest: /usr/sbin/sendmail + src: "ssmtp" + dest: "/usr/sbin/sendmail" force: true - owner: root - group: mail + owner: "root" + group: "mail" state: link -- name: Configuration file for ssmtp +- name: "Configuration file for ssmtp" ansible.builtin.template: - src: ssmtp.conf.j2 - dest: /etc/ssmtp/ssmtp.conf - owner: root - group: mail - mode: '0640' + src: "ssmtp.conf.j2" + dest: "/etc/ssmtp/ssmtp.conf" + owner: "root" + group: "mail" + mode: "0640" diff --git a/tasks/main.yml b/tasks/main.yml index a1101501b5b0e043b7ca93818e28d39f26310402..40e63c149d6f4dd1cc2a7eee9776d86b8546e46c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,129 +1,136 @@ --- -- name: Import mail tasks +- name: "Import mail tasks" ansible.builtin.import_tasks: mail.yml when: server_security__manage_mail == 'enabled' -- name: Install fail2ban, iptables-persistent and auditd +- name: "Install fail2ban, iptables-persistent and auditd" ansible.builtin.package: - name: - - fail2ban - - iptables-persistent - - auditd - state: present + name: + - "fail2ban" + - "iptables-persistent" + - "auditd" + state: present async: 120 poll: 10 when: not ansible_check_mode -- name: Check presence of fail2ban, iptables-persistent and auditd packages +- name: "Check presence of fail2ban, iptables-persistent and auditd packages" ansible.builtin.package: - name: - - fail2ban - - iptables-persistent - - auditd - state: present + name: + - "fail2ban" + - "iptables-persistent" + - "auditd" + state: present when: ansible_check_mode -- name: Make fail2ban persistent +- name: "Make fail2ban persistent" ansible.builtin.service: - name: fail2ban - enabled: true - state: started + name: "fail2ban" + enabled: true + state: started -- name: Make sure netfilter-persistent is enabled +- name: "Make sure netfilter-persistent is enabled" ansible.builtin.service: - name: netfilter-persistent - enabled: true - state: started + name: "netfilter-persistent" + enabled: true + state: started -- name: Make sure auditd is enabled +- name: "Make sure auditd is enabled" ansible.builtin.service: - name: auditd - enabled: true - state: started + name: "auditd" + enabled: true + state: started -- name: Push specific fail2ban jail configuration file +- name: "Push specific fail2ban jail configuration file" + tags: + - "fail2ban" ansible.builtin.template: - src: "jail.{{ ansible_distribution }}{{ ansible_distribution_major_version }}.j2" - dest: "/etc/fail2ban/jail.local" - owner: 'root' - group: 'root' - mode: '0644' + src: "jail.local.j2" + dest: "/etc/fail2ban/jail.local" + owner: "root" + group: "root" + mode: "0644" when: ansible_os_family == "Debian" - notify: Restart fail2ban - tags: fail2ban + notify: + - "restart fail2ban" -- name: Push specific fail2ban actions +- name: "Push specific fail2ban actions" + tags: + - "fail2ban" ansible.builtin.template: - src: "{{ item }}.j2" - dest: "/etc/fail2ban/{{ item }}.local" - owner: 'root' - group: 'root' - mode: '0644' + src: "{{ item }}.j2" + dest: "/etc/fail2ban/{{ item }}.local" + owner: "root" + group: "root" + mode: "0644" with_items: - - action.d/sendmail-common - - action.d/sendmail-whois-lines + - "action.d/sendmail-common" + - "action.d/sendmail-whois-lines" when: ansible_os_family == "Debian" - notify: Restart fail2ban - tags: fail2ban + notify: + - "restart fail2ban" -- name: Push specific fail2ban filters +- name: "Push specific fail2ban filters" + tags: + - "fail2ban" ansible.builtin.copy: - src: traefik-auth - dest: "/etc/fail2ban/filter.d/traefik-auth.conf" - owner: 'root' - group: 'root' - mode: '0644' - force: false + src: "traefik-auth" + dest: "/etc/fail2ban/filter.d/traefik-auth.conf" + owner: "root" + group: "root" + mode: "0644" + force: false when: inventory_hostname in groups.docker - notify: Restart fail2ban - tags: fail2ban + notify: + - "restart fail2ban" -- name: Create iptables configuration +- name: "Create iptables configuration" ansible.builtin.template: - src: iptables.conf.j2 - dest: /etc/iptables/rules.v4 - owner: root - group: root - mode: '0600' + src: "iptables.conf.j2" + dest: "/etc/iptables/rules.v4" + owner: "root" + group: "root" + mode: "0600" notify: - - Restore iptables - - Restart fail2ban - - Restart docker + - "restore iptables" + - "restart fail2ban" + - "restart docker" -- name: Create ip6tables configuration +- name: "Create ip6tables configuration" ansible.builtin.template: - src: ip6tables.conf.j2 - dest: "/etc/iptables/rules.v6" - owner: root - group: root - mode: '0600' + src: "ip6tables.conf.j2" + dest: "/etc/iptables/rules.v6" + owner: "root" + group: "root" + mode: "0600" notify: - - Restore iptables - - Restart fail2ban - - Restart docker + - "restore iptables" + - "restart fail2ban" + - "restart docker" -- name: Push iptables rsyslog configuration +- name: "Push iptables rsyslog configuration" ansible.builtin.copy: - src: rsyslog.d-iptables - dest: /etc/rsyslog.d/33-iptables.conf - owner: root - group: root - mode: '0644' - notify: Restart rsyslog + src: "rsyslog.d-iptables" + dest: "/etc/rsyslog.d/33-iptables.conf" + owner: "root" + group: "root" + mode: "0644" + when: ansible_distribution == 'Ubuntu' + notify: "restart rsyslog" -- name: Push iptables logrotate configuration +- name: "Push iptables logrotate configuration" ansible.builtin.copy: - src: logrotate.d-iptables - dest: /etc/logrotate.d/iptables - owner: root - group: root - mode: '0644' + src: "logrotate.d-iptables" + dest: "/etc/logrotate.d/iptables" + owner: "root" + group: "root" + mode: "0644" -- name: Configuration file for auditd +- name: "Configuration file for auditd" ansible.builtin.template: - src: audit.rules.j2 - dest: /etc/audit/rules.d/audit.rules - owner: root - group: root - mode: '0640' - notify: Restart auditd + src: "audit.rules.j2" + dest: "/etc/audit/rules.d/audit.rules" + owner: "root" + group: "root" + mode: "0640" + notify: "restart auditd" diff --git a/templates/jail.Ubuntu16.j2 b/templates/jail.Ubuntu16.j2 deleted file mode 100644 index 2d9792d90fbdcccf87361beea22431cc1b6e58c1..0000000000000000000000000000000000000000 --- a/templates/jail.Ubuntu16.j2 +++ /dev/null @@ -1,67 +0,0 @@ -[INCLUDES] -before = paths-debian.conf - -[DEFAULT] -# MISC -ignoreip = 127.0.0.1/8 - -ignorecommand = -bantime = 86400 ; ban for 1 day -findtime = 3600 ; search for 1 hour -maxretry = 3 - -backend = auto -usedns = warn -logencoding = auto -enabled = false - -filter = %(__name__)s - - -# ACTIONS -destemail = {{ default_maintenance_email }} -sender = {{ inventory_hostname|lower }}_server@{{ inventory_hostname|lower }}.server -mta = sendmail -protocol = tcp -chain = INPUT -port = 0:65535 - -banaction = iptables-multiport - -action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] -action = %(action_)s - -# JAILS -[sshd] -enabled = true -logpath = %(sshd_log)s -port = {{ default_sshd_port }} - - -[sshd-ddos] -enabled = true -port = {{ default_sshd_port }} -logpath = %(sshd_log)s - - -{% if inventory_hostname in groups.odoo_server or inventory_hostname in groups.owncloud_server %} -[nginx-http-auth] -enabled = true -logpath = %(nginx_error_log)s -port = http,https - -[nginx-botsearch] -enabled = true -logpath = %(nginx_error_log)s -maxretry = 2 -port = http,https - - -{% endif %} -[recidive] -enabled = true -logpath = /var/log/fail2ban.log -banaction = iptables-allports -bantime = 604800 ; 1 week -findtime = 86400 ; 1 day -maxretry = 5 diff --git a/templates/jail.Ubuntu18.j2 b/templates/jail.Ubuntu18.j2 deleted file mode 100644 index 0ccfd5ef3a4b7d1ab05b7031a3c69f057b740778..0000000000000000000000000000000000000000 --- a/templates/jail.Ubuntu18.j2 +++ /dev/null @@ -1,77 +0,0 @@ -[INCLUDES] -before = paths-debian.conf - -[DEFAULT] -# MISC -ignoreip = 127.0.0.1/8{% if inventory_hostname in groups.docker %} 172.16.0.0/12 192.168.0.0/16{% endif %} - -ignorecommand = -bantime = 86400 ; ban for 1 day -findtime = 3600 ; search for 1 hour -maxretry = 3 - -backend = polling -usedns = warn -logencoding = auto -enabled = false -mode = normal -filter = %(__name__)s[mode=%(mode)s] - - -# ACTIONS -destemail = {{ default_maintenance_email }} -sender = {{ inventory_hostname|lower }}_server@{{ inventory_hostname|lower }}.server -mta = sendmail -protocol = tcp -chain = INPUT -port = 0:65535 -fail2ban_agent = Fail2Ban/%(fail2ban_version)s -banaction = iptables-multiport -banaction_allports = iptables-allports -action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] -action = %(action_)s - -# JAILS -[sshd] -backend = systemd -enabled = true -logpath = /var/log/auth.log -mode = aggressive -port = {{ default_sshd_port }} - - -[recidive] -banaction = %(banaction_allports)s -bantime = 1w -enabled = true -findtime = 1d -logpath = /var/log/fail2ban.log - - -{% if inventory_hostname in groups.odoo_server or inventory_hostname in groups.owncloud_server %} -[nginx-http-auth] -enabled = true -logpath = /var/log/nginx/*error.log -port = http,https - -[nginx-botsearch] -enabled = true -port = http,https -logpath = /var/log/nginx/*error.log -maxretry = 2 - - -{% endif %} -{% if inventory_hostname in groups.docker %} -[docker-traefik-auth] -chain = DOCKER-USER -enabled = true -filter = traefik-auth -{% if docker_userns_remap %} -logpath = /var/lib/docker/{{ dockremap_subuid | default("*") }}.{{ dockremap_subgid | default("*") }}/volumes/inverseproxy_logs/_data/access.log -{% else %} -logpath = /var/lib/docker/volumes/inverseproxy_logs/_data/access.log -{% endif %} -port = http,https - -{% endif %} diff --git a/templates/jail.Ubuntu20.j2 b/templates/jail.Ubuntu20.j2 deleted file mode 100644 index ddd1b120f950f8559974a323ce195e885048acc4..0000000000000000000000000000000000000000 --- a/templates/jail.Ubuntu20.j2 +++ /dev/null @@ -1,91 +0,0 @@ -[INCLUDES] -before = paths-debian.conf - -[DEFAULT] -# MISC -ignoreip = 127.0.0.1/8{% if inventory_hostname in groups.docker %} 172.16.0.0/12 192.168.0.0/16{% endif %}{% for host in groups.docker_nagios %} {{ hostvars[host].ansible_host }}/32{% endfor %} - -ignorecommand = -bantime = 86400 ; ban for 1 day -findtime = 3600 ; search for 1 hour -maxretry = 3 -maxmatches = %(maxretry)s -backend = polling -usedns = warn -logencoding = auto -enabled = false -mode = normal -filter = %(__name__)s[mode=%(mode)s] - - -# ACTIONS -destemail = {{ default_maintenance_email }} -sender = {{ inventory_hostname|lower }}_server@{{ inventory_hostname|lower }}.server -mta = sendmail -protocol = tcp -chain = INPUT -port = 0:65535 -fail2ban_agent = Fail2Ban/%(fail2ban_version)s -banaction = iptables-multiport -banaction_allports = iptables-allports -action_ = %(banaction)s[name=%(__name__)s, bantime="%(bantime)s", port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] -action = %(action_)s - -# JAILS -[sshd] -backend = systemd -enabled = true -logpath = /var/log/auth.log -mode = aggressive -port = {{ default_sshd_port }} - - -[recidive] -banaction = %(banaction_allports)s -bantime = 1w -enabled = true -findtime = 1d -logpath = /var/log/fail2ban.log - - -{% if inventory_hostname in groups.gitlab %} -[nginx-http-auth] -enabled = true -logpath = /var/log/gitlab/nginx/*error.log -port = http,https - -[nginx-botsearch] -enabled = true -port = http,https -logpath = /var/log/gitlab/nginx/*error.log -maxretry = 3 - - -{% endif %} -{% if inventory_hostname in groups.odoo_server or inventory_hostname in groups.owncloud_server %} -[nginx-http-auth] -enabled = true -logpath = /var/log/nginx/*error.log -port = http,https - -[nginx-botsearch] -enabled = true -port = http,https -logpath = /var/log/nginx/*error.log -maxretry = 2 - - -{% endif %} -{% if inventory_hostname in groups.docker and inventory_hostname not in groups.docker_nextcloud %} -[docker-traefik-auth] -chain = DOCKER-USER -enabled = true -filter = traefik-auth -{% if docker_userns_remap %} -logpath = /var/lib/docker/{{ dockremap_subuid | default("*") }}.{{ dockremap_subgid | default("*") }}/volumes/inverseproxy_logs/_data/access.log -{% else %} -logpath = /var/lib/docker/volumes/inverseproxy_logs/_data/access.log -{% endif %} -port = http,https - -{% endif %} diff --git a/templates/jail.Ubuntu22.j2 b/templates/jail.Ubuntu22.j2 deleted file mode 100644 index 23342d4ea9896b93b3326fc2d6cf16014dbc4d0f..0000000000000000000000000000000000000000 --- a/templates/jail.Ubuntu22.j2 +++ /dev/null @@ -1,91 +0,0 @@ -[INCLUDES] -before = paths-debian.conf - -[DEFAULT] -# MISC -ignoreip = 127.0.0.1/8{% if inventory_hostname in groups.docker | default([]) %} 172.16.0.0/12 192.168.0.0/16{% endif %}{% for host in groups.docker_nagios | default([]) %} {{ hostvars[host].ansible_host }}/32{% endfor %} - -ignorecommand = -bantime = 86400 ; ban for 1 day -findtime = 3600 ; search for 1 hour -maxretry = 3 -maxmatches = %(maxretry)s -backend = polling -usedns = warn -logencoding = auto -enabled = false -mode = normal -filter = %(__name__)s[mode=%(mode)s] - -# ACTIONS -destemail = {{ default_maintenance_email }} -sender = {{ inventory_hostname|lower }}_server@{{ inventory_hostname|lower }}.server -mta = sendmail -protocol = tcp -chain = INPUT -port = 0:65535 -fail2ban_agent = Fail2Ban/%(fail2ban_version)s -banaction = iptables-multiport -banaction_allports = iptables-allports -action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] -action = %(action_)s - -# JAILS -[sshd] -backend = systemd -enabled = true -logpath = /var/log/auth.log -mode = aggressive -port = {{ default_sshd_port }} - -{% if inventory_hostname in groups.gitlab | default([]) %} -[gitlab] -enabled = true -logpath = /var/log/gitlab/gitlab-rails/application.log -port = http,https - -[nginx-http-auth] -enabled = true -logpath = /var/log/gitlab/nginx/*error.log -port = http,https - -[nginx-botsearch] -enabled = true - -logpath = /var/log/gitlab/nginx/*error.log -maxretry = 2 -port = http,https - -{% endif %} -{% if inventory_hostname in groups.odoo_server | default([]) or inventory_hostname in groups.owncloud_server | default([]) %} -[nginx-http-auth] -enabled = true -logpath = /var/log/nginx/*error.log -port = http,https - -[nginx-botsearch] -enabled = true -logpath = /var/log/nginx/*error.log -maxretry = 2 -port = http,https - -{% endif %} -[recidive] -banaction = %(banaction_allports)s -bantime = 1w -enabled = true -findtime = 1d -logpath = /var/log/fail2ban.log -{% if inventory_hostname in groups.docker | default([]) and inventory_hostname not in groups.docker_nextcloud | default([]) %} - -[traefik-auth] -chain = FORWARD -enabled = true -{% if docker_userns_remap %} -logpath = /var/lib/docker/{{ dockremap_subuid | default("*") }}.{{ dockremap_subgid | default("*") }}/volumes/inverseproxy_logs/_data/access.log -{% else %} -logpath = /var/lib/docker/volumes/inverseproxy_logs/_data/access.log -{% endif %} -mode = aggressive -port = http,https -{% endif %} diff --git a/templates/jail.Ubuntu24.j2 b/templates/jail.local.j2 similarity index 99% rename from templates/jail.Ubuntu24.j2 rename to templates/jail.local.j2 index 23342d4ea9896b93b3326fc2d6cf16014dbc4d0f..a0ede6e6d9fc0ea1856f9e46705131943e1b6bfa 100644 --- a/templates/jail.Ubuntu24.j2 +++ b/templates/jail.local.j2 @@ -51,7 +51,6 @@ port = http,https [nginx-botsearch] enabled = true - logpath = /var/log/gitlab/nginx/*error.log maxretry = 2 port = http,https