diff --git a/roles/ssh_hardening/README.md b/roles/ssh_hardening/README.md index 059db9a3e..9805f6245 100644 --- a/roles/ssh_hardening/README.md +++ b/roles/ssh_hardening/README.md @@ -136,7 +136,7 @@ Warning: This role disables root-login on the target server! Please make sure yo - Description: `true` to allow password-based authentication with the ssh client - `ssh_server_password_login` - Default: `false` - - Description: `true` to allow password-based authentication with the ssh server + - Description: `true` to allow password-based authentication to the ssh server. You probably also need to change `sshd_authenticationmethods` to include `password` if you set `ssh_server_password_login`: `true` - `ssh_banner` - Default: `false` - Description: `true` to print a banner on login diff --git a/roles/ssh_hardening/templates/openssh.conf.j2 b/roles/ssh_hardening/templates/openssh.conf.j2 index c26957eae..0b9dfe83a 100644 --- a/roles/ssh_hardening/templates/openssh.conf.j2 +++ b/roles/ssh_hardening/templates/openssh.conf.j2 @@ -2,7 +2,7 @@ {{ ansible_managed | comment }} # This is the ssh client system-wide configuration file. -# See ssh_config(5) for more information on any settings used. Comments will be added only to clarify why a configuration was chosen. +# See ssh_config(5) for more information on any settings used. {% if ssh_custom_options %} # Custom configuration that overwrites default configuration @@ -26,14 +26,14 @@ Host {{ host.names | join(' ') }} {{ host.options | join('\n') | indent(2) }} {% endfor %} - # Global defaults for all Hosts Host * # The port at the destination should be defined Port {{ ssh_client_port }} -# Identity file configuration. You may restrict available identity files. Otherwise ssh will search for a pattern and use any that matches. +# Identity file configuration. You may restrict available identity files. +# Otherwise ssh will search for a pattern and use any that matches. #IdentityFile ~/.ssh/identity #IdentityFile ~/.ssh/id_rsa #IdentityFile ~/.ssh/id_dsa @@ -42,9 +42,12 @@ Port {{ ssh_client_port }} # Security configuration # ====================== -# Set the protocol version to 2 for security reasons. Disables legacy support. +{# Support for legacy SSHv1 has been completely removed from OpenSSH in version 7.6 -#} +{% if sshd_version is version('7.6', '<') %} +# Set the protocol version explicitly to 2. Version 1 is obsolete and should not be used. Protocol 2 +{% endif %} # Make sure passphrase querying is enabled BatchMode no @@ -54,35 +57,34 @@ CheckHostIP yes # Always ask before adding keys to the `known_hosts` file. Do not set to `yes`. StrictHostKeyChecking ask - # **Ciphers** -- If your clients don't support CTR (eg older versions), cbc will be added # CBC: is true if you want to connect with OpenSSL-base libraries # eg ruby Net::SSH::Transport::CipherFactory requires cbc-versions of the given openssh ciphers to work # -- see: (http://net-ssh.github.com/net-ssh/classes/Net/SSH/Transport/CipherFactory.html) # - -{# This outputs 'Ciphers ' if ssh_ciphers is defined or '#Ciphers' if ssh_ciphers is undefined #} +{# This outputs 'Ciphers ' if ssh_ciphers is defined or '#Ciphers' if ssh_ciphers is undefined -#} {{ 'Ciphers ' ~ ssh_ciphers|join(',') if ssh_ciphers else 'Ciphers'|comment }} # **Hash algorithms** -- Make sure not to use SHA1 for hashing, unless it is really necessary. # Weak HMAC is sometimes required if older package versions are used # eg Ruby's Net::SSH at around 2.2.* doesn't support sha2 for hmac, so this will have to be set true in this case. # - -{# This outputs 'MACs ' if ssh_macs is defined or '#MACs' if ssh_macs is undefined #} +{# This outputs 'MACs ' if ssh_macs is defined or '#MACs' if ssh_macs is undefined -#} {{ 'MACs ' ~ ssh_macs|join(',') if ssh_macs else 'MACs'|comment }} -# Alternative setting, if OpenSSH version is below v5.9 -#MACs hmac-ripemd160 - # **Key Exchange Algorithms** -- Make sure not to use SHA1 for kex, unless it is really necessary # Weak kex is sometimes required if older package versions are used # eg ruby's Net::SSH at around 2.2.* doesn't support sha2 for kex, so this will have to be set true in this case. # based on: https://bettercrypto.org/static/applied-crypto-hardening.pdf - +# {# This outputs 'KexAlgorithms ' if ssh_kex is defined or '#KexAlgorithms' if ssh_kex is undefined #} {{ 'KexAlgorithms ' ~ ssh_kex|join(',') if ssh_kex else 'KexAlgorithms'|comment }} +{% if sshd_version is version('5.9', '<') %} +# Alternative setting, if OpenSSH version is below v5.9 +#MACs hmac-ripemd160 + +{% endif %} # Disable agent forwarding, since local agent could be accessed through forwarded connection. ForwardAgent no @@ -120,6 +122,7 @@ Compression {{ 'yes' if (ssh_client_compression|bool) else 'no' }} #VisualHostKey yes {% if sshd_version is version('7.1', '<=') %} -# Disable experimental client roaming. This is known to cause potential issues with secrets being disclosed to malicious servers and defaults to being disabled. +# Disable experimental client roaming. +# This is known to cause potential issues with secrets being disclosed to malicious servers. Disabled by default. UseRoaming {{ 'yes' if ssh_client_roaming else 'no' }} {% endif %} diff --git a/roles/ssh_hardening/templates/opensshd.conf.j2 b/roles/ssh_hardening/templates/opensshd.conf.j2 index c52816330..1deefa441 100644 --- a/roles/ssh_hardening/templates/opensshd.conf.j2 +++ b/roles/ssh_hardening/templates/opensshd.conf.j2 @@ -45,9 +45,12 @@ HostKey {{ key }} # Security configuration # ====================== +{# Support for legacy SSHv1 has been completely removed from OpenSSH in version 7.6 -#} +{% if sshd_version is version('7.6', '<') %} # Set the protocol version explicitly to 2. Version 1 is obsolete and should not be used. Protocol 2 +{% endif %} # Make sure sshd checks file modes and ownership before accepting logins. This prevents accidental misconfiguration. StrictModes {{ 'yes' if (sshd_strict_modes|bool) else 'no' }} @@ -63,26 +66,26 @@ LogLevel {{ sshd_log_level }} # eg ruby Net::SSH::Transport::CipherFactory requires cbc-versions of the given openssh ciphers to work # -- see: (http://net-ssh.github.com/net-ssh/classes/Net/SSH/Transport/CipherFactory.html) # - -{# This outputs 'Ciphers ' if ssh_ciphers is defined or '#Ciphers' if ssh_ciphers is undefined #} +{# This outputs 'Ciphers ' if ssh_ciphers is defined or '#Ciphers' if ssh_ciphers is undefined -#} {{ 'Ciphers ' ~ ssh_ciphers|join(',') if ssh_ciphers else 'Ciphers'|comment }} # **Hash algorithms** -- SHA-1 is formally deprecated by NIST in 2011 because of security issues. # Weak HMAC is sometimes required if older package versions are used # eg Ruby's Net::SSH at around 2.2.* doesn't support sha2 for hmac, so this will have to be set true in this case. # - -{# This outputs 'MACs ' if ssh_macs is defined or '#MACs' if ssh_macs is undefined #} +{# This outputs 'MACs ' if ssh_macs is defined or '#MACs' if ssh_macs is undefined -#} {{ 'MACs ' ~ ssh_macs|join(',') if ssh_macs else 'MACs'|comment }} +{% if sshd_version is version('5.9', '<') %} # Alternative setting, if OpenSSH version is below v5.9 #MACs hmac-ripemd160 +{% endif %} # **Key Exchange Algorithms** -- SHA-1 is formally deprecated by NIST in 2011 because of security issues. # Weak kex is sometimes required if older package versions are used # eg ruby's Net::SSH at around 2.2.* doesn't support sha2 for kex, so this will have to be set true in this case. # based on: https://bettercrypto.org/static/applied-crypto-hardening.pdf - +# {# This outputs 'KexAlgorithms ' if ssh_kex is defined or '#KexAlgorithms' if ssh_kex is undefined #} {{ 'KexAlgorithms ' ~ ssh_kex|join(',') if ssh_kex else 'KexAlgorithms'|comment }} @@ -114,17 +117,17 @@ IgnoreRhosts yes IgnoreUserKnownHosts yes HostbasedAuthentication no -# Enable PAM to enforce system wide rules. {% if ssh_pam_support %} +# Enable PAM to enforce system wide rules. UsePAM {{ 'yes' if (ssh_use_pam|bool) else 'no' }} -{% endif %} -# Set AuthenticationMethods per default to publickey -# AuthenticationMethods was introduced in OpenSSH 6.2 - https://www.openssh.com/txt/release-6.2 +{% endif %} +{# Set AuthenticationMethods per default to publickey -#} +{# AuthenticationMethods was introduced in OpenSSH 6.2 - https://www.openssh.com/txt/release-6.2 -#} {% if sshd_version is version('6.2', '>=') %} AuthenticationMethods {{ sshd_authenticationmethods }} -{% endif %} +{% endif %} # Disable password-based authentication, it can allow for potentially easier brute-force attacks. PasswordAuthentication {{ 'yes' if (ssh_server_password_login|bool) else 'no' }} PermitEmptyPasswords no @@ -142,28 +145,28 @@ KerberosTicketCleanup yes GSSAPIAuthentication {{ 'yes' if ssh_gssapi_support else 'no' }} GSSAPICleanupCredentials yes +{% if ssh_deny_users %} # In case you don't use PAM (`UsePAM no`), you can alternatively restrict users and groups here. # For key-based authentication this is not necessary, since all keys must be explicitely enabled. -{% if ssh_deny_users %} DenyUsers {{ ssh_deny_users }} -{% endif %} +{% endif %} {% if ssh_allow_users %} AllowUsers {{ ssh_allow_users }} -{% endif %} +{% endif %} {% if ssh_deny_groups %} DenyGroups {{ ssh_deny_groups }} -{% endif %} +{% endif %} {% if ssh_allow_groups %} AllowGroups {{ ssh_allow_groups }} -{% endif %} +{% endif %} {% if ssh_authorized_keys_file %} AuthorizedKeysFile {{ ssh_authorized_keys_file }} -{% endif %} +{% endif %} {% if ssh_trusted_user_ca_keys_file %} TrustedUserCAKeys {{ ssh_trusted_user_ca_keys_file }} {% if ssh_authorized_principals_file %} @@ -178,7 +181,8 @@ AuthorizedPrincipalsFile {{ ssh_authorized_principals_file }} TCPKeepAlive no # Manage `ClientAlive..` signals via interval and maximum count. -# This will periodically check up to a `..CountMax` number of times within `..Interval` timeframe, and abort the connection once these fail. +# This will periodically check up to a `..CountMax` number of times within `..Interval` timeframe, +# and abort the connection once these fail. ClientAliveInterval {{ ssh_client_alive_interval }} ClientAliveCountMax {{ ssh_client_alive_count }} @@ -238,8 +242,8 @@ Banner {{ ssh_banner_path if (ssh_banner|bool) else 'none' }} {% if ansible_facts.os_family == 'Debian' %} DebianBanner {{ 'yes' if (ssh_print_debian_banner|bool) else 'no' }} -{% endif %} +{% endif %} # Reject keys that are explicitly blacklisted RevokedKeys /etc/ssh/revoked_keys