Introduction
Securing your SSH configurations across multiple servers can be efficiently managed using Ansible. In this guide, we will walk you through a comprehensive Ansible playbook designed to harden SSH configurations, ensuring your servers are protected against common vulnerabilities.
Why Harden SSH?
Hardening SSH configurations is essential to protect against unauthorized access and ensure secure communications. Key steps include disabling root login, enforcing key-based authentication, and setting strong encryption algorithms.
Ansible Playbook for SSH Hardening
Below is an Ansible playbook that automates the process of hardening SSH configurations on your servers.
---
- hosts: ubuntu
gather_facts: yes
become: true
become_method: su
become_user: root
tasks:
- name: Ensure the SSH configuration file has the correct permissions
file:
path: /etc/ssh/sshd_config
owner: root
group: root
mode: '0600'
- name: Backup the original SSH configuration file
copy:
src: /etc/ssh/sshd_config
dest: /etc/ssh/sshd_config.bak
owner: root
group: root
mode: '0600'
- name: Hardening sshd
block:
- name: Editing sshd config
lineinfile:
dest: "/etc/ssh/sshd_config"
regexp: "{{ item.regexp | default(omit) }}"
line: "{{ item.line }}"
state: "{{ item.state | default('present') }}"
validate: "sshd -t -f %s"
with_items:
- line: "Protocol 2"
- line: "Protocol 1"
state: "absent"
- line: "RSAAuthentication yes"
state: "absent"
- regexp: "^Port\ "
line: "Port {{ ssh_port }}"
- regexp: "^PermitRootLogin\ "
line: "PermitRootLogin no"
- regexp: "^PasswordAuthentication\ "
line: "PasswordAuthentication no"
- regexp: "^PermitEmptyPasswords\ "
line: "PermitEmptyPasswords no"
- regexp: "^StrictModes\ "
line: "StrictModes yes"
- regexp: "^IgnoreRhosts\ "
line: "IgnoreRhosts yes"
- regexp: "^RhostsAuthentication\ "
line: "RhostsAuthentication no"
- regexp: "^RhostsRSAAuthentication\ "
line: "RhostsRSAAuthentication no"
- regexp: "^ClientAliveInterval\ "
line: "ClientAliveInterval 300"
- regexp: "^ClientAliveCountMax\ "
line: "ClientAliveCountMax 0"
- regexp: "^AllowTcpForwarding\ "
line: "AllowTcpForwarding no"
- regexp: "^X11Forwarding\ "
line: "X11Forwarding no"
- regexp: "^KexAlgorithms\ "
line: "KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256"
- regexp: "^Ciphers\ "
line: "Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr"
- regexp: "^MACs\ "
line: "MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com"
- name: Reload sshd
service:
name: sshd
state: reloaded
This playbook uses the lineinfile module with Ansible variables loaded in from the with_items. It parses through every line in the with_items section and changes the value in the sshd_config according the regular expression. The last step reloads the sshd daemon to finalize the settings.
The settings used are:
- Change protocol version to 2 to allow better cipher suites.
- Removes RSAAuthentication which is deprecated.
- Changes the SSH port to the set variable.
- Sets PermitRootLogin to no. This disables direct root login via SSH.
- Sets PasswordAuthentication to no. This only allows key based logins.
- Sets PermitEmptyPasswords to no. This disables to use of empty passwords.
- Enables Strictmode. This enables checks on the daemon before starting up SSH. For example file permissions. If the settings are wrong. The SSH services does not start.
- Disables multiple RHosts ettings. This disables the use of .rhosts file to connect.
- Sets ClientAlive settings. Drops idle connections after set time.
- Sets AllowTcpForwarding to no. This disables the use of tcp forwarding via SSH.
- Sets X11Forwarding to no. This disables to use of X11 forwarding via SSH.
- Sets optimal cipher suites to use for the connection.
Conclusion
Using this Ansible playbook ensures your servers adhere to a secure SSH configuration policy, reducing the risk of unauthorized access. Regularly review and update your security policies to adapt to emerging threats. For more information on deploying SSH keys with Ansible, check out our Configuring Linux Users and SSH Keys with Ansible post.
Feel free to leave a comment.
This playbook doesn’t appear to be idempotent and can’t be run on the same system again
Works fine on my servers.
As this script is altering the content of the SSH configuration file you can’t rerun the same script as it won’t find the required regex patterns.
With the regex it looks for the line and skips it if already matches the desired state. So it works fine.