Tunneling X Connection Through Intermediate Linux / BSD Gateway

Posted on in Categories , , , , , , , , , , , , , , last updated May 7, 2009

I‘ve ssh gateway behind my NAT firewall. So all users must first login to my gateway host from the internet and then login to other machines on the LAN. This works great for cli based apps. However, few users would like to run x apps from internal LAN hosts and tunnel X display through intermediate ssh gateway and display back output on their local system. For example, from localsystem user makes connection as follows:

ssh -X [email protected]
ssh -X [email protected]

X forwarding fails with an error:

Error: Can’t open display:

How do I fix this problem and allow users to use X apps with my intermediate Linux / BSD gateway?

You need to use ProxyCommand in your $HOME/.ssh/config for the external host connecting via the Internet. It specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed with the user’s shell. In the command string, %h will be substituted by the host name to connect and %p by the port. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an sshd server running on some machine, or execute sshd -i somewhere. Host key management will be done using the HostName of the host being connected (defaulting to the name typed by the user). Setting the command to none disables this option entirely.

You need to use this directive in conjunction with nc and its proxy support. For example, the following directive would connect via an HTTP proxy at at port 3128:

ProxyCommand /usr/bin/nc -X connect -x %h %p

Open $HOME/.ssh/config:
$ vi $HOME/.ssh/config
Modify / add configuration as follows:

Host internal
        Hostname somelan.example.com
        HostKeyAlias proxy
        User vivek
        # ProxyCommand ssh gw.nixcraft.in nc %h %p 2> /dev/null
        ProxyCommand ssh gateway.example.com "/usr/bin/nc internal 22"

Save and close the file.

  • Host internal – Restricts the following declarations (up to the next Host keyword) to be only for those hosts that match one of the patterns given after the keyword.
  • ProxyCommand – Used nc command to Proxy your SSH session to internal system through gateway.
  • User – Specifies the user to log in as. In our example login as vivek.
  • HostKeyAlias – Specifies an alias that should be used instead of the real host name when looking up or saving the host key in the host key database files. This line can be commented out.

Now, user can login and run X apps:
$ ssh -X [email protected]
$ ssh -X [email protected]
$ xeyes &

See ssh_config man page for further details.

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on Twitter, Facebook, Google+.

5 comment

  1. I do a similar thing to access my linux boxes behind a linux firewall at home. In this case ‘defender’ being the firewall and ‘digdug’ the server I want to ssh to, yes yes – 80’s arcade theme for server names. :)

    ssh -t defender ssh digdug
    xterm &

    I have used the ‘-t’ option to do this through 4 servers as well.

  2. some occations using “ssh -X yadayada” i’d have some autentication troubles …overall with old version of x11 ..troubles are about mit cookies stuff …for this kind of case are very usefull use “ssh -Y yadayada”

Leave a Comment