diff --git a/.infra/ansible/setup/tasks/configure-ssh.yml b/.infra/ansible/setup/tasks/configure-ssh.yml new file mode 100644 index 0000000..24b3481 --- /dev/null +++ b/.infra/ansible/setup/tasks/configure-ssh.yml @@ -0,0 +1,96 @@ +--- +# recommandation from https://www.sshaudit.com/hardening_guides.html +# keys configuration is skipped (first 2 steps of the documentation above) + +- name: Regen host keys + command: /opt/app/tools/ssh/regen-host-key.sh + args: + creates: /etc/ssh/ssh_host_keys_generated + +- name: Create safe moduli file + command: /opt/app/tools/ssh/moduli_file.sh + args: + creates: /etc/ssh/moduli.safe + +- name: Get if moduli file has been modified + stat: + path: /etc/ssh/moduli + register: moduli_stat + +- name: Get if moduli safe file has been modified + stat: + path: /etc/ssh/moduli.safe + register: moduli_safe_stat + +- name: Move moduli.safe to moduli + command: mv /etc/ssh/moduli.safe /etc/ssh/moduli + when: moduli_stat.stat.checksum != moduli_safe_stat.stat.checksum + notify: + - restart-ssh + +- name: Create SSH hardening configuration Ubuntu 22 + copy: + dest: /etc/ssh/sshd_config.d/ssh-audit_hardening.conf + content: | + # Restrict key exchange, cipher, and MAC algorithms, as per sshaudit.com + # hardening guide. + KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,gss-curve25519-sha256-,diffie-hellman-group16-sha512,gss-group16-sha512-,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256 + + Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-gcm@openssh.com,aes128-ctr + + MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com + + HostKeyAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 + + CASignatureAlgorithms sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sh2-256 + + GSSAPIKexAlgorithms gss-curve25519-sha256-,gss-group16-sha512- + + HostbasedAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256 + + PubkeyAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256 + when: ansible_facts['distribution_major_version'] == '22' + notify: + - restart-ssh + +- name: Create SSH hardening configuration Ubuntu 24 + copy: + dest: /etc/ssh/sshd_config.d/ssh-audit_hardening.conf + content: | + # Restrict key exchange, cipher, and MAC algorithms, as per sshaudit.com + # hardening guide. + KexAlgorithms sntrup761x25519-sha512@openssh.com,gss-curve25519-sha256-,curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256,gss-group16-sha512-,diffie-hellman-group16-sha512 + + Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-gcm@openssh.com,aes128-ctr + + MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com + + RequiredRSASize 3072 + + HostKeyAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 + + CASignatureAlgorithms sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 + + GSSAPIKexAlgorithms gss-curve25519-sha256-,gss-group16-sha512- + + HostbasedAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 + + PubkeyAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 + when: ansible_facts['distribution_major_version'] == '24' + notify: + - restart-ssh + +- name: IPtable + ansible.builtin.shell: + cmd: /opt/app/tools/ssh/iptables.sh + +# Do not use iptables-persistant due to conflict with fail2ban and docker policies +- name: Run IPtable script after reboot + ansible.builtin.cron: + name: "iptables" + special_time: "reboot" + job: "/opt/app/tools/ssh/iptables.sh >> /var/log/cron.log 2>&1; /opt/app/tools/monitoring/export-cron-status-prom.sh -c 'Restore SSH iptables' -v $?" + +- name: Validate sshd Config + shell: + cmd: sshd -t diff --git a/.infra/ansible/setup/tasks/main.yml b/.infra/ansible/setup/tasks/main.yml index 0289134..88f0d62 100644 --- a/.infra/ansible/setup/tasks/main.yml +++ b/.infra/ansible/setup/tasks/main.yml @@ -23,6 +23,9 @@ - import_tasks: install-app.yml tags: app +- import_tasks: configure-ssh.yml + tags: ssh + - import_tasks: configure-fail2ban.yml tags: fail2ban diff --git a/.infra/files/app/tools/ssh/iptables.sh b/.infra/files/app/tools/ssh/iptables.sh new file mode 100755 index 0000000..8a1f9c2 --- /dev/null +++ b/.infra/files/app/tools/ssh/iptables.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail +#Needs to be run as sudo + +iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set +iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 10 --hitcount 10 -j DROP +ip6tables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set +ip6tables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 10 --hitcount 10 -j DROP diff --git a/.infra/files/app/tools/ssh/moduli_file.sh b/.infra/files/app/tools/ssh/moduli_file.sh new file mode 100755 index 0000000..c66d19a --- /dev/null +++ b/.infra/files/app/tools/ssh/moduli_file.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail +#Needs to be run as sudo + +awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.safe \ No newline at end of file diff --git a/.infra/files/app/tools/ssh/regen-host-key.sh b/.infra/files/app/tools/ssh/regen-host-key.sh new file mode 100755 index 0000000..4227421 --- /dev/null +++ b/.infra/files/app/tools/ssh/regen-host-key.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail +#Needs to be run as sudo + +rm /etc/ssh/ssh_host_* +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 "" +touch /etc/ssh/ssh_host_keys_generated \ No newline at end of file diff --git a/.infra/files/sshd/sshd_config b/.infra/files/sshd/sshd_config index dd1e732..097ecf9 100644 --- a/.infra/files/sshd/sshd_config +++ b/.infra/files/sshd/sshd_config @@ -21,17 +21,20 @@ IgnoreRhosts yes X11Forwarding no PrintMotd no PrintLastLog yes -AcceptEnv LANG LC_* #Allow client to pass locale environment variables -ClientAliveInterval 300 #Client timeout (5 minutes) -ClientAliveCountMax 3 #This way enforces timeouts on the server side -LoginGraceTime 30 #Authentication must happen within 30 seconds -#MaxStartups 2 #Max concurrent SSH sessions +AcceptEnv LANG LC\_\* #Allow client to pass locale environment variables +ClientAliveInterval 300 #Client timeout (5 minutes) +ClientAliveCountMax 3 #This way enforces timeouts on the server side +LoginGraceTime 30 #Authentication must happen within 30 seconds +#MaxStartups 2 #Max concurrent SSH sessions TCPKeepAlive yes Subsystem sftp /usr/lib/openssh/sftp-server #Tunnel -#PermitTunnel no #Only SSH connection and nothing else -#AllowTcpForwarding no #Disablow tunneling out via SSH -#AllowStreamLocalForwarding no #Disablow tunneling out via SSH -#GatewayPorts no #Disablow tunneling out via SSH -#AllowAgentForwarding no #Do not allow agent forwardng +#PermitTunnel no #Only SSH connection and nothing else +#AllowTcpForwarding no #Disablow tunneling out via SSH +#AllowStreamLocalForwarding no #Disablow tunneling out via SSH +#GatewayPorts no #Disablow tunneling out via SSH +#AllowAgentForwarding no #Do not allow agent forwardng + +HostKey /etc/ssh/ssh_host_ed25519_key +HostKey /etc/ssh/ssh_host_rsa_key