Skip to content

Instantly share code, notes, and snippets.

@cmavr8
Last active January 4, 2024 19:52
Show Gist options
  • Star 45 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save cmavr8/eb4a9e596bd0e3e85f97d907de288c54 to your computer and use it in GitHub Desktop.
Save cmavr8/eb4a9e596bd0e3e85f97d907de288c54 to your computer and use it in GitHub Desktop.
Secure SSH configuration ansible playbook. Last updated years ago, NOT recommended for use. There are better ways to do this today.
---
# SSH server settings, in line with https://stribika.github.io/2015/01/04/secure-secure-shell.html
# Before using, change myhosts to your hosts' nickname and myuser to your username (two instances! make sure you replace both or you'll be locked out of ssh!)
- hosts: myhosts
become: true
remote_user: myuser
tasks:
# Key exchange, ciphers and MACs
- lineinfile: dest=/etc/ssh/sshd_config regexp='^KexAlgorithms' line='KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256'
- lineinfile: dest=/etc/ssh/sshd_config regexp='^Ciphers' line='Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr'
# I have removed hmac-ripemd160 and hmac-ripemd160-etm@openssh.com from the following line, as Mozilla's SSH guidelines are stricter and avoid using them. Just to be on the safe side.
- lineinfile: dest=/etc/ssh/sshd_config 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: Enable the most secure server auth algos and protocol version
lineinfile: dest=/etc/ssh/sshd_config regexp='^Protocol 2' line='Protocol 2'
- lineinfile: dest=/etc/ssh/sshd_config regexp='^HostKey /etc/ssh/ssh_host_ed25519_key' line='HostKey /etc/ssh/ssh_host_ed25519_key'
- lineinfile: dest=/etc/ssh/sshd_config regexp='^HostKey /etc/ssh/ssh_host_rsa_key' line='HostKey /etc/ssh/ssh_host_rsa_key'
- name: Disable bad ones
lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^HostKey /etc/ssh/ssh_host_ecdsa_key'
state: absent
- lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^HostKey /etc/ssh/ssh_host_dsa_key'
state: absent
- name: And remove the files
file:
dest: /etc/ssh/ssh_host_ecdsa_key.pub
state: absent
- file:
dest: /etc/ssh/ssh_host_ecdsa_key
state: absent
- file:
dest: /etc/ssh/ssh_host_dsa_key.pub
state: absent
- file:
dest: /etc/ssh/ssh_host_dsa_key
state: absent
- name: Password based logins are disabled - only public key based logins are allowed.
lineinfile: dest=/etc/ssh/sshd_config regexp='^#?AuthenticationMethods' line='AuthenticationMethods publickey'
- lineinfile: dest=/etc/ssh/sshd_config regexp='^#?PasswordAuthentication' line='PasswordAuthentication no'
- lineinfile: dest=/etc/ssh/sshd_config regexp='^#?ChallengeResponseAuthentication' line='ChallengeResponseAuthentication no'
- lineinfile: dest=/etc/ssh/sshd_config regexp='^#?PubkeyAuthentication' line='PubkeyAuthentication yes'
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
- lineinfile: dest=/etc/ssh/sshd_config regexp='^LogLevel' line='LogLevel VERBOSE'
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
- lineinfile: dest=/etc/ssh/sshd_config regexp='^Subsystem sftp' line='Subsystem sftp /usr/lib/openssh/sftp-server -f AUTHPRIV -l INFO'
# Root login is not allowed for auditing reasons. This is because it's difficult to track which process belongs to which root user
# On Linux, user sessions are tracking using a kernel-side session id, however, this session id is not recorded by OpenSSH.
# Additionally, only tools such as systemd and auditd record the process session id.
# On other OSes, the user session id is not necessarily recorded at all kernel-side.
# Using regular users in combination with /bin/su or /usr/bin/sudo ensure a clear audit track.
- lineinfile: dest=/etc/ssh/sshd_config regexp='^PermitRootLogin' line='PermitRootLogin No'
# Use kernel sandbox mechanisms where possible in unprivileged processes
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
- lineinfile: dest=/etc/ssh/sshd_config regexp='^UsePrivilegeSeparation' line='UsePrivilegeSeparation sandbox'
# Only allow specific users to login remotely (may be more suitable to change this to AllowGroups).
- lineinfile: dest=/etc/ssh/sshd_config regexp='^AllowUsers' line='AllowUsers myuser'
# And some client-side, ssh_config modifications
- name: Generic ssh client settings. Includes special settings for Github; it needs diffie-hellman-group-exchange-sha1 some of the time but not always.
blockinfile:
dest: /etc/ssh/ssh_config
block: |
Host *
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
UseRoaming no
Host github.com
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1
- debug:
msg: "If needed, Generate client keys using the following command: ssh-keygen -t ed25519 -o -a 100 && ssh-keygen -t rsa -b 4096 -o -a 100"
@firxworx
Copy link

Thanks for sharing it was interesting to review this. It can be hard to find what someone with a background in security recommends on pretty much anything, especially in such an actionable and usable format such as a set of ansible tasks.

Heads up that OpenSSH 7.6+ on Ubuntu 18.04 LTS says UsePrivilegeSeparation is deprecated with the output of sshd -t: Deprecated option UsePrivilegeSeparation.

I'd also suggest a few small changes to a few regexes. It happens that I'm working on a new AWS LightSail VPS at the moment and the image's sshd_config has 'LogLevel INFO' commented out for example; your regex as-written would fail to catch the line. Also importantly I had a 'Subsystem sftp' line that wasn't commented out but had a tab between 'Subsystem' and 'sftp'. The following regexes would match more universally:

- lineinfile: dest=/etc/ssh/sshd_config regexp='^#?LogLevel' line='LogLevel VERBOSE'
- lineinfile: dest=/etc/ssh/sshd_config regexp='^#?Subsystem[ \t]+sftp' line='Subsystem sftp  /usr/lib/openssh/sftp-server -f AUTHPRIV -l INFO'

It might make sense to do the same start (^#?) for your AllowUsers line as well. For reference, there is no commented out AllowUsers stub in my OS's boilerplate sshd_config, so as-written your regex would suffice but I don't think there's a guarantee that this wouldn't be stubbed out in someone else's config file.

Thanks again for sharing!

@cmavr8
Copy link
Author

cmavr8 commented Jun 2, 2020

Hi @firxworx! I am very sorry to respond so late. I missed the notification before :/

So, thanks so much for the suggestions! To be honest, I haven't updated this gist in a long time, because I'm not using it any more.

Instead, I use templates for the main config files of ssh (ssh_config.j2 and sshs_config.j2) which contain all the things I need, including Mozilla's recommendations. The "lineinfile" system is quite verbose and fragile as you've noticed. Using templates has worked much better.

What could be even better is use modules that someone else wrote, but I don't currently need that level of granularity so I haven't tested that.

Regarding UsePrivilegeSeparation, it's funny that Mozilla have not updated their page to reflect the deprecation, interesting :)

Thanks again for your comments and chat!

@wojciehm
Copy link

@cmavr8 Could you please share your current way of securing sshd_config?

@cmavr8
Copy link
Author

cmavr8 commented Feb 1, 2022

Hey @wojciehm, for private use, I'd just use https://infosec.mozilla.org/guidelines/openssh nowadays.

@wojciehm
Copy link

wojciehm commented Feb 2, 2022

Thanks, @cmavr8 I was more wondering how you implement the rules not which rule. You mentioned templates.

@cmavr8
Copy link
Author

cmavr8 commented Feb 4, 2022

@wojciehm ah ok gotcha. Well I haven't updated my playbooks lately, and I cannot publish them as is right now.

So you'd have to look into Ansible templating or search through Galaxy to find someone else's solution you can re-use. Github seems to have a few too, but none references Mozilla's guidelines directly.

Sorry I can't be of more help! :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment