Jump to one of the sections of this page:
Configure the service by modifying /etc/ssh/ssh_config and /etc/ssh/sshd_config on all hosts as follows:
/etc/ssh/ssh_config is used by local users connecting from this host to some remote server. Put the following in that configuration file:
# Only the more secure SSH2 protocol Protocol 2 # Allow the user to tunnel X applications through SSH. # Read "man ssh_config" first. Yes, there is a security # issue. However, very carefully read that section. It # is described as an additional problem if the attacker # is able to subvert Unix file system security on one # of the hosts. If the attacker is able to do that, # I have far worse problems that must be fixed NOW. ForwardX11 yes
/etc/ssh/sshd_config controls how this server handles connection requests from remote users. Put the following in that configuration file:
# Only the more secure SSH2 protocol Protocol 2 # If you list users allowed to connect via SSH, then # they will be the only users allowed to authenticate # to SSH. # Also see "AllowGroups", "DenyUsers", # and "DenyGroups" in "man sshd_config". AllowUsers joe jane .... # Only accept authentication via cryptographic # challenge-response. The remote client must # have cryptographic keys. PasswordAuthentication no # Do not allow root login -- first login # as ordinary user, then su to root PermitRootLogin no # Specify how to run sftp Subsystem sftp /usr/libexec/sftp-server
Collect host public keys with the following command, where the parameters list every SSH server as both simple hostname and fully-qualified domain name, as well as their IP addresses:
# ssh-keyscan host1 host1.example.com 10.0.0.1 \
host2 host2.example.com 10.0.0.2 \
[....] \
hostN hostN.example.com 10.0.0.N > /etc/ssh/ssh_known_hosts
Alternatively, create a file /tmp/hostlist containing all hostnames, all fully-qualified domain names, and all IP addresses, one item per line, for all of your SSH servers. Then run this command:
# ssh-keyscan -f /tmp/hostlist > /etc/ssh/ssh_known_hosts
Once you have generated /etc/ssh/ssh_known_hosts, securely copy it to every host on which SSH will be used, even the workstations that will only be SSH clients.
You will generate new (and different!) SSH keys if you reinstall the operating system. That means that clients will refuse to connect to that freshly built SSH server, because it will look like it is a different host trying to masquerade. You will need to at least update that host's key. A simple yet safe procedure would be:
Start an SSH agent at login time if your display manager does not already do this. Some, like Gnome's gdm display manager, tend to do this. Others, like KDE's kdm display manager, tend not to.
To test if this is needed, login to the graphical desktop as a user and run this command:
$ ssh-add -l
If an SSH agent is running, you will see the following and you don't need to do anything additional to start an agent for the user:
The agent has no identities.
However, if you see the following, you need to make a change to get an agent started for the users:
Could not open a connection to your authentication agent.
If you need to make a change to get an SSH agent running at login time, modify your display manager configuration.
For example, on Linux with KDE's display manager, the configuration is stored in /usr/share/config/kdm/. On OpenBSD, it is /usr/local/share/config/kdm/. The file Xsession originally contains a block reading as follows:
case $session in
"")
exec xmessage -center -buttons OK:0 -default OK "Sorry, $DESKTOP_SESSION is no valid session."
;;
failsafe)
exec xterm -geometry 80x24-0-0
;;
custom)
exec $HOME/.xsession
;;
default)
exec /usr/bin/startkde
;;
*)
eval exec "$session"
;;
esac
Change that code to the following, with the change highlighted:
case $session in
"")
exec xmessage -center -buttons OK:0 -default OK "Sorry, $DESKTOP_SESSION is no valid session."
;;
failsafe)
exec xterm -geometry 80x24-0-0
;;
custom)
exec $HOME/.xsession
;;
default)
exec ssh-agent /usr/bin/startkde
;;
*)
eval exec "$session"
;;
esac
If you are stuck with CDE and its dtlogin interface (decent technology for about 1990), you need to make a change within the large and complicated file /usr/dt/bin/Xsession. Look for a block like the below, and insert the highlighted code. Yes, you will probably have to specify the full path, and you very likely will have to do some research and experimentation to figure out just exactly where this goes. Hint: look for the reference(s) to dtsession
#
# Session startup clients and args
#
if [ "$SESSIONTYPE" = "altDt" ]; then
dtstart_session[0]="/usr/bin/ssh-agent $SDT_ALT_SESSION"
dtstart_hello[0]="$SDT_ALT_HELLO"
else
dtstart_session[0]="/usr/bin/ssh-agent $DT_BINPATH/dtsession"
dtstart_hello[0]="$DT_BINPATH/dthello &"
fi
dtstart_session[1]="$HOME/.xsession"
dtstart_session[2]="$HOME/.x11start"
Log out, log back in, and run this command:
$ ssh-add -l
You should see a message that the SSH agent has no identities. That's fine, that's what we were looking for. If you instead see a message that the SSH agent cannot be contacted, then you got something wrong. Either you didn't really log all the way out and back in again, or (more likely, I would hope) you didn't get things set up correctly.
Re-start the SSH service however your version of *nix does this. You may find that the following signals your SSH daemon to re-read its configuration:
# pkill -HUP sshd
If not, consult the below table or your system documentation. If you reconfigured your display manager, also restart that.
| Linux | # /etc/init.d/sshd restart |
| Solaris and similar |
# /etc/init.d/sshd stop # /etc/init.d/sshd start |
| BSD |
# pkill -TERM sshd # /usr/sbin/sshd |
Now your system is considerably more secure.
You might want to consider some access control. Be aware that it can only provide limited protection. SSH access control applies in the following order:
Packet filtering — This is a big topic. For Linux, see the Netfilter/iptables documents at http://www.netfilter.org/
TCP Wrapper by example
Allow SSH access for one block of IP addresses only, allow all connection requests on all other network services:
# cat /etc/hosts.allow sshd : 192.168. # cat /etc/hosts.deny sshd : ALL
Allow SSH access for one block of IP addresses only, allow no other connection requests for network services aware of TCP Wrapper access control:
# cat /etc/hosts.allow sshd : 192.168. # cat /etc/hosts.deny ALL : ALL
Allow only specific user@host SSH access, deny all other network services:
# cat /etc/hosts.allow sshd : joe@192.168.12.0/24 , jane@host1.example.com , jane@host2.example.com # cat /etc/hosts.deny ALL : ALL
PAM and Automatic black-list of remote password-guessing attackers — If you are reachable from the Internet, attackers using hosts all over the world will be trying to guess passwords through SSH connection.
First, see if you need to add this line to your /etc/ssh/sshd_config configuration file. You will have to experiment to verify whether your SSH daemon uses PAM by default (see if the syslog messages from sshd include references to PAM rules):
UsePAM
The pam_abl PAM module can automatically add a password-guessing host to a black-list. Put something like this in the file /etc/pam.d/sshd before the existing auth lines:
auth required pam_abl.so config=/etc/security/pam_abl.conf
Then add something like this to the reference configuration file /etc/security/pam_abl.conf
# Black-list any remote host with 10 consecutive authentication failures # in one hour, or 30 in one day. Keep them in the black-list for two days. host_db=/var/lib/abl/hosts.db host_purge=2d host_rule=*:10/1h,30/1d # Black-list any local user other than root for which there are # 10 consecutive authentication failures in one hour, or 30 in # one day. Keep them in the black-list for two days. Note that # this means that non-root users may be subjected to denial of # service attacks caused by remote password guessing. user_db=/var/lib/abl/users.db user_purge=2d user_rule=!root:10/1h,30/1d
Allow/Deny rules in /etc/ssh/sshd_config: — See the sshd_config manual page for the details on this. The short version is that you add lines like the following to sshd_config and then send a HUP signal to the daemon. Once you add one AllowUsers rule, then the only users allowed to login via SSH are the listed ones:
AllowUsers joe AllowUsers jane
You can also do this by client hosts:
AllowUsers *@host1.example.com AllowUsers *@host2.example.com
Or even by domains:
AllowUsers *@*.example.com
The user needs to generate SSH public/private key pairs. Use the following command sequence. Provide a strong passphrase, since security rests on this being extremely difficult to guess. Unless you really want to greatly inconvenience and confuse yourself, use the same passphrase for both RSA and DSA key pairs! Accept the default locations for key storage:
$ ssh-keygen -t rsa $ ssh-keygen -t dsa $ cat ~/.ssh/*.pub > ~/.ssh/authorized_keys
In some situations (for example, Red Hat Enterprise Linux 5), the umask of the unprivileged user's environment may be set to 002, so the permission of the resulting authorized_keys file is 664, world-writeable. And the SSH daemon may refuse to pay attention to those keys (again, as seen on RHEL5). So you may need to do this:
$ chmod 644 ~/.ssh/authorized_keys
Once those keys are generated, the entire directory ~/.ssh must be copied into place on all systems. If you are using NFS and automounting, this is already done! If you are not, then the administrator might need to get involved briefly.
At every login, the user simply runs this command:
$ ssh-add
Type your SSH key passphrase (what you typed back when you generated the keys). Now everything is automatic! Commands like ssh, scp, and even sftp work automatically without any password-typing by you!
You can observe quite a bit of this by asking SSH to be verbose. For example:
$ ssh -v someserver date
If you are really interested in details, ask for very verbose narration:
$ ssh -vv someserver date
1 — Your client host and the remote server authenticate to each other using public-key cryptography. Each host is certain that it has the other's public key, since the administrator stored all those in /etc/ssh/ssh_authorized_keys. Host #1 picks a random number and sends it to host #2 as a challenge. The host #2 encrypts that challenge with its private key to create the response, and sends it back to host #1. Host #1 decrypts the response using the public key of host #2 (which host #1 is certain that it has). If the result is identical to the challenge, then that must really be host #2 over there!
2 — The client and server negotiate a cipher and a session key. The cipher will be the strongest encryption algorithm that both hosts know. The session key will be generated with the Diffie-Hellman algorithm — see my "Just enough cryptography" page for details.
3 —
User authentication happens.
Now that the two hosts are certain of each other's identity,
and they have negotiated a secure communication channel,
the user can be authenticated.
Cryptographic challenge-response authentication is tried first,
as described above for hosts.
Since we disabled password authentication on the server,
that method has to work.
If the user forgot to run ssh-add,
they get mysterious remote authentication failures.
So either:
— Train your users to always run ssh-add
— Put something in a startup file to force them to do this
My page on hardening default installations of Linux and BSD
| Home Page | Site Map | Public Key |
|
|
|
|
|
|
| © Bob Cromwell Jul 2008. Created with /bin/vi, hosted on OpenBSD with Apache. Root password available here | ||||