Monday, May 20, 2013

X11 Forwarding over SSH: run remote graphical app and display locally

In the modern networked environment, we often wish to run an application on a remote host while we are comfortably logged in on our local computer.

Assuming both machines are Linux-based, and the application runs on the graphical X desktop, the following approaches come to mind:

  • VNC
  • X11 forwarding over SSH

This article focuses only on X11 forwarding. X11 forwarding over SSH enables you to run a remote X app and display it locally, with traffic between the 2 hosts encrypted by SSH.

For X11 forwarding over SSH to work, both the SSH client and SSH server must be properly configured.

X11 forwarding must be enabled on The SSH server side. This is the machine where the application resides. To enable the feature, make sure the X11 configuration file /etc/ssh/sshd_config on the server contains this line:

X11Forwarding yes

If you edit the said file, you need to restart the sshd daemon for the change to take effect.

On Debian or Ubuntu systems, you restart the SSH daemon like this:

$ sudo service ssh restart
[ ok ] Restarting OpenBSD Secure Shell server: sshd.
$

On the ssh client side, you need to run SSH command with the proper parameters. For instance, suppose you want to run the xclock application on the remote SSH server and have it displayed back on the local client.

$ ssh -fX peter@192.168.1.112 xclock 
peter@192.168.1.112's password: 
$

The -X parameter allows an one-off X11 forwarding session.

The -f parameter instructs the SSH client to go to the background just before xclock is run.

If you want to permanently enable X11 forwarding for an user, insert this line in the user's own ~/.ssh/config file on the local host.

ForwardX11 yes 

With X11 forwarding permanently enabled for the client, you can leave out the -X parameter:

$ ssh -f peter@192.168.1.112 xclock 
peter@192.168.1.112's password: 
$

If X11 forwarding is not enabled on the SSH server, any attempt to tunnel X11 will fail with the following error message:

$ ssh -X peter@192.168.1.112 xclock 
peter@192.168.1.112's password: 
X11 forwarding request failed on channel 0
Error: Can't open display: 
$
If X11 forwarding is properly enabled on the server side, you will see a nice looking clock displayed on your local screen.

Thursday, May 2, 2013

Forcing pseudo terminal on ssh command execution

You already know how to execute a command on a remote computer via ssh.

The syntax is like this:

$ ssh peter@192.168.1.112 

This will work if the command is simply piping output, for example, ls.

If the command is "screen-based" in that it interprets user input, you may get an error. The following shows what happens when you ssh to run such programs (e.g., top, emacs, screen).

$ ssh peter@192.168.1.112 top
peter@192.168.1.112's password: 
TERM environment variable not set.
$ ssh peter@192.168.1.112 emacs
peter@192.168.1.112's password: 
emacs: standard input is not a tty
$ ssh peter@192.168.1.112 screen
peter@192.168.1.112's password: 
Must be connected to a terminal.

Here is a high-level explanation of what is happening behind the scene.

When you run ssh without a command just to login, a pseudo tty is automatically allocated. But if you specify a command to execute on the ssh command line, by default, ssh does not allocate a pseudo tty. You need to force it to allocate one if you want to run commands such as top or screen. This you do by giving the -t parameter to ssh.

$ ssh -t peter@192.168.1.112 top
peter@192.168.1.112's password: 
top - 11:09:46 up 133 days, 13:44,  5 users,  load average: 0.00, 0.00, 0.00
Tasks: 201 total,   1 running, 200 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.2%sy,  0.0%ni, 99.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1938896k total,  1466144k used,   472752k free,   592508k buffers
Swap:        0k total,        0k used,        0k free,   508120k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
22176 peter     20   0  2856 1296  984 R  0.3  0.1   0:00.07 top
    1 root      20   0  3944  572  332 S  0.0  0.0   0:02.80 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.17 kthreadd
    3 root      RT   0     0    0    0 S  0.0  0.0   0:09.22 migration/0
    4 root      20   0     0    0    0 S  0.0  0.0 406:20.92 ksoftirqd/0
    5 root      RT   0     0    0    0 S  0.0  0.0   0:00.03 migration/0

In summary, if you run ssh with a command argument to execute on a remote server, and you see an error message that suggests a terminal is not configured, run it again with the -t parameter.