1. Overview
In this tutorial, we’ll talk about solutions to forwarding our ssh-agent and having access to our private keys when using sudo in the remote system.
2. ssh-agent Forwarding and the Problem Statement
Before discussing the solutions, let’s see the applications we use and the problem itself in detail.
2.1. What Is ssh-agent?
We’re dealing with the SSH protocol, which stands for Secure SHell, and uses public-key cryptography for the remote login.
To access a remote system, we need a pair of keys, one public and one private. We store the private key in our computer encrypted, to avoid unauthorized parties accessing it. The encryption is based on a passphrase that the user needs to remember.
To avoid typing the passphrase every time we establish a connection, we can also enter the passphrase only one time for each local login. We can then store the unencrypted private key in program memory. Linux associates this key with a process. However, the SSH client can’t store this unencrypted key because the process ends once the remote session finishes.
This is where ssh-agent comes into play. ssh-agent stores the unencrypted private key in memory and the process doesn’t end when an SSH remote session closes. It communicates with the SSH client that we have in our system through Unix domain sockets. These sockets are endpoints for communicating data between processes running in the system.
2.2. What Is ssh-agent Forwarding?
Let’s imagine that we connect to a remote system A with SSH. Once in this remote system A, we want to interact with yet another remote system B using SSH. However, we might not want to have our private keys in remote system A and we want to keep them only in our local system.
With ssh-agent forwarding, we can instruct our SSH client to forward the local ssh-agent to the remote server. This way, when we attempt to log into remote system B, the SSH client checks the private keys on our local system instead of in the remote system A.
With ssh-agent forwarding, we’re not sending the private keys, not even encrypted. We’re just pointing to our local system as the location of the private keys. Remote system B verifies our identity based on the keys of our local system. Only the response is sent through remote system A.
ssh-agent creates a socket and an environment variable named $SSH_AUTH_SOCK. This environment variable contains the filepath of the socket that the ssh-agent uses for communications for other processes. This points to a temporary address in memory:
$ echo $SSH_AUTH_SOCK
/tmp/ssh-OsVxXXgVI8jD/agent.157042
2.3. Why Can’t We sudo Into Another User With ssh-agent Forwarding?
Let’s imagine that we can log in to a remote system A. Inside this remote system A we can change users with sudo su – user2. Now if we want to access the remote system B, we won’t be able to because we lost key forwarding when we used the sudo command to switch users.
This happens due to security reasons: when we use sudo, Linux removes the user environment variables. This is done to avoid letting users with sudo rights that connect to the system have access to our forwarded ssh-agent and use our keys.
3. Solutions to the Problem
We’ll discuss three solutions to the problem. The purpose is to SSH access remote_system_A with user1. Then, once we’re there, we want to switch to user2 and access remote_system_B through SSH.
3.1. Enable Forwarding of the Authentication Agent Connection
We can use the -A flag (if using the OpenSSH client) to enable the forwarding of the authentication agent connection if we have our public key in the home directory of user1:
$ ssh -A user1@remote_system_A
Forwarding the authentication connection might bring some security issues. All the users with root access or similar permission in the remote system A will have access to the local agent forwarded through the connection. No data should be retrieved from the system that user1 has logged from, but the keys can be used to authenticate into other systems impersonating user1. Moreover, this won’t work if we can access user2 with sudo only and not over SSH.
This is an interesting option for testing or quick tasks: we can just open another terminal and connect to a remote system with the -A option. If the connection falls, we’ll lose the socket redirection and we’ll need to establish it again.
3.2. Preserve Environment Variables When Using sudo
Another solution is to preserve the environment variables when switching users inside remote_system_A with the -E flag:
user1@remote_system_A $ sudo -E -s
With the previous command, we’ll get a rooted shell that has the original keys through the environment variables. The -s flag is used to run a command defaulting to a shell.
This approach only works for becoming root and not user2, but since we established that we’d log to user2 with sudo – su user2, we should have root access.
Moreover, we can be more strict and specify only the environment variable that we want to keep, which is the SSH_AUTH_SOCK that we saw before:
user1@remote_system_A $ sudo --preserve-env=SSH_AUTH_SOCK -s
3.3. Keep the Environment Variable Permanently
With the previous approach, once inside remote_system_A, when user1 runs the command with sudo, we needed to specify the environment variable we want to preserve. We can make this choice persistent to avoid specifying it every time we run sudo.
To do that, we can modify the /etc/sudoers file (with superuser rights) to specify that the environment variable SSH_AUTH_SOCK should be preserved. To get the option to be set for all users, we use the Defaults option:
Defaults env_keep+=SSH_AUTH_SOCK
With that, we should be able to sudo in remote_server_A from user1 to then access remote_system_B. We’ll still need the public keys to be located in our local system: user1 key for remote_system_A and user2 key for remote_system_B.
4. Conclusion
In this article, we’ve discussed three ways we can keep our forwarded ssh-agent to have access to the private keys in our remote systems when using sudo. We can enable the ssh-agent forwarding through the SSH connection itself, although this can pose security risks. Otherwise, we have to preserve the environment variable related to the ssh-agent socket when switching to sudo. We can choose to do this for a single session or set it as default for every time we switch to sudo.