Dustin Boswell - Brain Dumps about Computers, Programming, and Everything Else
dustwell.com About Me Past Academic Work
Blog Posts How to hash passwords Snapshotting with Rsync "An hour" vs. "A hour" Yes/No proposition bets div, span, and CSS "display:" Pair programming + screen SSH keys in 2 easy steps Fixing Your Flaky Internet How X-over-SSH works Drinking Distilled Water djb-dns installation Vim Cheat Sheet Oil ETFs leak money
How X Over SSH really works September 27, 2008
Imagine you are sitting in front of a machine named "home" that has a keyboard, mouse, display, and is running an X server. Now you open a terminal and ssh to a machine called "remote" (which doesn't need to have an X server running), and run a program like "firefox" which pops a window in your screen. How does this all work?

First, let's clear up the client/server terminology confusion. When talking about X:
Whenever an X client starts up, it reads the local $DISPLAY environment variable, whose value looks like: [hostname]:display_number[.screen_number]. The X client immediately opens a connection to that X server. If it can't, it fails:

user@home: echo $DISPLAY
:0 # hostname is "localhost" by default
@home: xcalc # pops up a calculator on my screen
user@home: DISPLAY="nosuchhost:99"
user@home: xcalc
Error: Can't open display: nosuchhost:99

Now let's see what happens when you ssh to another machine:

user@home: ps aux | grep X # yep, X server running @home
root ... /usr/bin/X :0 ...
user@home: ssh -X user@remote # -X enables X-forwarding
user@remote: ps aux | grep X # nope, no X server here
user@remote: echo $DISPLAY
user@remote: xcalc # pops up screen @home

Wait a minute, the $DISPLAY variable is pointing to the localhost ("remote"). Natural questions to ask at this point:
The answer has to do with the ssh-daemon running @remote:

user@remote: ps aux | grep user
root ... sshd:user@pts/11

What's happening is that there's an "X emulator" running @remote that was setup just for your ssh session, that is listening on display 11.

To review, here's a play-by-play:
  1. You type "ssh -X user@remote" in your terminal
  2. The ssh process connects to the sshd server @remote.
  3. sshd spawns a new process that is an X-server-emulator listening on some display number, e.g. "11"
  4. sshd sets the $DISPLAY to point to that local "X-server" (e.g. ":11")
  5. xcalc reads this $DISPLAY and conncects to this X-server. xcalc thinks it's displaying to the local machine.
  6. the X-server-emulator simply forwards the X commands from xcalc through the ssh connection, to the original ssh process.
  7. The ssh process @home now acts as a normal X-client and sends those commands to the X-server @home.

Some of you might be wondering: wasn't the X protocol designed to go over the network? Can't you do all this without ssh? You might be tempted to try something like:

user@remote: DISPLAY="home:0"
user@remote: xcalc

This doesn't work because the X server @home won't let other hosts connect to it. To change this (not that you should -- see below) you can do:

user@home: xhost +remote

xhost is a command which says "that host can connect to our X-server". However, everybody uses ssh X forwarding instead. Here are some security reasons why:
There's also an issue with firewalls: by doing "DISPLAY=home:0", you're assuming that a connection can be established from remote -> home. But this isn't always possible -- home might be sitting behind a firewall (like your Netgear router). Since the ssh-connection was setup from home-> remote, it takes advantage of this already-established connection.

Other notes for the curious:
- if $DISPLAY is set to "localhost:0" (or any explicitly named host) it uses tcp-ip to send the X-traffic locally.
- if $DISPLAY is just ":0" it uses a special (more efficient, non-tcp-ip) connection.
blog comments powered by Disqus