X Forwarding
Now that you've seen general TCP port forwarding, we move to a new topic: forwarding of X protocol connections. X is a popular window system for Unix workstations, and one of its best features is its transparency. Using X, you can run remote X applications that open their windows on your local display (and vice versa, running local applications on remote displays). Unfortunately, the inter-machine communication is insecure and wide open to snoopers. But there's good news: SSH X forwarding makes the communication secure by tunneling the X protocol.X forwarding also addresses some firewall-related difficulties. Suppose you're a system administrator with a set of exposed production machines on the other side of a firewall from you. You log into one of these machines using SSH, and want to run an graphical performance-monitoring tool, such as Solaris'sperfmon
, that uses the X Window System. You can't, though, because to do that, the external machine needs to make a TCP connection back to the internal machine you started on, and the firewall blocks it (as it should, since X is quite insecure). X forwarding solves this problem, permitting X protocol connections to pass through the firewall, securely tunneled via SSH.Our discussion begins with a brief overview of X and then explains the details of X forwarding. In addition to explaining how to use X forwarding, we also expose the internals of X authentication and how it interacts with SSH, as well as other technical topics.
VNC Forwarding: An Alternative to X Forwarding
X forwarding is problematic from a security point of view, for the same reason as X itself. As we will see, the design of X means that remote programs must make separate network connections back to the user; this requires yet another layer of authentication and authorization, complicating the situation and opening an avenue of attack. SSH X forwarding tries to secure this as much as possible, but it may still be unacceptable in some environments.An alternative technique is to use Virtual Network Computing (VNC) over SSH. VNC is free software developed by AT&T Laboratories in the United Kingdom, which provides remote GUI access for Unix and Windows platforms. With VNC, you can open a window on your Unix machine running X and have the desktop of a remote Windows machine appear there, so you can operate the Windows box remotely. Conversely, you can run the VNC client on a Windows machine and connect to a remote X display running on a Unix host. Since VNC involves only a single outbound connection, it is easier and safer to tunnel through SSH than X. You can find out more about VNC (and download the software) at:http://www.uk.research.att.com/vnc/
The X Window System
The X Window System, or X, is the most widely used graphical display system for Unix machines. Like SSH, X has clients and servers. X clients are windowing application programs, such as terminal emulators, paint programs, graphical clocks, and so forth. An X server is the underlying display engine that processes requests from X clients, communicating via a network protocol called the X protocol. A machine typically runs a single X server but possibly many X clients.Most important to our discussion, X supports sophisticated window management over a network. X clients can open windows not only on their local machine but also on other computers on the network, whether they are down the hall or across the globe. To accomplish this, an X client makes a network connection to a remote X server and carries on a conversation, using the X protocol to draw on the remote screen, receive remote keyboard events, learn the remote mouse location, and so on. This obviously requires some type of security, which we discuss soon.A central concept of X is the display, an abstraction for the screen managed by an X server. When an X client is invoked, it needs to know which display to use. Displays are named by strings of the form HOST:n.v, where:- HOST is the name of the machine running the X server controlling the display.
- n is the display number, an integer, usually 0. X allows for multiple displays controlled by a single server; additional displays are numbered 1, 2, and so on.
- v is the visual number, another integer. A visual is a virtual display. X supports multiple virtual displays on a single, physical display. If there's only one virtual display (which is the most common scenario), you omit the ".v", and the default is visual 0.
xterm
on the only X display of the workstation anacreon, use the command-line option:
$ xterm -d anacreon:0 &
or the environment variable:
$ setenv DISPLAY anacreon:0 $ xterm &
X is a large, deep software product whose documentation fills a dozen Anonymous tutorials. We've barely scratched the surface with our explanation, but you've now seen enough to understand X forwarding.
How X Forwarding Works
Although X clients can communicate with remote X servers, this communication isn't secure. All interactions between the X client and server, such as keystrokes and displayed text, can be easily monitored by network snooping because the connection isn't encrypted. In addition, most X environments use primitive authentication methods for connecting to a remote display. A knowledgeable attacker can get a connection to your display, monitor your keystrokes, and control other programs you're running.Once again, SSH comes to the rescue. An X protocol connection can be routed through an SSH connection to provide security and stronger authentication. This feature is called X forwarding.X forwarding works in the following way. (As illustration, please refer to Figure 9-10.) An SSH client requests X forwarding when it connects to an SSH server (assuming X forwarding is enabled in the client). If the server allows X forwarding for this connection, your login proceeds normally, but the server takes some special steps behind the scenes. In addition to handling your terminal session, it sets itself up as a proxy X server running on the remote machine and sets the DISPLAY environment variable in your remote shell to point to the proxy X display:syrinx$ ssh sys1 Last login: Sat Nov 13 01:10:37 1999 from blackberry Oracle Inc. SunOS 5.6 Generic August 1997 You have new mail. sys1$ echo $DISPLAY sys1:10.0 sys1$ xeyes The "xeyes" X client appears on the screen

Figure 9-10. X forwarding
The DISPLAY value appears to refer to X display #10 on sys1, but there's no such display. (In fact, there might be no true displays on sys1 at all.) Instead, the DISPLAY value points to the X proxy established by the SSH server, i.e., the SSH server is masquerading as an X server. If you now run an X client program, it connects to the proxy. The proxy behaves just like a "real" X server, and in turn instructs the SSH client to behave as a proxy X client, connecting to the X server on your local machine. The SSH client and server then cooperate to pass X protocol information back and forth over the SSH pipe between the two X sessions, and the X client program appears on your screen just as if it had connected directly to your display. That's the general idea of X forwarding.X forwarding can even solve the firewall problem mentioned earlier, as long as the firewall permits SSH connections to pass through. If a firewall sits between your local and remote machines, and you run an X client on the remote machine, X forwarding tunnels the X connection through the firewall's SSH port to the local machine. Therefore, the X client's windows can open on your local display. If X forwarding isn't present, the firewall blocks the connection.Some aspects of X forwarding probably sound familiar from our earlier explanation of port forwarding. In fact, X forwarding is just a special case of port forwarding for which SSH has special support.Enabling X Forwarding
X forwarding is on by default in SSH1 and SSH2, but off in OpenSSH. If you need to enable or disable X forwarding for your clients, here's how to do it. Unlike general port forwarding, which requires you to fiddle with TCP port numbers, X forwarding has only an on/off switch. In your SSH client configuration file, use the keywordForwardX11
with a value yes
(the default, to enable) or no
(to disable):
# SSH1, SSH2, OpenSSH ForwardX11 yes
On the command line, you may also use -x to disable X forwarding:
# SSH1, SSH2, OpenSSH $ ssh -x server.example.com
SSH2 and OpenSSH enables X forwarding with the following options:
# SSH2 only $ ssh2 +x server.example.com # OpenSSH only $ ssh -X server.example.com
Configuring X Forwarding
The behavior of X forwarding can be modified through compile-time configuration, serverwide configuration, and per-account configuration.Compile-time configuration
SSH1 and SSH2 can be compiled with or without X support. The compile-time flags--with-x
and -- without-x
make this determination:
# SSH1, SSH2 $ configure ... --without-x ...
In addition, if you compile with X support, you may set the default behavior for X forwarding. In SSH1, you can enable or disable forwarding by default in the client and the server separately, using the compile-time flags
-- enable-client-x11-forwarding
(or -- disable-client-x11-forwarding
) and -- enable-server-x11-forwarding
(or -- disable-server-x11-forwarding
):
# SSH1 only $ configure ... --disable-server-x11-forwarding ...
In SSH2, you can enable or disable all X forwarding by default with
-- enable-X11-forwarding
or -- disable-X11-forwarding
:
# SSH2 only $ configure ... --enable-X11-forwarding ...
Remember, enable/disable flags simply set the default behavior. You can override these defaults with serverwide and per-account configuration.
Serverwide configuration
The serverwide configuration keywordsX11Forwarding
(SSH1, SSH2, OpenSSH) and its synonyms ForwardX11
(SSH2) and AllowX11Forwarding
(SSH2) enable or disable X forwarding in the SSH server. By default, it is enabled:
# SSH1, SSH2, OpenSSH X11Forwarding no # SSH2 only: either will work ForwardX11 no AllowX11Forwarding no
The
X11DisplayOffset
keyword lets you reserve some X11 display numbers so sshd
can't use them. This keyword specifies the lowest display number SSH may use, preventing sshd
from clashing with real X servers on the lower-numbered displays. For example, if you normally run actual X servers on displays and 1, set:
# SSH1, OpenSSH X11DisplayOffset 2
The
XAuthLocation
keyword specifies the path to the xauth
program, which manipulates authorization records for X. We describe this keyword later, after we discuss xauth
. ["Location of the xauth program"]
# SSH1, OpenSSH XAuthLocation /usr/local/bin/xauth
Per-account configuration
In your SSH1 or OpenSSH authorized_keys file, you may disallow X forwarding for incoming SSH connections that use a particular key for authentication. This is done with the optionno-X11-forwarding
: ["Disabling Forwarding "]
# SSH1, OpenSSH no-X11-forwarding rest of key...
X Authentication
We've mentioned in passing that X performs its own authentication when X clients connect to X servers. Now we're going to dive into technical detail on the inner workings of X authentication, why it's insecure, and how SSH X forwarding builds on it to create a secure solution.In most cases, X forwarding simply works, and you don't have to think about it. The following material is to aid your understanding and satisfy any intense cravings for tech talk (both yours and ours).How X authentication works
When an X client requests a connection to an X server, the server authenticates the client. That is, the X server determines the client's identity to decide whether to allow a connection to the server's display. The current release of the X Window system (X11R6) provides two categories of authentication: host-based and key-based:- Host-based X authentication
- The simpler method. Using the program
xhost
, you indicate a list of hosts that may connect to your X display. Notice that connections are authenticated only by hostname, not by username. That is, any user on a listed host may connect to your display. - Key-based X authentication
- Uses the xauth program to maintain a list of X authentication keys, or display keys, for X clients. Keys are kept in a file, usually ~/.Xauthority, along with other data associated with the various displays the client wants to access. When an X client connects to a server requiring authentication, the client supplies the appropriate credentials for that display from the xauth data. If authentication is successful, the X client can then connect to the display managed by the X server.
xinit
or startx
, these programs invoke an X server and insert a copy of the server's key directly into your xauth data. Alternatively, if you connect to a remote machine that runs the X Display Manager (XDM), the key is sent to your remote account when establishing your XDM session.
xauth and the SSH rc files
SSH has startup files that can be set to execute on the server side when a client logs in. These are the systemwide /etc/sshrc and the per-account ~/.ssh/rc. These can be shell scripts or any kind of executable program.An important thing to note is thatsshd
runs xauth
only to add the proxy display key if it doesn't run an rc program. If it does run an rc program, it feeds the key type and data to the program on a single line to its standard input, and it is up to the rc program to store the display key. This feature provides a way to customize handling the display key, in case just running xauth
isn't the right thing to do in your situation.
Problems with X authentication
If you've used X, the authentication was probably transparent and seemed to work fine. Behind the scenes, however, the mechanism is insecure. Here are the major problems:- xhost is insecure
- Once you give permission for a remote host to connect to your display, any user on that host can connect. As with the r-commands, this authentication method depends on the network address of the connecting host, which can be easy for an attacker to usurp.
- Key transfer may be manual and insecure
- Some remote-login protocols, such as telnet, don't assist with X authentication. If your display keys aren't available on a remote machine, you have to transfer them yourself, either manually or by automating the transfer, perhaps in your login script. This isn't only a nuisance but also insecure, since you're sending the key in plaintext over the network.
- The most common key-based method, MIT-MAGIC-COOKIE-1, is insecure
- Although it uses a random string of bits, or cookie, as the xauth display key, this key is transmitted in plaintext at the beginning of every connection, where it can be intercepted and read.
- The remote host might not support your chosen X authentication method
- X11R6 supports other, more secure authentication methods. SUN-DES-1 employs Sun's secure RPC system, XDM-AUTHORIZATION-1 uses DES, and MIT-KERBEROS-5 involves Kerberos user-to-user authentication.[126] Unfortunately, these methods are often not available in particular instances of the X software. Sometimes they aren't compiled into X installations due to cryptographic export restrictions; other times, the X version is too old to support the more secure methods.
[126]See the X11R6 Xsecurity (1) manpage for details on these methods. Also, remember that this is authentication only, not encryption. The contents of your X connection remain unencrypted and open to snooping or modification on the network.
- If the remote host is insecure, your display key can be compromised
- In the best scenario, where the X server supports strong authentication and your key can be copied securely to the remote machine, you still have to store your sensitive display key there. If that machine is untrustworthy, your key can be at risk. (SSH doesn't have this problem, since only your public key is stored on the SSH server machine.)
SSH and authentication spoofing
Through X forwarding, SSH provides transparent, secure authentication and key transfer for X sessions. This is done by a technique called authentication spoofing, as depicted in Figure 9-11. Authentication spoofing involves a fake display key, which we call the proxy key, that authenticates access to the SSH X proxy server on the remote side. When relaying X traffic containing a key, SSH cleverly substitutes the real display key. Here's how it works.
Figure 9-11. Authentication of forwarded X connections
The players begin in the following positions. You are logged into a local machine with a local display. The local machine runs an X server and SSH clients. On the other side of the network connection, an SSH server is running on a remote machine, where you invoke X clients. The goal is for the remote X clients to appear on your local display by way of SSH.First, you run a local SSH client, asking it to set up X forwarding. The SSH client requests X forwarding from the remote SSH server, and it also reads your local display key from your .Xauthority
file.Next, the SSH client generates a proxy key. This is a string of random data of the same length as your local display key. The SSH client then sends the proxy key and its key type (e.g., MIT-MAGIC-COOKIE-1) to the remote machine, and the SSH server runs the xauth program on your behalf to associate the proxy key with your local display. The stage is now set for X forwarding.When you start a remote X client, your local SSH client connects to your local X display. It then watches for the first X protocol message sent over the forwarded connection and treats it specially. Specifically, the SSH client parses the message, finds the X authentication key inside it, and compares it to the proxy key. If the keys don't match, the SSH client rejects and closes the connection. Otherwise, if the keys match, the SSH client substitutes the real display key in place of the proxy key and relays the modified message to your local X server. The X server, blissfully unaware that a key switch has taken place, reads the display key and proceeds normally with X authentication. The forwarded X connection is now established.X forwarding with authentication spoofing solves all but one of the X authentication problems we raised earlier:
- xhost
- X forwarding doesn't use xhost. (By the way, make sure to disable all xhost permissions when using X forwarding, or you will undermine the X security provided by SSH.)
- Key transfer
- SSH transfers the X display key automatically and runs xauth on your behalf to install it on the remote side. The transfer is secure since the key travels over the encrypted SSH connection.
- MIT-MAGIC-COOKIE-1 insecurity
- The key transmitted at the beginning of every X session is now encrypted, along with the rest of the X traffic, inside the SSH session. This greatly increases the operational security of this common X authentication scheme.
- Untrustworthy remote hosts
- With authentication spoofing, only the proxy key, not the true display key, is sent to the remote host. The proxy key is good only for connecting to your display through SSH, not for connecting to your display directly. As soon as your SSH session ends, the proxy key becomes useless. Since SSH sessions come and go, but some people leave their X sessions up (with the same key) for days, X forwarding can be a great improvement.
Improving authentication spoofing
The remaining problem with X forwarding is the possibility of unsupported X authentication mechanisms. The local side can use a more sophisticated authentication method a remote host might not support.In theory, SSH X forwarding can solve this problem by always installing a proxy key of type MIT-MAGIC-COOKIE-1, no matter what local authentication method is actually in use. After the SSH client has checked the X client's key against the proxy key for a match, its client could then generate and substitute whatever local authenticator is required using the true authentication type and key.Unfortunately, SSH implementations don't go this far. The server compares keys literally as bit strings, and the SSH client substitutes keys verbatim, regardless of the key types. As a result, if you use a stronger X authentication method such as XDM-AUTHORIZATION-1,sshd
blindly compares an encrypted authenticator with the proxy key, rightly determine that they don't match, and invalidly rejects the connection. The failure is silent and mysterious; we wish the software would detect the presence of an unsupported mode and issue a warning when setting up the connection.If SSH knew the details of all X authentication modes, it could check the proxy authenticators on one side and generate correct ones for the X server on the other. However, this is a significant development effort, though perhaps one could link SSH against the X11 libraries to obtain the necessary algorithms. SSH would also have to deal with differing key data lengths, constructing a new X message to hold the proxy key instead of copying it to an existing message.It would also be useful if X forwarding could be used without authentication spoofing. Then you could arrange your own security for the connection by, say, using xhost to allow any connection from your local machine (and hence the SSH X proxy), while still applying key-based authentication to X connections originating from elsewhere. You can accomplish this with general port forwarding, as discussed in the next section, but direct support is more convenient.
Nonstandard X clients
X clients generally do Xxauth
-style authentication by virtue of having been linked against Xlib, the common X developing library. Occasionally, though, you run across particular X client programs that don't use Xlib and simply ignore authentication issues. Since you can't turn off SSH X authentication spoofing, you can't use such programs across SSH X forwarding; you get this message:
X11 connection requests different authenticationprotocol: 'MIT-MAGIC-COOKIE-1' vs. ''
You can, however, use a general port forwarding instead. For example:
foo% ssh -R6010:localhost:6000 bar bar% setenv DISPLAY bar:10
Note that this bypasses the discipline imposed by X forwarding, of requiring
xauth
authentication on forwarded X connections. If your real X server is using xhost
for access control, this port forwarding allows anyone on host foo to connect to your X server. Use this sort of thing with caution if you need to.
Further Issues
As we've said, X forwarding usually works fine without any special effort on your part. In some special situations, however, you might need to take some extra steps.X server configuration
In order for X forwarding to work, your X server must accept the proxy X connections from your SSH client. This is sometimes not set up to begin with, because normal use doesn't require it. For example, if you're using an X server on a PC to access a remote Unix machine via XDM, you might never run local X clients at all, and they may not be allowed by default. You can runxhost
+localhost
to allow all connections from the your PC, while still applying key-based authentication to connections from other sources. This allows SSH-forwarded (and authenticated) connections to be accepted.
Setting your DISPLAY environment variable
SSH sets the DISPLAY variable automatically only if X forwarding is in effect. If you don't use X forwarding but want to use X on a remote machine you logged into via SSH, remember that you have to set the DISPLAY variable yourself. You should only do this when the both machines are on the same, trusted network, as the X protocol by itself is quite insecure.Be careful not to set DISPLAY unintentionally! It is common for people to set the DISPLAY variable in a login command file or by other means. If you're not careful, this can make your X connections insecure without your noticing. If you use SSH to tunnel through a firewall that blocks normal X connections, then of course you'll notice because your X clients won't work. But if normal X connections are possible but undesirable, and X forwarding isn't in effect, your X programs will work but will (silently) not be secured. This is a good reason to block X traffic at the firewall if it presents a security risk or to configure your X server to accept connections only from the local host (the source of the SSH-forwarded X connections). If that's not feasible, you may want to put something like this in your login script:#!/bin/csh if ($?DISPLAY) then set display_host = `expr "$DISPLAY" : '\(.*\):'` set display_number = `expr "$DISPLAY" : '.*:\([^.]*\)'` set my_host = `hostname` set result = `expr '(' "$display_host" = "$my_host" ')' '&' '(' \ "$display_number" '>' "0" ')'` if ($result == 0) then echo "WARNING: X display $DISPLAY does not appear to be protected by SSH!" echo "unsetting DISPLAY variable just to be safe" unsetenv DISPLAY endif endif
Shared accounts
If you share a single account among multiple people, you may have some trouble with X forwarding. For example, it is common for a group of sysadmins to share use of the root account. For each person to retain their own environment when using the root account, they may set their USER, LOGNAME, and HOME environment variables explicitly to reflect their personal accounts rather than the root account. If you use SSH to log into the root account with X forwarding turned on, though, it adds the proxy xauth key to root's Xauthority file before the shell reads your login script and resets these environment variables. The result is that once you're logged in and try to use X, it fails: the X client looks in your Xauthority file (because of the setting of your HOME variable), but the key isn't there.You can deal with this problem by setting the XAUTHORITY variable to point to root's Xauthority file, or by using code like the following in your login script to copy the needed key into your personal one:if (($uid == 0) && ($?SSH_CLIENT) && ($?DISPLAY)) then # If I do ssh -l root with X forwarding, the X proxy server's xauth key # gets added to root's xauth db, not mine. See if there's an entry for my # display in root's xauth db... set key = `bash -c "xauth -i -f /.Xauthority list $DISPLAY 2> /dev/null"` # ... and if so, copy it into mine. if ($? == 0) then xauth -bi add $key chown res ~res/.Xauthority >& /dev/null endif endif
Location of the xauth program
Remember thatsshd
runs the xauth program on your behalf, to add the proxy key to your Xauthority file on the remote side. The location of the xauth program is discovered when you configure the SSH package and compiled into the sshd
executable. If xauth is subsequently moved, X forwarding won't work (ssh -v
reveals this explicitly). For SSH1 and OpenSSH, the system administrator on the server side can use the serverwide configuration keyword XAuthLocation to set the path to the xauth
program without having to recompile sshd1
:
# SSH1, Open SSH XAuthLocation /usr/local/bin/xauth
XAuthLocation
can also appear in the client configuration file (OpenSSH only); the client uses xauth to get the local X display key.
X forwarding and the GatewayPorts feature
TheGatewayPorts
(-g) feature discussed earlier applies only to general port forwarding, not to X forwarding. The X proxies in SSH1, SSH2, and OpenSSH always listen on all network interfaces and accept connections from anywhere, though those connections are then subject to X authentication as described earlier. To restrict X client source addresses, use TCP-wrappers, which we discuss in the next section.