aboutsummaryrefslogtreecommitdiff
path: root/roles/harden
diff options
context:
space:
mode:
authorheqnx <root@heqnx.com>2025-05-25 11:51:57 +0300
committerheqnx <root@heqnx.com>2025-05-25 11:51:57 +0300
commit8fb0b275bf00c963a24c21e1dfbaa64491c4f445 (patch)
tree28e9b4bbf0d4391f092f832d8f00d84ec20fed4f /roles/harden
parent7c8ed923df3c02338dfbf826fd6fd9a23dac502e (diff)
downloadansible-playbooks-8fb0b275bf00c963a24c21e1dfbaa64491c4f445.tar.gz
ansible-playbooks-8fb0b275bf00c963a24c21e1dfbaa64491c4f445.zip
added role-based playbooks
Diffstat (limited to 'roles/harden')
-rw-r--r--roles/harden/handlers/main.yaml38
-rw-r--r--roles/harden/tasks/harden.yaml139
-rw-r--r--roles/harden/tasks/main.yaml1
-rw-r--r--roles/harden/templates/jail.local.j246
4 files changed, 224 insertions, 0 deletions
diff --git a/roles/harden/handlers/main.yaml b/roles/harden/handlers/main.yaml
new file mode 100644
index 0000000..e25c78f
--- /dev/null
+++ b/roles/harden/handlers/main.yaml
@@ -0,0 +1,38 @@
+- name: update grub
+ command: update-grub
+
+- name: reload fail2ban
+ command: fail2ban-client reload
+
+- name: enable ufw
+ ufw:
+ state: enabled
+ policy: deny
+
+- name: restart ufw
+ systemd:
+ name: ufw
+ state: restarted
+ enabled: true
+ when: ansible_facts['service_mgr'] == 'systemd'
+
+- name: restart ssh
+ systemd:
+ name: ssh
+ state: restarted
+ enabled: true
+ when: ansible_facts['service_mgr'] == 'systemd'
+
+- name: restart unattended-upgrades
+ systemd:
+ name: unattended-upgrades
+ state: restarted
+ enabled: true
+ when: ansible_facts['service_mgr'] == 'systemd'
+
+- name: restart fail2ban
+ systemd:
+ name: fail2ban
+ state: restarted
+ enabled: true
+ when: ansible_facts['service_mgr'] == 'systemd'
diff --git a/roles/harden/tasks/harden.yaml b/roles/harden/tasks/harden.yaml
new file mode 100644
index 0000000..cf60e95
--- /dev/null
+++ b/roles/harden/tasks/harden.yaml
@@ -0,0 +1,139 @@
+- name: remove snap and snapd
+ apt:
+ name:
+ - snap
+ - snapd
+ state: absent
+ purge: true
+
+- name: clean apt cache
+ apt:
+ autoclean: yes
+
+- name: clear /etc/issue and /etc/motd
+ copy:
+ content: ""
+ dest: "{{ item }}"
+ loop:
+ - /etc/issue
+ - /etc/motd
+
+- name: check if /etc/update-motd.d directory exists
+ stat:
+ path: /etc/update-motd.d
+ register: motd_dir
+
+- name: find files in /etc/update-motd.d
+ find:
+ paths: /etc/update-motd.d
+ file_type: file
+ register: motd_files
+ when: motd_dir.stat.exists
+
+- name: remove execute permissions from all files in /etc/update-motd.d
+ file:
+ path: "{{ item.path }}"
+ mode: u-x,g-x,o-x
+ loop: "{{ motd_files.files }}"
+ when: motd_dir.stat.exists
+
+- name: enforce root-only cron/at
+ file:
+ path: "{{ item }}"
+ state: touch
+ owner: root
+ group: root
+ mode: '0600'
+ loop:
+ - /etc/cron.allow
+ - /etc/at.allow
+
+- name: remove deny files for cron and at
+ file:
+ path: "{{ item }}"
+ state: absent
+ loop:
+ - /etc/cron.deny
+ - /etc/at.deny
+
+- name: backup sshd_config
+ copy:
+ src: /etc/ssh/sshd_config
+ dest: "/etc/ssh/sshd_config.bak_{{ ansible_date_time.iso8601_basic }}"
+ remote_src: yes
+
+- name: harden sshd_config
+ copy:
+ dest: /etc/ssh/sshd_config
+ content: |
+ Port 22
+ Banner /etc/issue
+ UsePAM yes
+ Protocol 2
+ Subsystem sftp /usr/lib/openssh/sftp-server
+ LogLevel verbose
+ PrintMotd no
+ AcceptEnv LANG LC_*
+ MaxSessions 5
+ StrictModes yes
+ Compression no
+ MaxAuthTries 3
+ IgnoreRhosts yes
+ PrintLastLog yes
+ AddressFamily inet
+ X11Forwarding no
+ PermitRootLogin yes
+ AllowTcpForwarding no
+ ClientAliveInterval 1200
+ AllowAgentForwarding no
+ PermitEmptyPasswords no
+ ClientAliveCountMax 0
+ GSSAPIAuthentication no
+ KerberosAuthentication no
+ IgnoreUserKnownHosts yes
+ PermitUserEnvironment no
+ ChallengeResponseAuthentication no
+ MACs hmac-sha2-512,hmac-sha2-256
+ Ciphers aes128-ctr,aes192-ctr,aes256-ctr
+
+- name: regenerate SSH host keys
+ shell: |
+ rm -f /etc/ssh/ssh_host_*key*
+ ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
+ ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
+ args:
+ creates: /etc/ssh/ssh_host_ed25519_key
+ notify: restart ssh
+
+- name: enable unattended-upgrades
+ shell: dpkg-reconfigure --priority=low unattended-upgrades
+ args:
+ creates: /etc/apt/apt.conf.d/50unattended-upgrades
+ notify: restart unattended-upgrades
+
+- name: disable ipv6 in grub
+ lineinfile:
+ path: /etc/default/grub
+ regexp: '^GRUB_CMDLINE_LINUX='
+ line: 'GRUB_CMDLINE_LINUX="ipv6.disable=1"'
+ notify: update grub
+
+- name: allow ssh port and enable ufw
+ ufw:
+ rule: allow
+ port: 22
+ proto: tcp
+ notify:
+ - enable ufw
+ - restart ufw
+
+- name: deploy custom fail2ban jail.local
+ template:
+ src: templates/jail.local.j2
+ dest: /etc/fail2ban/jail.local
+ owner: root
+ group: root
+ mode: '0644'
+ notify:
+ - restart fail2ban
+ - reload fail2ban
diff --git a/roles/harden/tasks/main.yaml b/roles/harden/tasks/main.yaml
new file mode 100644
index 0000000..95fdd29
--- /dev/null
+++ b/roles/harden/tasks/main.yaml
@@ -0,0 +1 @@
+- import_tasks: tasks/harden.yaml
diff --git a/roles/harden/templates/jail.local.j2 b/roles/harden/templates/jail.local.j2
new file mode 100644
index 0000000..dd548df
--- /dev/null
+++ b/roles/harden/templates/jail.local.j2
@@ -0,0 +1,46 @@
+[INCLUDES]
+#before = paths-distro.conf
+before = paths-debian.conf
+
+[DEFAULT]
+#ignoreself = true
+#ignoreip = 127.0.0.1/8 ::1
+ignorecommand =
+bantime = 1h
+findtime = 10m
+maxretry = 3
+maxmatches = %(maxretry)s
+backend = auto
+usedns = warn
+logencoding = auto
+enabled = false
+mode = normal
+filter = %(__name__)s[mode=%(mode)s]
+destemail = root@localhost
+sender = root@<fq-hostname>
+mta = sendmail
+protocol = tcp
+chain = <known/chain>
+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_mw = %(action_)s
+ %(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]
+action_mwl = %(action_)s
+ %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
+action_xarf = %(action_)s
+ xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]
+action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
+ %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
+action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]
+action_abuseipdb = abuseipdb
+action = %(action_)s
+
+[sshd]
+mode = aggressive
+enabled = true
+port = ssh
+logpath = %(sshd_log)s
+backend = %(sshd_backend)s