ShareWiz Ultra Secure Server Setup

SSH Security

ssh

SSH Security

OpenSSH

OpenSSH is the implementation of the SSH protocol on Ubuntu. OpenSSH is recommended for remote login, making backups, remote file transfer via scp or sftp, and much more. SSH is perfect to keep confidentiality and integrity for data exchanged between two networks and systems. However, the main advantage is server authentication, through the use of public key cryptography.

Here are a few things you need to tweak in order to improve OpenSSH server security:

Before making any modifications to the /etc/sshd_config file, make a backup by:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.factory-defaults

...and

sudo chmod a-w /etc/ssh/sshd_config.factory-defaults

NOTE: Not all of the possible changes mentioned below have to be made. Some changes are not recommended to be made but may offer tighter security depending on your requirements.

Further documentation about SSH can be found at: Ubuntu SSH help.

Issue the command man sshd_config for further details about the server configuration file.

Default SSH Config Files and SSH Port:

Config FileDescription
/etc/ssh/sshd_configOpenSSH server configuration file
/etc/ssh/ssh_configOpenSSH client configuration file
~/.ssh/Users SSH configuration directory
~/.ssh/authorized_keys or ~/.ssh/authorized_keysLists the public keys (RSA or DSA) that can be used to log into the user’s account
/etc/nologinIf this file exists, sshd refuses to let anyone except root to log in
/etc/hosts.allow and /etc/hosts.denyAccess controls lists that should be enforced by tcp-wrappers are defined here
SSH default port22

Once you have finished editing the /etc/ssh/sshd_config file, make sure to save your changes before restarting your SSH daemon.

top

Edit the sshd config file

Issue the following command:

sudo vi /etc/ssh/sshd_config

top

Restrict SSH to version 2

…add in this line if not already in the sshd configuration file, otherwise modify it to be:

Protocol 2

SSH protocol version 1 (SSH-1) has man-in-the-middle attacks problems and security vulnerabilities. SSH-1 is obsolete and should be avoided at all cost.

top

Restrict SSH Key Size to 2048 or above

…add in this line if not already in the sshd configuration file, otherwise modify it to be:

ServerKeyBits 2048

This defines the number of bits in the ephemeral protocol version 1 server key.

NOTE: The file /etc/ssh/moduli file contains a list of all keys supported.

A recommendation is to remove the smaller groups from the /etc/ssh/moduli file on the server.

When the client asks for a Diffie-Hellman group, sshd searches the moduli file for groups and picks one at random from the set at least as large as what the client requested. If there are no small (eg 1k, 1.5k) keys, then sshd will always use larger ones.

top

Don’t listen to all addresses

Change the following line in the sshd config file from:

ListenAddress 0.0.0.0

to

ListenAddress 192.168.0.11

Allowing connections from only certain IP addresses makes a system a lot more secure.

It's recommended to change the listening address.

top

Disable SSH root login

Change the following line in the sshd config file from:

PermitRootLogin yes

to

PermitRootLogin no

By default, the SSH daemon ships with remote root logins enabled. Normally Ubuntu does not allow direct access to the root user, so this setting is unimportant. If you have set a password on the root account, this setting can be a potential security risk, and should be disabled.

It is safer to login as another user and use sudo.

NOTE: Sometimes it is necessary to allow root logins when doing automated tasks such as backups. To disallow normal logins but allow forced commands, you can use:

PermitRootLogin forced-commands-only

top

Disable empty passwords when using SSH

…add in this line if not already in the /etc/ssh/sshd_config file, otherwise modify it to be:

PermitEmptyPasswords no

You need to explicitly disallow remote login from accounts with empty passwords.

top

Log more information about SSH connections

Change the following line in the /etc/ssh/sshd_config file from:

LogLevel INFO

to

LogLevel VERBOSE

By default, the OpenSSH server logs to the AUTH facility of syslog, at the INFO level. To record more information - such as failed login attempts - increase the logging level to VERBOSE.

Now all the details of ssh login attempts will be saved in your /var/log/auth.log file.

If you have started using a different port, or if you think your server is well-enough hidden not to need much security, you should increase your logging level and examine your /var/log/auth.log file every so often. If you find a significant number of spurious login attempts, then your computer is under attack and you need more security.

Whatever security precautions you've taken, you might want to set the logging level to VERBOSE for a week, and see how much spurious traffic you get. It can be a sobering experience to see just how much your computer gets attacked.

It's recommended to log more information if you're curious about malicious SSH traffic.

top

Configure the SSH Idle Log Out Timeout Interval

Add the following lines to the sshd config file:

ClientAliveInterval 900

ClientAliveCountMax 1

You are setting an idle timeout interval in seconds (900 secs = 15 minutes). After this interval has passed, the idle user will be automatically logged out.

PCI-DSS requires that there be a maximum of 1 concurrent SSH session per user.

top

Disable SSH support for .rhost files

…add in this line if not already in the sshd configuration file, otherwise modify it to be:

IgnoreRhosts yes

SSH can emulate the behavior of the obsolete rsh command. Therefore disable access via rsh. To ensure that SSH does not read the user's ~/.rhosts and ~/.shosts files.

It's recommended to disable rsh access.

top

Disable IPV6 access to SSH (Optional)

…add in this line if not already in the sshd configuration file, otherwise modify it to be:

AddressFamily inet

Specifically limit traffic to IPv4. This will limit attack vectors.

The options that can be used for this line are:

  • inet = IPv4
  • inet6 = IPv6
  • any = both

It's recommended to limit the system to IPV4 if IPV6 is not used on the system.

top

Enable the SSH welcome banner

Change the following line in the sshd config file from:

#Banner /etc/issue.net

to

Banner /etc/issue.net

Now, edit /etc/issue.net and place a warning to unauthorized users. An example of what to include is shown here:

***************************************************************************

NOTICE TO USERS

 

This computer system is the private property of its owner, whether

individual, corporate or government. It is for authorized use only.

Users (authorized or unauthorized) have no explicit or implicit

expectation of privacy.

 

Any or all uses of this system and all files on this system may be

intercepted, monitored, recorded, copied, audited, inspected, and

disclosed to your employer, to authorized site, government, and law

enforcement personnel, as well as authorized officials of government

agencies, both domestic and foreign.

 

By using this system, the user consents to such interception, monitoring,

recording, copying, auditing, inspection, and disclosure at the discretion

of such personnel or officials. Unauthorized or improper use of this

system may result in civil and criminal penalties and administrative

or disciplinary action, as appropriate. By continuing to use this system

you indicate your awareness of and consent to these terms and

conditions of use. LOG OFF IMMEDIATELY if you do not agree to the

conditions stated in this warning.

 

****************************************************************************

Once this is in place, restart sshd and all users will see this warning before they get the login prompt.

The SSH daemon will allow a message to be displayed to users attempting to log in to the SSH server.

To enable login messages, remove the hash sign # from the Banner line.

For legal reasons, it can be useful to display a banner informing people about their legal rights with regards to your server.

This will obviously not dissuade automated SSH attacks, and will potentially worsen Denial-of-Service (DoS) effects, but it may tip off a human attacker that the system is being looked after closely, and that they should move on to some other system on the network.

top

Limit SSH access to only certain users

Create a group called sshusers and only add users to it who require remote access.

Issue the following command:

sudo groupadd sshusers

…and add users to the group who are allowed to access ssh:

sudo usermod -a -G sshusers peter

Alternatively edit the /etc/group file:

sudo vi /etc/group

...and edit the sshusers line as follows:

sshusers:x:1002:peter, john, james, SHAREWIZ\SWAdmin, SHAREWIZ\peter.roux

NOTE: Besides groups, individual users can also be allowed to access SSH.

As can be seen from the above example, the last few usernames show Active Directory logins. Information on Active Directory can be found elsewhere on this site.

Edit the /etc/ssh/sshd_config file:

sudo vi /etc/ssh/sshd_config

Add in the following line:

AllowGroups sshusers

By default, SSH will permit every user with a UNIX account to be able to log in.

You can explicitly allow or deny access for certain users or groups.

An alternative to using AllowGroups is to use the AllowUsers and DenyUsers directives to modify the access rights of these users.

Examples:

To allow access to users username1 and username2, add the following:

AllowUsers username1 username2

To limit access to a specific user from a specific IP address, use something like:

AllowUsers username@192.168.0.2 username2

To deny access to specific users, add the following:

DenyUsers username3 username4 username5

IMPORTANT: If using Active Directory logins, remember to add in these users to the sshusers group as well. So in /etc/group, add in users such as:

SHAREWIZ\peter.roux

top

Switch off DNS checking on SSH

To prevent slow SSH connections, disable DNS checking for SSH.

…add in this line if not already in the sshd configuration file, otherwise modify it to be:

useDNS no

This can be re-enabled at a later stage once DNS is configured.

top

Lower the SSH Login Grace Time (Optional)

Change the following line in the sshd config file from:

LoginGraceTime 120

to

LoginGraceTime 60

By default, OpenSSH gives you two minutes to type a password in once you've connected. You might want to change this if you are worried about attackers, but need to allow passwords.

This doesn't add much security, but also doesn't make it much harder to legitimately use SSH.

top

Disable password authentication for SSH (Optional)

Security can be tightened by forcing public key authentication and disabling password authentication entirely. While this greatly enhances security and completely defeats brute-force attacks, it will lock you out of the machine if you lose your private key. Use with caution!

On the client, generate a key pair with a strong passphrase using:

sudo ssh-keygen -t rsa -b 4096

which will display:

Generating public/private rsa key pair.

Enter file in which to save the key (/home/<username>/.ssh/id_rsa):

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /home/<username>/.ssh/id_rsa.

Your public key has been saved in /home/<username>/.ssh/id_rsa.pub.

The key fingerprint is:

xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx <username>@<client hostname>

Next, copy the above key to the server you'd like to login to (NOTE: This puts the key in /home/<username>/.ssh/authorized_keys on the server):

ssh-copy-id -i /home/<username>/.ssh/id_rsa.pub <username>@<server hostname>

Verify you can login to the server with your new key:

ssh <username>@<server hostname>

which will prompt:

Enter passphrase for key '/home//.ssh/id_rsa':

<username>@<server hostname:~$

Once you have verified you can login to the server with your new key pair, update /etc/ssh/sshd_config on the server to have Password Authentication disabled.

# Change to disable tunnelled clear text passwords:

#PasswordAuthentication yes

to

PasswordAuthentication no

top

Use SFTP instead of FTP with SSH (Optional)

Change the following line in the sshd config file from:

Subsystem sftp /usr/lib/openssh/sftp-server

to

Subsystem sftp internal-sftp

Add a stanza like the following to the *bottom* of the same file. NOTE: It must be at the bottom, because Match groups are only terminated by the end of the file (or another Match stanza):

Match User peter

ChrootDirectory %h/public_html

X11Forwarding no

AllowAgentForwarding no

AllowTcpForwarding no

ForceCommand internal-sftp

Suppose you want to give some users the ability to upload and download files from their home directories (or ~/public_html), but not a full shell account. This is simple to achieve with OpenSSH's SFTP component.

Now peter can use SFTP to read from and write to his ~/public_html/ directory, but can't use OpenSSH to get a shell, nor even to read files outside of ~/public_html.

If you have many such users, you can change User peter to `Group sftponly, and add users to the sftponly group using usermod(8)`. For FTP on such systems, consider vsftpd: it is more security-conscious than other FTP implementations.

top

Check the Current SSH Ports

Issue the following command:

sudo netstat -na|grep tcp

...which should show something like:

root@server1:~# netstat -na|grep tcp
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 192.168.0.11:22         192.168.0.184:39662     ESTABLISHED
tcp6       0      0 :::22                   :::*                    LISTEN

The 0.0.0.0 in the first line indictes that SSH is listing on all ports.

The 2nd line can be ignored. This is simply the current connection.

Similarly, the :::in the 3rd line indicates that SSH is listing on all ports with IPV6.

top

Restart SSH

Execute the following command:

sudo service ssh restart

Alternatively use the old-fashioned method to restart the service:

sudo /etc/init.d/ssh restart

top

Check the SSH Ports Again

Issue the following command:

sudo netstat -na|grep tcp

...which should show something like:

root@server1:~# netstat -na|grep tcp
tcp        0      0 192.168.0.11:22         0.0.0.0:*               LISTEN
tcp        0      0 192.168.0.11:22         192.168.0.184:39662     ESTABLISHED

This now shows that SSH is listening on 192.168.0.11 which is out external WAN address.

top

Troubleshooting SSH

First, check that the SSH daemon is running:

sudo ps -A | grep sshd

This command should produce a line(s) like this:

<some number> ?   00:00:00   sshd

If there is no line, your SSH daemon is not running. If it is, you should next check that it's listening for incoming connections:

sudo netstat --inet -lpn | grep sshd

This command should produce a line that looks like this:

tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN <same number>/sshd

If there is more than one line, then your SSH daemon is listening on more than one port - you might want to go back and delete some Port lines in your sshd_config file.

If there are no lines, your SSH daemon isn't listening on any ports, so you need to add at least one Port line. If the line specifies something other than "0.0.0.0:22", then your SSH daemon is listening on a non-standard port or address, which you might want to fix.

Next, try logging in from your own computer:

sudo ssh -v localhost

...which should show something like:

root@server1:~# sudo ssh -v localhost
OpenSSH_6.2p2 Ubuntu-6ubuntu0.1, OpenSSL 1.0.1e 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to localhost [127.0.0.1] port 22.
debug1: connect to address 127.0.0.1 port 22: Connection refused
ssh: connect to host localhost port 22: Connection refused

Notice that the connection was refused. This is due to the earlier config that limited access only from 192.168.0.11. In this case, that allowed IP address was not used, and an attempt was made to login using localhost instead.

Lets retry logging in using an allowed IP address:

sudo ssh -v 192.168.0.11

...which should show something like:

root@server1:~# sudo ssh -v 192.168.1.11
OpenSSH_6.2p2 Ubuntu-6ubuntu0.1, OpenSSL 1.0.1e 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to 192.168.0.11 [192.168.0.11] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: SELinux support disabled
debug1: identity file /root/.ssh/id_rsa type -1
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: identity file /root/.ssh/id_ecdsa type -1
debug1: identity file /root/.ssh/id_ecdsa-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.2p2 Ubuntu-6ubuntu0.1
debug1: Remote protocol version 2.0, remote software version OpenSSH_6.2p2 Ubuntu-6ubuntu0.1
debug1: match: OpenSSH_6.2p2 Ubuntu-6ubuntu0.1 pat OpenSSH*
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5-etm@openssh.com none
debug1: kex: client->server aes128-ctr hmac-md5-etm@openssh.com none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ECDSA b7:60:9d:55:7e:43:6a:33:f8:b1:57:54:93:4a:b7:b3
The authenticity of host '192.168.0.11 (192.168.0.11)' can't be established.
ECDSA key fingerprint is b7:60:9d:55:7e:43:6a:33:f8:b1:57:54:93:4a:b7:b3.
Are you sure you want to continue connecting (yes/no)?

This will print a lot of debugging information, and will then prompt whether you want to connect.

Enter yes.

...which should show some additional lines:

Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.0.11' (ECDSA) to the list of known hosts.
debug1: ssh_ecdsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
Write failed: Broken pipe

The Write failed: Broken pipe message is caused by a timeout issue.

You may recall that the login time was limited in the earlier config.

NOTE:This has however added our WAN IP address into the list of known hosts.

Simply rerun by issuing the following command again.

sudo ssh -v 192.168.0.11

...which should show something like:

debug1: Server host key: ECDSA b7:60:9d:55:7e:43:6a:33:f8:b1:57:54:93:4a:b7:b3
debug1: Host '192.168.1.11' is known and matches the ECDSA host key.
debug1: Found key in /root/.ssh/known_hosts:1
debug1: ssh_ecdsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Trying private key: /root/.ssh/id_rsa
debug1: Trying private key: /root/.ssh/id_dsa
debug1: Trying private key: /root/.ssh/id_ecdsa
debug1: Next authentication method: password
root@192.168.1.11's password:

Remember that the password will only be accepted if the corresponding user is allowed access in by SSH.

In this case this would not work, as root was not an allowed user.

Try logging in from a valid user's account. For instance to login using peter as the username use:

sudo ssh -v 192.168.0.11 -l peter

...which should show something like:

...
peter@192.168.1.11's password:
debug1: Authentication succeeded (password).
Authenticated to 192.168.1.11 ([192.168.1.11]:22).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LC_PAPER = en_GB.UTF-8
debug1: Sending env LC_ADDRESS = en_GB.UTF-8
debug1: Sending env LC_MONETARY = en_GB.UTF-8
debug1: Sending env LC_NUMERIC = en_GB.UTF-8
debug1: Sending env LC_TELEPHONE = en_GB.UTF-8
debug1: Sending env LC_IDENTIFICATION = en_GB.UTF-8
debug1: Sending env LANG = en_GB.UTF-8
debug1: Sending env LC_MEASUREMENT = en_GB.UTF-8
debug1: Sending env LC_TIME = en_GB.UTF-8
debug1: Sending env LC_NAME = en_GB.UTF-8
Welcome to Ubuntu 13.10 (GNU/Linux 3.11.0-18-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

  System information as of Mon Mar 24 21:38:35 GMT 2014

  System load:    0.08            Processes:           117
  Usage of /home: 0.4% of 452MB   Users logged in:     0
  Memory usage:   3%              IP address for eth0: 192.168.1.11
  Swap usage:     0%              IP address for eth1: 192.168.2.1

  Graph this data and manage this system at:
    https://landscape.canonical.com/

Last login: Mon Mar 24 21:38:41 2014 from 192.168.1.184

If nothing happens, you might need to tell your computer's firewall to allow connections on port 22 (See the FireWall Security section).

Once logged in, to leave the SSH command-line, type:

exit

top

Continue to the Memory Security...