Remote Viewing-Not Just a Psychic Power

Most people today are used to having a nice, intuitive graphical environment when they sit down to use a computer. Gone are the days of using a DOS machine or being lucky enough to have a dial-up account at 300 baud on a UNIX mainframe. Today, most people expect to be able to point and click their way to work nirvana, even when that work is being done on some other machine over a network. In this article, I look at some of the available options, what the relative costs and benefits are, and hopefully by the end, you should have enough information to make a choice as to what would be the best option for you.

Before I begin though, I probably should take a look at what actually is involved in using a GUI on Linux. The overwhelming majority of Linux users will be using the X11 Window System (typically shortened to just X11). X11 has been around since 1987. Since then, it has gone through several revisions, and it's currently at R7. Any X11 installation you are likely to encounter will be some version of X11R7. There have been attempts to replace it, including Wayland, Berlin/Fresco and the Y Window System, but they are fairly rare out in the wild, and you'll need to go out of your way to run into them.

X11 is built on a client-server model. In this model, the X11 server is the part that actually draws on a physical screen. As such, it is the part you end up running on your desktop in front of you. The client portion in this model is the user-space program that has output that needs to be seen by the end user.

Figure 1. The X11 Window System (from Wikipedia)

The client does this by sending requests to the X11 server. These are high level and of the form "Draw a window", "Add text to the window border", "Move the window to the right by x pixels". Because of this, there potentially can be a lot of communication if a lot is going on.

When most people experience X11, both parts of this model are running on the desktop in front of them. But, this isn't the only option. There is no reason for the client and server to be on the same machine, or even on the same continent. Because everything is done by sending messages, those messages easily can be sent over a network connection.

The first thought that should come to you is "Hey, I can open a window on my friend's machine and display rude pictures there." Unfortunately, the writers of the X11 specification have beaten you there and closed that particular hole. By default, X11 servers are configured not to accept connections from clients on the network. You have to allow this explicitly. You can use two separate mechanisms to allow external connections. The older one is called xhosts. With xhosts, you tell the X11 server to accept connections from the servers that you permit. The command looks like this:


xhost +111.222.333.444

The newer authentication mechanism is called xauth. In this method, the X11 server creates a cookie that is required in order to connect to the X11 server. If you want to connect to the X11 server from a remote machine, you need to copy this cookie over to the remote machine. An example of doing this, from the xauth man page is:


xauth extract - $DISPLAY | ssh otherhost xauth merge -

This command pulls out the cookie for the current X11 server and "SSHes" it over to the remote machine and merges it into the user's xauth file.

Once you have done this, how do client applications go ahead and connect to your X11 server? All programs that run under X11 accept certain command-line options. One of these is -display. With this option, you can tell your client program to which X11 server to connect and send its output. The general form of this option is:


-display hostname:display#.screen#

The reason for all of the parts of this option is that a given machine could be running more than one X11 server, and each server could be running more than one display screen. The first server and screen is labeled as 0.0, so in most cases you will use:


-display hostname:0.0

As an aside, you can do this on your desktop. If you open a terminal, you can run an X11 client program with:


-display :0.0

and it will show up on your default desktop.

A consequence of this is that you need to have a connection to the remote machine that will be running the client program. Most times, this connection will be over an SSH connection between your local machine and the remote machine. Luckily, SSH provides the ability to tunnel X11 traffic over your SSH connection for you. This tunneling happens "out-of-band", so to speak. You start a session by SSHing in to your remote machine and using either the -X or -Y options. The -X option is the preferred method. It sets up a secure X11 socket on the remote machine using xauth as the authentication system. Unfortunately, some X11 servers have a hard time with this, so you can use -Y. This essentially turns off any authentication. It is equivalent to using xhost +.

Once your SSH connection is established, a new X11 socket is created on the remote machine, and the environment variable DISPLAY is set to point to it. From here on, any X11 applications you start on this remote machine will send their output to your X11 server on your desktop. When you do this, you may notice something. In most cases, it is unbelievably slow—even slower than slow if the machine you are connecting to is any appreciable distance away. Due, in part, to this issue, the SSH developers have included an extra option, -C. This turns on compression of the data traveling over the SSH connection. A side effect is that the packets being sent containing the X11 protocol instructions get bunched together and sent as a single unit. This makes much more efficient use of the bandwidth available, because you are cutting down the amount of control data that also gets sent over the line.

As I mentioned above, both X11 and X11 over SSH are notoriously slow. In some cases, it is nearly unusable. Luckily, there's another option available, VNC. VNC also follows the client/server model, but it reverses the location of the client and server from what you might be used to with X11. With VNC, you run a server out on the remote machine and then use a client on your desktop in front of you. You can run a VNC server in the background, where it sits and acts like any other service. It also doesn't use any of the standard X11 sockets, so it will not interfere with any standard X11 desktop that also may be running on the remote machine. Because it runs as a service, it can continue to run, whether you are connected to it or not. You can think of it as a GUI version of the old standby, screen.

There also are client applications for all the major operating systems, and they are much lighter weight than a full X11 server. So, you can start up vncserver on the remote machine, connect to it from your Windows box, start some long-running process, disconnect and go home, and then check on its progress from your Linux box. This is a great improvement over straight X11. Also, you will notice that in most cases, it is a bit more responsive than X11 was. This is due to the amount of information being sent back and forth between the client and server parts of VNC.

The server command is simply vncserver. When you run this command, a directory named .vnc is created in your home directory if it doesn't exist already. If a password has not been set yet for this instance of the VNC server, it will ask you to enter one. It is saved in the file passwd in encrypted form. If you want to change it, you can use the command vncpasswd. In this directory, you also should find log files for each instance of vncserver that you start, as well as a pid file containing the PID of any currently running instances of vncserver.

The last file of interest is the xstartup file. This is the file that is used when you start vncserver to set up all the required options and also lay out what will be run on the vncserver desktop. The defaults on my Ubuntu system look like this:


#!/bin/sh

xrdb $HOME/.Xresources
xsetroot -solid grey
#x-terminal-emulator -geometry 80x24+10+10 -ls -title 
 ↪"$VNCDESKTOP Desktop" &
#x-window-manager &
# Fix to make GNOME work
export XKL_XMODMAP_DISABLE=1
/etc/X11/Xsession

So in this case, it sets the background to gray and then tries to run whatever session is defined in the global script Xsession. This is where you can do some editing and make it your own. I prefer Fluxbox as a window manager on smaller screens. So you can simplify this to:


#!/bin/sh
xrdb $HOME/.Xresources
startfluxbox

Starting this gives you a nice-looking desktop running Fluxbox. If the client that is going to be connecting to this has to deal with a smaller screen size (like on a Netbook), you can set the desktop size on the command line with the -geometry option. You also can set the color depth of the virtual desktop with the -depth option. So, to set up a server that looks nice when I connect to it from my Netbook, I would use this:


vncserver -geometry 800x600

Now, what about the other end? There are two general classes of vncviewer applications, GUI and command line. The GUI versions, like the most common ones for Mac OS X and Windows, have point-and-click access to all the relevant options. They also have them in different locations, depending on who wrote your particular favorite viewer. Because VNC is a protocol (kind of like FTP or HTTP), there is a great deal of variation in what you get from the various implementers. Let's look at the command-line versions here and see what you can do with those. The GUI versions should have comparable options available. To connect to a vncserver, you would run:


vncviewer hostname:port

where hostname is either the true hostname of the remote machine or its IP address. port is the port number on which the vncserver is listening, starting at 1. This number is added to the default starting port number 5900, so the actual network port number in this case is 5901. This will try to connect to the given server, and it will ask for a password if one had been set during vncserver's startup. Then, you get a nice Fluxbox desktop.

Figure 2. Fluxbox Running under vncserver

There are lots of options for changing various parts of what is being transmitted, such as the encoding algorithm, the compression level and the quality level. Playing with these options can improve your session's responsiveness, potentially at the cost of some image quality. Depending on what work you are trying to do, this may not be a trade-off you are willing to make.

Although you can force some kind of authentication on VNC, that may not be enough in these security-conscious days. You may have to work with a remote machine that sits behind a firewall that allows only SSH traffic. What can you do? VNC allows for tunneling of the protocol over an SSH connection by using the -via gateway option. This gateway machine is the machine that you are SSHing in to for the tunneling. If this is the same machine as your vncserver, the command would look like this:


vncviewer -via user@somehost.com localhost:1

This tells vncviewer to ssh to somehost.com as user "user", then connect to vncserver on the localhost to somehost.com—in other words, somehost.com itself. There is no reason that these need to be the same machine. This means you could connect to a vncserver on a machine behind a security gateway machine. In this case, it would look like this:


vncviewer -via user@gateway.com someotherhost.com:1

Be aware that VNC still will ask you to authenticate after the SSH session has been established.

Conclusion

Hopefully, this article has provided some options for those times when you just can't live without a nice graphical interface. Even when you are forced to squeeze through an SSH connection, you still can have all of that great GUI goodness. If you know of other ways of getting a graphical interface on a remote machine, I would love to hear about them.

Load Disqus comments