Can socat be used to forward an ssh-agent socket into a chroot

chrootsocatssh-agent

I'm building custom Debian environments on a remote server, which I connect to over SSH. This involves building a debootstrap environment, then chrooting into it to run a custom installer. As part of the custom install process, I need the installer to be able to ssh out of the chroot environment to a further remote server, re-using the SSH credentials my ssh-agent outside the chroot knows about.

I simply can't think how to do this. In principle, I think I should be able to use socat to forward the $SSH_AUTH_SOCK into the chroot environment before calling chroot like this:

socat UNIX-CONNECT:$SSH_AUTH_SOCK UNIX-LISTEN:chroot_root$SSH_AUTH_SOCK,fork &
sudo -E chroot chroot_root /bin/bash

But that gives me a broken pipe from socat as soon as I try to use ssh inside the chroot, which I guess is understandable (in a way).

Is there any way around this? I've got a fallback of setting up an SSH master socket before chrooting and using that for everything inside the chroot, but that would involve a fairly intrusive rewrite of the installer, so I'm really not keen on that plan.

UPDATE

It turns out that I can get the effect I want simply by creating a hard link to the socket. I honestly didn't expect that to work.

Best Answer

You can forward the SSH Agent into a chroot but you have to jump through a few hoops, the first of which is making the socket accessible in the chroot and the second is telling users within chroot about it.

To make the socket available, the OP's suggestion to use socat works as long as permissions are set properly. Assuming that you're using a script to launch the chroot, the following snippet uses socat to provide the agent socket in the chroot:

# Set up a SSH AGENT forward socket
if [ -n "$SSH_AUTH_SOCK" ]
then
  _dir="$mnt$(dirname $SSH_AUTH_SOCK)"
  _owner=$(awk -F':' '{if ($1=="alice") {print $3":"$4}}' $mnt/etc/passwd)
  mkdir "$_dir"
  chown "$_owner" "$_dir"
  socat UNIX-CONNECT:$SSH_AUTH_SOCK \
        UNIX-LISTEN:$mnt$SSH_AUTH_SOCK,fork,user=${_owner%:*} &
  socat_pid=$!
  export SSH_AUTH_SOCK
fi

It establishes the uid and gid of the user (alice in the example) within the chroot that should be able to access the agent. It then creates that directory and establishes a socat in pretty-much the same manner as the OP. The addition is the user=${_owner%:*} pirce which sets the uid on the socket within the chroot so that alice can access it.

It then remembers the socat PID so that it can be torn down when the chroot exits. Finally it exports the SSH_AUTH_SOCK variable to make it available within the chroot.


Now, chroot can only be done by root so my guess would be that the script is run with sudo from a regular user who owns the agent process. If this is accurate, then there is one more thing to do which is to permit sudo to pass the environment varaible into the script. To do this, edit /etc sudoers (the approved mechanism is to so sudo visudo) and add the following:

Defaults env_keep+=SSH_AUTH_SOCK

This change also needs to be made to /etc/sudoers within the chroot if sudo will be used within the chroot (i.e. to switch from root to alice).

Here is an example of an agent socket within a chroot viewed by a regular user.

$ ls -l $SSH_AUTH_SOCK
srwxr-xr-x 1 alice root 0 Feb  1 15:06 /tmp/ssh-q1ntaubl6I2z/agent.1443