SSH Start to Finish Architecture – Public Key Options

Since we’ve introduced a few ways of doing tunneling, I thought now would be a good time to bring out some ways of restricting what a user can do in the event that they have access to a private key they shouldn’t.

We already talked about setting a pass phrase on the private key side, but there is still the chance that the user was able to brute force that, so let’s assume they have usable access to that private key. What options do we have for keeping things secure?

For starters, we can restrict which source IP/DNS names a user can come from using this key. If we modify the public key entry in the authorized_keys file to include a “from” directive before the key starts, we can provide a list of IP addresses/hostnames we expect to be coming from. This prevents an attack from the user’s workstation, for example. One caveat of this is, you can’t be coming through a source NAT, since that would reduce the effectiveness of this restriction. Everyone coming into the box from a source NAT VLAN or subnet would look like they are coming from the same place.

In order to set this directive, we will need to modify the public key by hand. It’s better to modify the public key before adding it to the authorized_keys file, but you can modify the authorized_keys file entry for this key, if you prefer.

To use this directive, we need to put the a “from” option with all of its values, comma separated, BEFORE the key starts. An example of how this might look follows:
from=”172.16.84.1,lanturtle,lanturtle.mydomain” ssh-rsa AAAA User_A@lanturtle

Now, let’s assume you also want to prevent proxying with this key. In order to restrict that, we need to set several options:
no-X11-forwarding – Prevents forwarding X11 sessions back to an X server via the SSH tunnel.
no-port-forwarding – Prevents port forwarding via TCP, TUN devices, and direct stdin proxying.
no-agent-forwarding – Prevents “forwarding” of the ssh-agent for handling the private key.

To add these to the example above, we would use a comma separated list of options like this:
from=”172.16.84.1,lanturtle,lanturtle.mydomain”,no-X11-forwarding,no-port-forwarding,no-agent-forwarding ssh-rsa AAAA User_A@lanturtle

We can further restrict this to only allowing this particular key to be used for running a specific command. Doing this ignores any commands passed by the user upon connection, and prevents the user from obtaining a full login shell (unless that’s the forced command.)
command=”/usr/local/bin/ssh-restricted-command.sh” (where “/usr/local/bin/ssh-restricted-command.sh” is the command you want it to run. Put the actual command you want to use, here.)
from=”172.16.84.1,lanturtle,lanturtle.mydomain”,no-X11-forwarding,no-port-forwarding,no-agent-forwarding,command=”/usr/local/bin/ssh-restricted-command.sh” ssh-rsa AAAA User_A@lanturtle

Finally, if we want to be sure that there isn’t a land mine waiting on the user’s .ssh/rc file, we can tell it to not read this by using the following option:
no-user-rc
from=”172.16.84.1,lanturtle,lanturtle.mydomain”,no-X11-forwarding,no-port-forwarding,no-agent-forwarding,no-user-rc,command=”/usr/local/bin/ssh-restricted-command.sh” ssh-rsa AAAA User_A@lanturtle

When we get into managing a certificate authority, you’ll find that these options can be set by ssh-keygen for certificate related keys, but the option names are slightly different. Unfortunately, using ssh-keygen to generate the initial public/private key with these options doesn’t work. It only works on certificates. Modifying the public key entry by hand does restrict this, however.

We will go into more detail about the forced command option (and setting one in sshd_config) next week.

Thanks for reading!