SSH Notes

Forwarding your ssh agent to vnc

While session managers such as gnome typically start an authentication agent at the beginning of a session, this doesn’t seem to be the right thing for a vnc session. Really, you want to keep your keys on your client machine and not have to remember to lock the agent whenever you disconnect from your vnc session (though you do have to remember to lock the agent on your client machine if you leave it unattended). In this section, I’ll describe a method of using ssh-agent on your local machine together with ssh_config to forward your local agent to your vnc session and use it there seamlessly.

The plan is this: use the key agent (ssh-agent, gnome-keyring-daemon or whatever) on your local machine to store your keys, forward a connexion to that agent through ssh whenever you connect and make the vnc session at the far end use that forwarded agent.

This is written (mostly) under the assumption that you don’t generally log in at the console of the vnc serving machine. In what follows, /home/you/.vnc/xstartup is the vnc startup script on the vnc serving machine.

  1. Avoid starting ssh-agent on your vnc session

    I think it best first to make sure that you don’t start one yourself in your /home/you/.vnc/xstartup. Then, if you are using gnome in your vnc session, you need to issue this command on the machine that will run the vnc server:

    gconftool-2 --set /apps/gnome-keyring/daemon-components/ssh --type bool false
    

    Which tells gnome-keyring-daemon not to function as an ssh-agent. You may need to find a way of making this specific to your vnc session if you sometimes log in at the console and want gnome-keyring-daemon to handle your ssh agent then.

    If your vnc server is running fedora (11 certainly) and you began with the default /home/you/.vnc/xstartup, you will also need to add this to your /home/you/.vnc/xstartup before it starts the window manager:

    # /etc/X11/xinit/xinitrc-common (called from /etc/X11/xinit/xinitrc)
    # checks if SSH_AGENT_PID is set and otherwise starts an agent
    # so set it to something bogus here
    declare -x SSH_AGENT_PID=FORWARDED
    
  2. Set SSH_AUTH_SOCK in your /home/you/.vnc/xstartup

    In order that all the shells and what-have-you in your vnc session can contact the agent you’ll forward, you need to set the ssh authorisation socket variable to point to somewhere you can link to the socket when you connect, so put the following lines in your /home/you/.vnc/xstartup (again before it starts the window manager).

    # Want vnc session to get its ssh agent from the connecting
    # ssh
    declare -x SSH_AUTH_SOCK=/home/you/.ssh/sock-puppet
    

    This all assumes that you only have one vnc session on server.example.com, otherwise you will have to have a different link for each session.

  3. Create an ssh key specifically for vnc sessions

    In order to make everything automatic in future, generate a key on the local machine, and copy it to the vnc server:

    ssh-keygen -f /home/you/.ssh/id_server.example.com_vnc
    scp /home/you/.ssh/id_server.example.com_vnc.pub server.example.com:.ssh/
    
  4. Force connexions using that key to issue a command

    You now have a public key in /home/you/.ssh/id_server.example.com_vnc.pub; you want to allow connexions from client.example.com using it, and you want to run a command to link the authorisation socket (let’s call it sock-puppet) to /home/you/.ssh/sock-puppet. So add the key to ~/.ssh/authorized_keys with a restriction on which machine can connect using that key and forcing the execution of a particular command:

    echo "from=\"client.example.com\",command=\"/home/you/Scripts/setup-sock-puppet\" \
         $(cat /home/you/.ssh/id_server.example.com_vnc.pub)" \
         >> ~/.ssh/authorized_keys
    
  5. Create the command to link the sock-puppet

    When we connect with vnc [viewer] via ssh, we want to forward the agent; that will set $SSH_AUTH_SOCK for the duration of the ssh connexion, and we want to link to it. So create a shell script, ~/Scripts/setup-sock-puppet

    #!/bin/bash
    # link the current authorisation socket to a well known place
    # overwriting any that lingers from a previous session
    ln -sf $SSH_AUTH_SOCK /home/you/.ssh/sock-puppet
    
    # Now we want to execute the command we would have executed if the
    # authorized_keys file hadn't forced this script to run.
    # It's kept in SSH_ORIGINAL_COMMAND, except that that's
    # empty if it's not specified, so run a shell in that case
    if [ "x$SSH_ORIGINAL_COMMAND" == "x" ]
    then exec bash -i -l
    else exec $SSH_ORIGINAL_COMMAND
    fi
    

    At this point if you ssh from client.example.com to server.example.com using the new key it should put a symbolic link in /home/you/.ssh/sock-puppet

    ssh server.example.com -i /home/you/.ssh/id_server.example.com_vnc -o IdentitiesOnly=yes
    ls -l /home/you/.ssh/sock-puppet
    ⇒ lrwxrwxrwx. 1 you you 30 2009-07-21 21:49 /home/you/.ssh/sock-puppet -> /tmp/ssh-dpjnKl2775/agent.2075=
    
  6. Simplify use of the vnc-specific key

    Use the ~/.ssh/config on your local machine to create a shorthand name to use when connecting to the vnc session. Add the following lines (mutatis mutandis) to the your ~/.ssh/config on your client machine:

    Host server.example.com/vnc
    Hostname server.example.com
    ForwardAgent yes
    IdentitiesOnly yes
    IdentityFile /home/you/.ssh/id_server.example.com_vnc
    LocalForward 5901 localhost:5901
    

    Now a command such as this:

    ssh server.example.com/vnc
    

    will forward a port and set up the link to the sock-puppet so that

    vncviewer localhost:1
    

    connects via ssh to the server machine, where you will have access to your ssh-agent, so that you can ssh from there to somewhere (on it’s local net for example) using a key that you’ve added to the agent on your client machine.

    Better still, if your vncviewer supports the “-via” option, you can skip the ssh command and do this:

    vncviewer -via server.example.com/vnc localhost:1
    

    which fires up a vnc connexion to server.example.com with the sock-puppet set up in one go.

Recorded: 2009-07-21 (this version uploaded 2016-10-20)

home