Security/Guidelines/OpenSSH: Difference between revisions
Gdestuynder (talk | contribs) (re-add AES-GCM) |
Gdestuynder (talk | contribs) (Automated sync from https://github.com/mozilla/wikimo_content) |
||
(24 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
<table> | |||
<tr> | |||
<td style="min-width: 25em;">__TOC__</td> | |||
<td style="vertical-align: top; padding-left: 1em;"> | |||
'''STATUS: <span style="background-color: #14892c; border-radius: .25em; color: #ffffff; display: inline-block; | |||
font-weight: bold; margin: .1em 0; min-width: 6em; padding: .05em .5em; text-transform: uppercase; text-align: | |||
center;">READY</span>''' | |||
The goal of this document is to help operational teams with the configuration of OpenSSH server and client. All Mozilla | |||
sites and deployment should follow the recommendations below. | |||
The Enterprise Information Security (Infosec, formerly OpSec) team maintains this document as a reference guide for operational teams. | |||
Updates to this page should be submitted to the [https://github.com/mozilla/wikimo_opsec/ source repository on github]. | |||
Changes are detailed in the [https://github.com/mozilla/wikimo_opsec/commits/master commit history]. | |||
<span style="float: right; padding-top: 3em;">[[File:OpSec.png|300px]]</span> | |||
</td> | |||
</tr> | |||
</table> | |||
[[File:OpSec.png | |||
</td> | |||
</tr></table> | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! <span style="color:red;">'''ATTENTION'''</span> | ! <span style="color:red;">'''ATTENTION'''</span> | ||
|- | |- | ||
| | | | ||
'''Only non-default settings are listed in this document'''. | '''Only non-default settings are listed in this document'''. | ||
Most default OpenSSH settings that are security-related already provide good security, thus changing them is at your own risk and is not documented here. | Most default OpenSSH settings that are security-related already provide good security, thus changing them is at your own risk and is not documented here. | ||
For example, these guidelines assume only SSH protocol 2 is configured in the server, and SSH protocol 1 is disabled. | |||
See <code>man sshd_config</code>, <code>man ssh_config</code> for more information on specific settings if you nevertheless need to change them. | See <code>man sshd_config</code>, <code>man ssh_config</code> for more information on specific settings if you nevertheless need to change them. | ||
Line 39: | Line 36: | ||
== Configuration == | == Configuration == | ||
Different versions of OpenSSH support different options which are not always compatible. | Different versions of OpenSSH support different options which are not always compatible. | ||
This guide | This guide shows settings for the most commonly deployed OpenSSH versions at Mozilla - however, using the latest version of OpenSSH is recommended. | ||
=== '''Modern''' (OpenSSH 6.7+) === | === '''Modern''' (OpenSSH 6.7+) === | ||
Line 55: | Line 52: | ||
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 | 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 | ||
# Password based logins are disabled - only public key based logins are allowed. | # Password based logins are disabled - only public key based logins are allowed. | ||
Line 64: | Line 58: | ||
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in. | # LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in. | ||
LogLevel VERBOSE | LogLevel VERBOSE | ||
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise. | |||
Subsystem sftp /usr/lib/ssh/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: | # 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. | # 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. | # Additionally, only tools such as systemd and auditd record the process session id. | ||
Line 73: | Line 70: | ||
PermitRootLogin No | PermitRootLogin No | ||
# Use kernel sandbox mechanisms where possible in | # Use kernel sandbox mechanisms where possible in unprivileged processes | ||
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere. | # Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere. | ||
UsePrivilegeSeparation sandbox | UsePrivilegeSeparation sandbox | ||
</source> | </source> | ||
File: <code>/etc/ssh/moduli</code> | |||
All Diffie-Hellman moduli in use should be at least 3072-bit-long (they are used for <code>diffie-hellman-group-exchange-sha256</code>) as per our [[Security/Guidelines/Key_Management]] recommendations. See also <code>man moduli</code>. | |||
To deactivate short moduli in two commands: <code>awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv /etc/ssh/moduli.tmp /etc/ssh/moduli</code> | |||
=== '''Intermediate''' (OpenSSH 5.3) === | === '''Intermediate''' (OpenSSH 5.3) === | ||
Line 91: | Line 95: | ||
MACs hmac-sha2-512,hmac-sha2-256 | MACs hmac-sha2-512,hmac-sha2-256 | ||
Ciphers aes256-ctr,aes192-ctr,aes128-ctr | Ciphers aes256-ctr,aes192-ctr,aes128-ctr | ||
# Password based logins are disabled - only public key based logins are allowed. | # Password based logins are disabled - only public key based logins are allowed. | ||
Line 105: | Line 106: | ||
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in. | # LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in. | ||
LogLevel VERBOSE | LogLevel VERBOSE | ||
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise. | |||
Subsystem sftp /usr/lib/ssh/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: | # 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. | # 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. | # Additionally, only tools such as systemd and auditd record the process session id. | ||
Line 114: | Line 118: | ||
PermitRootLogin No | PermitRootLogin No | ||
</source> | </source> | ||
File: <code>/etc/ssh/moduli</code> | |||
All Diffie-Hellman moduli in use should be at least 2048-bit-long. From the structure of <code>moduli</code> files, this means the fifth field of all lines in this file should be greater than or equal to 2047. | |||
To deactivate weak moduli in two commands: <code>awk '$5 >= 2047' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv /etc/ssh/moduli.tmp /etc/ssh/moduli</code> | |||
=== '''Multi-Factor Authentication''' (OpenSSH 6.3+) === | === '''Multi-Factor Authentication''' (OpenSSH 6.3+) === | ||
Line 123: | Line 133: | ||
|- | |- | ||
! <span style="color:red;">'''ATTENTION'''</span> | ! <span style="color:red;">'''ATTENTION'''</span> | ||
|- | |- | ||
| In order to allow using one time passwords (OTPs) and any other text input, Keyboard-interactive is enabled in OpenSSH. This ''MAY'' allow for password authentication to work. It is therefore very important to check your PAM configuration so that PAM disallow password authentication for OpenSSH. | | In order to allow using one time passwords (OTPs) and any other text input, Keyboard-interactive is enabled in OpenSSH. This ''MAY'' allow for password authentication to work. It is therefore very important to check your PAM configuration so that PAM disallow password authentication for OpenSSH. | ||
|} | |} | ||
==== OpenSSH 6.3+ (default) ==== | |||
File: <code>/etc/ssh/sshd_config</code> | |||
<source> | |||
# IMPORTANT: you will have to ensure OpenSSH cannot authenticate with passwords with PAM in /etc/pam.d/sshd | |||
# "PasswordAuthentication no" is not sufficient! | |||
PubkeyAuthentication yes | |||
PasswordAuthentication no | |||
AuthenticationMethods publickey,keyboard-interactive:pam | |||
KbdInteractiveAuthentication yes | |||
UsePAM yes | |||
# Ensure /bin/login is not used so that it cannot bypass PAM settings for sshd. | |||
UseLogin no | |||
</source> | |||
==== OpenSSH 5.3+ w/ RedHat/CentOS patch (old) ==== | |||
File: <code>/etc/ssh/sshd_config</code> | File: <code>/etc/ssh/sshd_config</code> | ||
<source> | <source> | ||
Line 135: | Line 160: | ||
PasswordAuthentication no | PasswordAuthentication no | ||
ChallengeResponseAuthentication yes | ChallengeResponseAuthentication yes | ||
UsePAM yes | |||
# Ensure /bin/login is not used so that it cannot bypass PAM settings for sshd. | # Ensure /bin/login is not used so that it cannot bypass PAM settings for sshd. | ||
UseLogin no | UseLogin no | ||
</source> | </source> | ||
PAM configuration for use with the [ | PAM configuration for use with the [https://www.nongnu.org/oath-toolkit/ OATH Toolkit] or [https://www.duosecurity.com DuoSecurity] as second authentication factor. | ||
File: <code>/etc/pam.d/sshd</code> | File: <code>/etc/pam.d/sshd</code> | ||
Line 162: | Line 188: | ||
* When CHACHA20 (OpenSSH 6.5+) is not available, AES-GCM (OpenSSH 6.1+) and any other algorithm using EtM (Encrypt then MAC) [http://blog.djm.net.au/2013/11/chacha20-and-poly1305-in-openssh.html disclose the packet length] - giving some information to the attacker. Only recent OpenSSH servers and client support CHACHA20. | * When CHACHA20 (OpenSSH 6.5+) is not available, AES-GCM (OpenSSH 6.1+) and any other algorithm using EtM (Encrypt then MAC) [http://blog.djm.net.au/2013/11/chacha20-and-poly1305-in-openssh.html disclose the packet length] - giving some information to the attacker. Only recent OpenSSH servers and client support CHACHA20. | ||
* NIST curves (<code>ecdh-sha2-nistp512,ecdh-sha2-nistp384,ecdh-sha2-nistp256</code>) are listed for compatibility, but the use of <code>curve25519</code> is [ | * NIST curves (<code>ecdh-sha2-nistp512,ecdh-sha2-nistp384,ecdh-sha2-nistp256</code>) are listed for compatibility, but the use of <code>curve25519</code> is [https://safecurves.cr.yp.to/ generally preferred]. | ||
* SSH protocol 2 supports [https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange DH] and [https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman ECDH] key-exchange as well as [https://en.wikipedia.org/wiki/Forward_secrecy forward secrecy]. | * SSH protocol 2 supports [https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange DH] and [https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman ECDH] key-exchange as well as [https://en.wikipedia.org/wiki/Forward_secrecy forward secrecy]. Regarding group sizes, please refer to [[Security/Guidelines/Key_Management]]. | ||
The various algorithms supported by a particular OpenSSH version can be listed with the following commands: | The various algorithms supported by a particular OpenSSH version can be listed with the following commands: | ||
Line 191: | Line 217: | ||
HashKnownHosts yes | HashKnownHosts yes | ||
# Host keys the client accepts - order here is honored by OpenSSH | # Host keys the client accepts - order here is honored by OpenSSH | ||
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01 | HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256 | ||
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2- | KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 | ||
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 | 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 | ||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr | Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr | ||
</source> | </source> | ||
Line 207: | Line 232: | ||
HashKnownHosts yes | HashKnownHosts yes | ||
# Host keys the client accepts - order here is honored by OpenSSH | # Host keys the client accepts - order here is honored by OpenSSH | ||
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01 | HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256 | ||
</source> | </source> | ||
== Key generation == | == Key generation == | ||
Large key sizes are used as SSH keys are not renewed very often (see also [[Security/Key_Management]]). | Large key sizes are used as SSH keys are not renewed very often (see also [[Security/Key_Management]]). | ||
{{note| | |||
DSA and RSA 1024 bit (or lower) keys are considered weak and should be replaced as soon as possible. | |||
}} | |||
Don't hesitate to create multiple different keys for different usages. | Don't hesitate to create multiple different keys for different usages. In particular, never mix your personal and | ||
Mozilla keys. | |||
<source code="bash"> | <source code="bash"> | ||
# ED25519 keys are favored over RSA keys when backward compatibility is not required. | # RSA keys are favored over ECDSA keys when backward compatibility ''is required'', | ||
# This is only compatible with OpenSSH 5 | # thus, newly generated keys are always either ED25519 or RSA (NOT ECDSA or DSA). | ||
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_mozilla_$(date +%Y-%m-%d) -C "Mozilla key for xyz" | |||
# ED25519 keys are favored over RSA keys when backward compatibility ''is not required''. | |||
# This is only compatible with OpenSSH 6.5+ and fixed-size (256 bytes). | |||
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_mozilla_$(date +%Y-%m-%d) -C "Mozilla key for xyz" | $ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_mozilla_$(date +%Y-%m-%d) -C "Mozilla key for xyz" | ||
</source> | |||
You may then want to add the new key to your SSH agent or your configuration file (or both). | |||
<source code="bash"> | |||
# Add key to ssh-agent | |||
$ ssh-add ~/.ssh/id_..._mozilla... # <= replace by your key's path | |||
</source> | |||
# | <source> | ||
# Add configuration to ~/.ssh/config | |||
host *.mozilla.com | |||
IdentityFile ~/.ssh/id_...mozilla... # <= replace by your key's path | |||
</source> | </source> | ||
Line 235: | Line 278: | ||
* Usage of machine keys should be registered in an inventory (a wiki page, ldap, an inventory database), to allow for rapid auditing of key usage across an infrastructure. | * Usage of machine keys should be registered in an inventory (a wiki page, ldap, an inventory database), to allow for rapid auditing of key usage across an infrastructure. | ||
* The machine keys should be unique per usage. Each new usage (different service, different script called, etc.) should use a new, different key. | * The machine keys should be unique per usage. Each new usage (different service, different script called, etc.) should use a new, different key. | ||
* Only used when strictly necessary. | |||
* Restrict privileges of the account (i.e. no root or "sudoer" machine account). | |||
* Using a ForceCommand returning only the needed results, or only allowing the machine to perform SSH-related tasks such as tunneling is prefered. | |||
* Disable sftp if not needed as it exposes more surface and different logging mechanisms than SSH (and thus scp) itself. | |||
{{note| | |||
You may want to use the group "users" instead of "sftpusers" in the example below as this may already exist and include all regular users by | |||
default. | |||
}} | |||
<source code="bash"> | |||
# groupadd sftpusers | |||
# usermod -a -g sftpusers <userthat_needs_ftp> | |||
# chgrp sftpusers /usr/lib/ssh/sftp-server | |||
# chmod 0750 /usr/lib/ssh/sftp-server | |||
</source> | |||
==== Multi-factor bypass setup for machine keys ==== | |||
Machine keys do not play well with multi-factor authentication as there is no human interaction. | |||
* All logins from machine accounts should be protected by an additional authentication layer (VPN, another machine, etc.). | |||
* All logins from machine accounts are only allowed within the private IP-space, and if possible, only the relevant machine source IPs should be accessible. | |||
File: <code>/etc/ssh/sshd_config</code> (OpenSSH 6.3+) | |||
<source> | |||
Match User machine_user Address 10.0.0.0/8,192.168.0.0/16,172.16.0.0/12 | |||
PubkeyAuthentication yes | |||
KbdInteractiveAuthentication no | |||
AuthenticationMethods publickey | |||
</source> | |||
File: <code>/etc/ssh/sshd_config</code> (OpenSSH 5.3+ w/ RedHat/CentOS patch) | |||
<source> | |||
Match User machine_user Address 10.0.0.0/8,192.168.0.0/16,172.16.0.0/12 | |||
RequiredAuthentications2 publickey | |||
</source> | |||
=== Auditing your existing SSH keys === | |||
Existing keys are generally stored in <code>~/.ssh/</code> (Linux/OSX) or <code>%APPDATA%</code> (Windows). | |||
Look for <code>id_{rsa,ed25519,ecdsa,dsa}, identity, IdentityFile, *.pem</code>, and other <code>identity</code> files. | |||
==== Display SSH keys information ==== | |||
<source code="bash"> | |||
# You may run this for any key file that you have. | |||
$ ssh-keygen -lf id_rsa | |||
2048 bc:4f:46:2b:3d:f1:e2:0f:ac:40:99:49:ed:c9:81:a2 Mozilla key for xyz (RSA) | |||
^^ ^^^^^^^^^ ^^^^ ^^^ | |||
|__ Size |__ Fingerprint |__ Comment |__ Type | |||
</source> | |||
== SSH agent forwarding == | == SSH agent forwarding == | ||
Line 240: | Line 333: | ||
|- | |- | ||
! <span style="color:red;">'''ATTENTION'''</span> | ! <span style="color:red;">'''ATTENTION'''</span> | ||
|- | |- | ||
| SSH Agent forwarding exposes your authentication to the server you're connecting to. By default, an attacker with control of the server (i.e. root access) can communicate with your agent and use your key to authenticate to other servers without any notification (i.e. impersonate you).<br />For this reason, one must be careful when using SSH agent forwarding. Defaulting to always forwarding the agent is strongly discouraged.<br /> Note also that while the attacker can use your key as long as the agent is running and forwarded, he cannot steal/download the key for offline/later use. | | SSH Agent forwarding exposes your authentication to the server you're connecting to. By default, an attacker with control of the server (i.e. root access) can communicate with your agent and use your key to authenticate to other servers without any notification (i.e. impersonate you).<br />For this reason, one must be careful when using SSH agent forwarding. Defaulting to always forwarding the agent is strongly discouraged.<br /> Note also that while the attacker can use your key as long as the agent is running and forwarded, he cannot steal/download the key for offline/later use. | ||
|} | |} | ||
Line 285: | Line 378: | ||
# Re-add it, with the -t flag to keep this specific key decrypted/useable in memory for 30 minutes (1800 seconds) | # Re-add it, with the -t flag to keep this specific key decrypted/useable in memory for 30 minutes (1800 seconds) | ||
$ ssh-add -t 1800 ~/.ssh/id_ed25519 | $ ssh-add -t 1800 ~/.ssh/id_ed25519 | ||
</source> | |||
For MacOSX in particular it's possible to save the passphrase in the Keychain. If you do so it is strongly recommended | |||
to also change the keychain setting to lock itself when the computer is locked, and/or to timeout and lock the keychain. | |||
These settings are not controlled by OpenSSH. | |||
<source code="bash"> | |||
# MacOSX only - save the passphrase in the Keychain | |||
$ ssh-add -K ~/.ssh/id_ed25519 | |||
</source> | </source> | ||
Line 293: | Line 395: | ||
* [https://github.com/gdestuynder/openssh-portable/commits/libnotify OpenSSH Linux] | * [https://github.com/gdestuynder/openssh-portable/commits/libnotify OpenSSH Linux] | ||
* [https://github.com/gdestuynder/putty-pagent-notification/commits/master PuTTY/ | * [https://github.com/gdestuynder/putty-pagent-notification/commits/master PuTTY/Pageant] | ||
* [https://github.com/gdestuynder/gnupg-agent-notification/commit/57697146188d52f5447a50303070371a8cf5c0bb GnuPG Agent Linux] | * [https://github.com/gdestuynder/gnupg-agent-notification/commit/57697146188d52f5447a50303070371a8cf5c0bb GnuPG Agent Linux] | ||
* [https://github.com/devinteske/apple/tree/master/OpenSSH-186/openssh OpenSSH MacOS X] (see also http://devinteske.com/) | * [https://github.com/devinteske/apple/tree/master/OpenSSH-186/openssh OpenSSH MacOS X] (see also http://devinteske.com/) | ||
}} | }} | ||
=== | === Recommended, safer alternatives to SSH agent forwarding === | ||
==== OpenSSH >=7.3 ==== | |||
OpenSSH 7.3 onwards allow users to jump through several hosts in a rather automated fashion. It has full support for | |||
scp and sftp commands as well as regular ssh. | |||
For example to reach a host behind a bastion/jumphost: | |||
<source code="bash"> | |||
# Single jump | |||
$ ssh -J ssh.mozilla.com myhost.private.scl3.mozilla.com | |||
# Jump through 2 hops | |||
$ ssh -J ssh.mozilla.com,ec2-instance.aws.net 10.0.0.3 | |||
# Copy data from a host | |||
$ scp -oProxyJump=ssh.mozilla.com myhost.private.scl3.mozilla.com:/home/kang/testfile ./ | |||
</source> | |||
You can also add these lines to your <code>~/.ssh/config</code> | |||
<source> | |||
Host *.mozilla.com !ssh.mozilla.com | |||
ProxyJump ssh.mozilla.com | |||
</source> | |||
==== Older versions of OpenSSH ==== | |||
It is possible to directly forward ports for single jumps instead of forwarding the agent. This has the advantage of never exposing your agent to the servers you're connecting to. | It is possible to directly forward ports for single jumps instead of forwarding the agent. This has the advantage of never exposing your agent to the servers you're connecting to. | ||
Line 304: | Line 432: | ||
For example, you can add these lines to your <code>~/.ssh/config</code> | For example, you can add these lines to your <code>~/.ssh/config</code> | ||
<source> | <source> | ||
Host *.mozilla.com | Host *.mozilla.com !ssh.mozilla.com | ||
ProxyCommand ssh ssh.mozilla.com -W %h:%p | ProxyCommand ssh ssh.mozilla.com -W %h:%p | ||
</source> | </source> | ||
Line 319: | Line 447: | ||
* OpenSSH server keys (<code>/etc/ssh/ssh_host_*key</code>) | * OpenSSH server keys (<code>/etc/ssh/ssh_host_*key</code>) | ||
* Client keys (<code>~/.ssh/id_{rsa,dsa,ecdsa,ed25519}</code> and <code>~/.ssh/identity</code>). | * Client keys (<code>~/.ssh/id_{rsa,dsa,ecdsa,ed25519}</code> and <code>~/.ssh/identity</code>). | ||
== Client key size and login latency == | == Client key size and login latency == | ||
Line 337: | Line 464: | ||
| RSA 4096 || 120ms || 145ms || 127ms | | RSA 4096 || 120ms || 145ms || 127ms | ||
|- | |- | ||
| RSA 2048 || | | RSA 2048 || 120ms || 129ms || 127ms | ||
|- | |- | ||
| ed25519 || 117ms || 138ms || 120ms | | ed25519 || 117ms || 138ms || 120ms | ||
Line 349: | Line 476: | ||
* [https://wiki.mozilla.org/Security/Key_Management Key Management] | * [https://wiki.mozilla.org/Security/Key_Management Key Management] | ||
* [https://wiki.mozilla.org/Security/Server_Side_TLS Server Side TLS] | * [https://wiki.mozilla.org/Security/Server_Side_TLS Server Side TLS] | ||
* [ | * [https://www.ietf.org/rfc/rfc4418.txt RFC4418 (umac)] | ||
* [http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt umac draft] | * [http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt umac draft] | ||
* [ | * [https://safecurves.cr.yp.to/ Safe curves] | ||
* [http://blog.djm.net.au/2013/11/chacha20-and-poly1305-in-openssh.html DJM blog] | * [http://blog.djm.net.au/2013/11/chacha20-and-poly1305-in-openssh.html DJM blog] | ||
* [https://stribika.github.io/2015/01/04/secure-secure-shell.html Stribika blog] | * [https://stribika.github.io/2015/01/04/secure-secure-shell.html Stribika blog] | ||
* [http://2013.diac.cr.yp.to/slides/gueron.pdf AES-GCM performance study] | * [http://2013.diac.cr.yp.to/slides/gueron.pdf AES-GCM performance study] | ||
* [ | * [https://security.googleblog.com/2014/04/speeding-up-and-strengthening-https.html CHACHA20 vs AES-GCM performance study] | ||
* [http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/ssh/PROTOCOL.certkeys?rev=1.9&content-type=text/plain PROTOCOL.certkeys] | * [http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/ssh/PROTOCOL.certkeys?rev=1.9&content-type=text/plain PROTOCOL.certkeys] | ||
* [https://wiki.gnupg.org/rfc4880bis rfc44880bis from GnuPG] | |||
* [https://weakdh.org/ Weak Diffie-Hellman and the Logjam Attack] | |||
* [https://jbeekman.nl/blog/2015/05/ssh-logjam/ On OpenSSH and Logjam, by Jethro Beekman] |
Latest revision as of 17:53, 27 October 2017
STATUS: READY The goal of this document is to help operational teams with the configuration of OpenSSH server and client. All Mozilla sites and deployment should follow the recommendations below. The Enterprise Information Security (Infosec, formerly OpSec) team maintains this document as a reference guide for operational teams. Updates to this page should be submitted to the source repository on github. Changes are detailed in the commit history. |
ATTENTION |
---|
Only non-default settings are listed in this document. Most default OpenSSH settings that are security-related already provide good security, thus changing them is at your own risk and is not documented here. For example, these guidelines assume only SSH protocol 2 is configured in the server, and SSH protocol 1 is disabled. See |
OpenSSH server
Configuration
Different versions of OpenSSH support different options which are not always compatible. This guide shows settings for the most commonly deployed OpenSSH versions at Mozilla - however, using the latest version of OpenSSH is recommended.
Modern (OpenSSH 6.7+)
File: /etc/ssh/sshd_config
# Supported HostKey algorithms by order of preference.
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
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
# Password based logins are disabled - only public key based logins are allowed.
AuthenticationMethods publickey
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp /usr/lib/ssh/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.
PermitRootLogin No
# Use kernel sandbox mechanisms where possible in unprivileged processes
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
UsePrivilegeSeparation sandbox
File: /etc/ssh/moduli
All Diffie-Hellman moduli in use should be at least 3072-bit-long (they are used for diffie-hellman-group-exchange-sha256
) as per our Security/Guidelines/Key_Management recommendations. See also man moduli
.
To deactivate short moduli in two commands: awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv /etc/ssh/moduli.tmp /etc/ssh/moduli
Intermediate (OpenSSH 5.3)
This is mainly for use by RHEL6, CentOS6, etc. which run older versions of OpenSSH.
File: /etc/ssh/sshd_config
# Supported HostKey algorithms by order of preference.
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
KexAlgorithms diffie-hellman-group-exchange-sha256
MACs hmac-sha2-512,hmac-sha2-256
Ciphers aes256-ctr,aes192-ctr,aes128-ctr
# Password based logins are disabled - only public key based logins are allowed.
RequiredAuthentications2 publickey
# RequiredAuthentications2 not work on official OpenSSH 5.3 portable.
# In this is your case, use this instead:
#PubkeyAuthentication yes
#PasswordAuthentication no
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
LogLevel VERBOSE
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
Subsystem sftp /usr/lib/ssh/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.
PermitRootLogin No
File: /etc/ssh/moduli
All Diffie-Hellman moduli in use should be at least 2048-bit-long. From the structure of moduli
files, this means the fifth field of all lines in this file should be greater than or equal to 2047.
To deactivate weak moduli in two commands: awk '$5 >= 2047' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv /etc/ssh/moduli.tmp /etc/ssh/moduli
Multi-Factor Authentication (OpenSSH 6.3+)
Recent versions of OpenSSH support MFA (Multi-Factor Authentication). Using MFA is recommended where possible.
It requires additional setup, such as using the OATH Toolkit or DuoSecurity.
ATTENTION |
---|
In order to allow using one time passwords (OTPs) and any other text input, Keyboard-interactive is enabled in OpenSSH. This MAY allow for password authentication to work. It is therefore very important to check your PAM configuration so that PAM disallow password authentication for OpenSSH. |
OpenSSH 6.3+ (default)
File: /etc/ssh/sshd_config
# IMPORTANT: you will have to ensure OpenSSH cannot authenticate with passwords with PAM in /etc/pam.d/sshd
# "PasswordAuthentication no" is not sufficient!
PubkeyAuthentication yes
PasswordAuthentication no
AuthenticationMethods publickey,keyboard-interactive:pam
KbdInteractiveAuthentication yes
UsePAM yes
# Ensure /bin/login is not used so that it cannot bypass PAM settings for sshd.
UseLogin no
OpenSSH 5.3+ w/ RedHat/CentOS patch (old)
File: /etc/ssh/sshd_config
# Allow keyboard-interactive.
# IMPORTANT: you will have to ensure OpenSSH cannot authenticate with passwords with PAM in /etc/pam.d/sshd
# "PasswordAuthentication no" is not sufficient!
RequiredAuthentications2 publickey,keyboard-interactive:skey
PasswordAuthentication no
ChallengeResponseAuthentication yes
UsePAM yes
# Ensure /bin/login is not used so that it cannot bypass PAM settings for sshd.
UseLogin no
PAM configuration for use with the OATH Toolkit or DuoSecurity as second authentication factor.
File: /etc/pam.d/sshd
#%PAM-1.0
auth required pam_sepermit.so
# WARNING: make sure any password authentication module is disabled.
# Example: pam_unix.so, or "password-auth", "system-auth", etc.
#auth include password-auth
# Options to enable when using OATH toolkit
#auth requisite pam_oath.so usersfile=/etc/users.oath digits=6 window=20
# Options to enable when using DuoSecurity
#auth sufficient /lib64/security/pam_duo.so
account required pam_nologin.so
Ciphers and algorithms choice
- When CHACHA20 (OpenSSH 6.5+) is not available, AES-GCM (OpenSSH 6.1+) and any other algorithm using EtM (Encrypt then MAC) disclose the packet length - giving some information to the attacker. Only recent OpenSSH servers and client support CHACHA20.
- NIST curves (
ecdh-sha2-nistp512,ecdh-sha2-nistp384,ecdh-sha2-nistp256
) are listed for compatibility, but the use ofcurve25519
is generally preferred.
- SSH protocol 2 supports DH and ECDH key-exchange as well as forward secrecy. Regarding group sizes, please refer to Security/Guidelines/Key_Management.
The various algorithms supported by a particular OpenSSH version can be listed with the following commands:
$ ssh -Q cipher
$ ssh -Q cipher-auth
$ ssh -Q mac
$ ssh -Q kex
$ ssh -Q key
OpenSSH client
Configuration
If you have a file containing known_hosts using RSA or ECDSA host key algorithm and the server now supports ed25519 for example, you will get a warning that the host key has changed and will be unable to connect. This means you will have to verify the new host key.
The following configurations expect a recent OpenSSH client, as updating OpenSSH on the client side is generally not an issue.
Modern
This configuration is less compatible and you may not be able to connect to some servers which use insecure, deprecated algorithms. Nevertheless, modern servers will work just fine.
File: ~/.ssh/config
# Ensure KnownHosts are unreadable if leaked - it is otherwise easier to know which hosts your keys have access to.
HashKnownHosts yes
# Host keys the client accepts - order here is honored by OpenSSH
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
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
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
Intermediate (connects to older servers)
This configuration can connect to older OpenSSH servers which run old or intermediate configurations.
File: ~/.ssh/config
# Ensure KnownHosts are unreadable if leaked - it is otherwise easier to know which hosts your keys have access to.
HashKnownHosts yes
# Host keys the client accepts - order here is honored by OpenSSH
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256
Key generation
Large key sizes are used as SSH keys are not renewed very often (see also Security/Key_Management).
Note:DSA and RSA 1024 bit (or lower) keys are considered weak and should be replaced as soon as possible.
Don't hesitate to create multiple different keys for different usages. In particular, never mix your personal and Mozilla keys.
# RSA keys are favored over ECDSA keys when backward compatibility ''is required'',
# thus, newly generated keys are always either ED25519 or RSA (NOT ECDSA or DSA).
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_mozilla_$(date +%Y-%m-%d) -C "Mozilla key for xyz"
# ED25519 keys are favored over RSA keys when backward compatibility ''is not required''.
# This is only compatible with OpenSSH 6.5+ and fixed-size (256 bytes).
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_mozilla_$(date +%Y-%m-%d) -C "Mozilla key for xyz"
You may then want to add the new key to your SSH agent or your configuration file (or both).
# Add key to ssh-agent
$ ssh-add ~/.ssh/id_..._mozilla... # <= replace by your key's path
# Add configuration to ~/.ssh/config
host *.mozilla.com
IdentityFile ~/.ssh/id_...mozilla... # <= replace by your key's path
Protection of user keys
- Protected by strong passphrase.
- Never copied to another system than your own workstation/personal physical disks/tokens.
- Use SSH forwarding or SSH tunneling if you need to jump between hosts. DO NOT maintain unnecessary agent forwarding when unused.
Protection of machine keys
When SSH keys are necessary for automation between systems, it is reasonable to use passphrase-less keys.
- The recommended settings are identical to the user keys.
- The keys must be accessible only by the admin user (root) and/or the system user requiring access.
- Usage of machine keys should be registered in an inventory (a wiki page, ldap, an inventory database), to allow for rapid auditing of key usage across an infrastructure.
- The machine keys should be unique per usage. Each new usage (different service, different script called, etc.) should use a new, different key.
- Only used when strictly necessary.
- Restrict privileges of the account (i.e. no root or "sudoer" machine account).
- Using a ForceCommand returning only the needed results, or only allowing the machine to perform SSH-related tasks such as tunneling is prefered.
- Disable sftp if not needed as it exposes more surface and different logging mechanisms than SSH (and thus scp) itself.
Note:You may want to use the group "users" instead of "sftpusers" in the example below as this may already exist and include all regular users by default.
# groupadd sftpusers
# usermod -a -g sftpusers <userthat_needs_ftp>
# chgrp sftpusers /usr/lib/ssh/sftp-server
# chmod 0750 /usr/lib/ssh/sftp-server
Multi-factor bypass setup for machine keys
Machine keys do not play well with multi-factor authentication as there is no human interaction.
- All logins from machine accounts should be protected by an additional authentication layer (VPN, another machine, etc.).
- All logins from machine accounts are only allowed within the private IP-space, and if possible, only the relevant machine source IPs should be accessible.
File: /etc/ssh/sshd_config
(OpenSSH 6.3+)
Match User machine_user Address 10.0.0.0/8,192.168.0.0/16,172.16.0.0/12
PubkeyAuthentication yes
KbdInteractiveAuthentication no
AuthenticationMethods publickey
File: /etc/ssh/sshd_config
(OpenSSH 5.3+ w/ RedHat/CentOS patch)
Match User machine_user Address 10.0.0.0/8,192.168.0.0/16,172.16.0.0/12
RequiredAuthentications2 publickey
Auditing your existing SSH keys
Existing keys are generally stored in ~/.ssh/
(Linux/OSX) or %APPDATA%
(Windows).
Look for id_{rsa,ed25519,ecdsa,dsa}, identity, IdentityFile, *.pem
, and other identity
files.
Display SSH keys information
# You may run this for any key file that you have.
$ ssh-keygen -lf id_rsa
2048 bc:4f:46:2b:3d:f1:e2:0f:ac:40:99:49:ed:c9:81:a2 Mozilla key for xyz (RSA)
^^ ^^^^^^^^^ ^^^^ ^^^
|__ Size |__ Fingerprint |__ Comment |__ Type
SSH agent forwarding
ATTENTION |
---|
SSH Agent forwarding exposes your authentication to the server you're connecting to. By default, an attacker with control of the server (i.e. root access) can communicate with your agent and use your key to authenticate to other servers without any notification (i.e. impersonate you). For this reason, one must be careful when using SSH agent forwarding. Defaulting to always forwarding the agent is strongly discouraged. Note also that while the attacker can use your key as long as the agent is running and forwarded, he cannot steal/download the key for offline/later use. |
SSH forwarding allows you to jump between hosts while keeping your private key on your local computer. This is accomplished by telling SSH to forward the authentication requests back to the ssh-agent of your local computer. SSH forwarding works between as many hosts as needed, each host forwarding new authentication request to the previous host, until the ssh-agent that holds the private key is reached.
On each host, two environment variables are declared for the user enabling ssh-agent:
- $SSH_AUTH_SOCK declares the location of the unix socket that can be used to forward an authentication request back to the previous host.(ex: /tmp/ssh-NjPxtt8779/agent.8779). Only present if using SSH agent forwarding.
- $SSH_CONNECTION shows the source IP and port of the previous host, as well as the local IP and port. (ex: 10.22.248.74 44727 10.8.75.110 22).
To use ssh-agent, add the flag -A
to your ssh commands:
$ ssh -A user@ssh.mozilla.com
You can set the following configuration parameter in your local ssh configuration at ~/.ssh/config.
Host ssh.mozilla.com
ForwardAgent yes
Hardening the Agent forwarder
It is possible to require confirmation every time the agent is used (i.e. when you connect to a server through the SSH agent) by using the -c
flag:
# First, remove the key from the agent if it's already loaded:
$ ssh-add -d ~/.ssh/id_ed25519
# And re-add it with the -c flag:
$ ssh-add -c ~/.ssh/id_ed25519
It is also possible to lock the key in the agent after a configurable amount of time, this can be done either for all keys when starting the agent, or per key when adding the keys to the agent with the -t
flag:
# Keep all keys decrypted/useable in memory for 30 minutes (1800 seconds)
$ ssh-agent -t 1800
# First, remove the key from the agent if it's already loaded:
$ ssh-add -d ~/.ssh/id_ed25519
# Re-add it, with the -t flag to keep this specific key decrypted/useable in memory for 30 minutes (1800 seconds)
$ ssh-add -t 1800 ~/.ssh/id_ed25519
For MacOSX in particular it's possible to save the passphrase in the Keychain. If you do so it is strongly recommended to also change the keychain setting to lock itself when the computer is locked, and/or to timeout and lock the keychain. These settings are not controlled by OpenSSH.
# MacOSX only - save the passphrase in the Keychain
$ ssh-add -K ~/.ssh/id_ed25519
Note:There are also some third-party patches for various OpenSSH clients that will notify you visually when the agent is being used.
These are not officially supported and may require you to recompile OpenSSH.
Recommended, safer alternatives to SSH agent forwarding
OpenSSH >=7.3
OpenSSH 7.3 onwards allow users to jump through several hosts in a rather automated fashion. It has full support for scp and sftp commands as well as regular ssh.
For example to reach a host behind a bastion/jumphost:
# Single jump
$ ssh -J ssh.mozilla.com myhost.private.scl3.mozilla.com
# Jump through 2 hops
$ ssh -J ssh.mozilla.com,ec2-instance.aws.net 10.0.0.3
# Copy data from a host
$ scp -oProxyJump=ssh.mozilla.com myhost.private.scl3.mozilla.com:/home/kang/testfile ./
You can also add these lines to your ~/.ssh/config
Host *.mozilla.com !ssh.mozilla.com
ProxyJump ssh.mozilla.com
Older versions of OpenSSH
It is possible to directly forward ports for single jumps instead of forwarding the agent. This has the advantage of never exposing your agent to the servers you're connecting to.
For example, you can add these lines to your ~/.ssh/config
Host *.mozilla.com !ssh.mozilla.com
ProxyCommand ssh ssh.mozilla.com -W %h:%p
This will automatically forward the SSH connection over ssh.mozilla.com when you connect to a mozilla.com SSH server.
Appendixes
Key material handling
Key material identifies the cryptographic secrets that compose a key. All key material must be treated as RESTRICTED data, meaning that:
- Only individual with specific training and need-to-know should have access to key material.
- Key material must be encrypted on transmission.
- Key material can be stored in clear text, but only with proper access control (limited access).
This includes:
- OpenSSH server keys (
/etc/ssh/ssh_host_*key
) - Client keys (
~/.ssh/id_{rsa,dsa,ecdsa,ed25519}
and~/.ssh/identity
).
Client key size and login latency
In order to figure out the impact on performance of using larger keys - such as RSA 4096 bytes keys - on the client side, we have run a few tests:
On an idle, i7 4500 intel CPU using OpenSSH_6.7p1, OpenSSL 1.0.1l and ed25519 server keys the following command is ran 10 times:
time ssh localhost -i .ssh/id_thekey exit
Results:
Client key | Minimum | Maximum | Average |
---|---|---|---|
RSA 4096 | 120ms | 145ms | 127ms |
RSA 2048 | 120ms | 129ms | 127ms |
ed25519 | 117ms | 138ms | 120ms |
Keep in mind that these numbers may differ on a slower machine, and that this contains the complete login sequence and therefore is subject to variations. However, it seems safe to say that the latency differences are not significant and do not impact performance sufficiently to cause any concern regardless of the type of key used.