Linux ssh: allow public-key authentication without giving user read rights to private key
Users logged in on my Linux server should be able to ssh to a specific remote machine with a default account. The authentication on the remote machine uses public key, so on the server the corresponding private key is available.
I don't want the server users to actually be able to read the private key. Basically, the fact that they have access to the server allows them the ssh right, and removing them from the server should also disallow connection to the remote machine.
How can I allow users to open an ssh connection without giving them read access to the private key?
My thoughts so far: obviously the ssh executable must be able to read the private key, so it must run under another user on the server which has those right. Once the ssh connection is established, I can then "forward" it to the user so that he can enter commands and interact with the remote machine.
- Is this a good approach?
- How should I implement the forward?
- How can the user initiate the connection (that is, the execution of the ssh by the user which has read rights on the key)?
- Is there a security loophole? - if the users can execute an ssh as another user, can they then do everything that other user could (including, reading the private key)?
That is one of the reasons sudo
exists. Simply allow your users to run 1 single command with only the pre-authorized command-line options and most obvious circumventions are solved. e.g.
#/etc/sudoers
%users ALL = (some_uid) NOPASSWD: /usr/bin/ssh -i /home/some_uid/.ssh/remote-host.key username@remotehost
sets up sudo
so all members of the group users
can run the ssh command as user some_uid without entering their own password (or that of the some_uid account) when they run:
sudo -u some_uid /usr/bin/ssh -i /home/some_uid/.ssh/remote-host.key username@remotehost
Remove the NOPASSWD:
option to force that users enter their own passwords before logging in to the remote-host.
Possibly set up an alias or wrapper script as a convenience for your users because sudo
is quite picky about using the correct arguments.
This seems like a good use case for host-based authentication. This is a method of authentication where SSH does not use an individual user's key on the local machine (in this case, your server) to authenticate; instead, it uses the host's private key, the one stored in /etc/ssh/
and which is only readable by root
.
To set this up, you'll need to create a file named .shosts
on the remote machine, in the home directory of the user you want people to log in as (not in ~/.ssh
). The file should have the contents
server-hostname +
where server-hostname
is the name of your server, and +
is a literal plus sign that serves as a wildcard meaning "any user".
You'll also need to ensure that the remote machine can verify the server's host key, which means the server's host key needs to be listed in either /etc/ssh/ssh_known_hosts
or ~/.ssh/known_hosts
on the remote machine. If this is not already the case, you can set it up by logging into the remote machine and running
ssh-keyscan server-hostname >> /etc/ssh/ssh_known/hosts
Once you've set up these steps, you can delete the private key on the server entirely, if you don't need it for anything else. (And if you do, you can always set it to be only readable by root
or something.)
You can also easily do things like allowing or denying certain users access to the remote machine. See the man pages of ssh
and hosts.equiv
for details.
One problem with this setup is that users who log into the remote machine can modify .shosts
. There's nothing they can do that would allow them to log in to the remote machine as a different user, but they could cut off their own or others' access to the remote machine. If this is a concern, you might be able to make .shosts
only writable by root
or something - I'm not sure if this works, but you could try it and see. (Other methods like the one with sudo
are susceptible to the same risk, since a user could always delete ~/.ssh/authorized_keys
.)