46

I have hosts A,B and C. From host A I can access through ssh only B. From B I can access C. I want to be able to run X11 programs on C and forward display to A.

I tried this:

A$ ssh -X B
B$ ssh -X C
C$ xclock
Error: Can't open display:

But it doesn't work.

8 Answers 8

33

There are several ways to do this, the one I prefer is to forward the ssh port:

First, connect to machine B and forward [localPort] to C:22 through B

A$ ssh -L [localPort]:C:22 B

Next, connect to C from A through this newly-created tunnel using [localPort], forwarding X11

A$ ssh -X -p [localPort] localhost

Now we can run X11 programs on C and have them display on A

C$ xclock

[localPort] can be any port that you are not already listening to on A, I often use 2222 for simplicity.

4
  • 6
    not exactly... if X11Forwarding is not enabled on server C, it won't work. it also won't work unless one sets AllowTcpForwarding yes and GatewayPorts yes on server B. this answer is not acceptable at all
    – asdmin
    Aug 12, 2009 at 7:02
  • You make a good point, I did not notice this since I use debian, on which X11Forwarding and AllowTcpForwarding are enabled by default. GatewayPorts is not needed since when it is disabled, SSH still listens on localhost and that is what we are connecting to. You would only need it if you wanted to make the second connection via an external IP for machine A.
    – dave
    Aug 12, 2009 at 22:48
  • On step 1, it didn't ask me the password for host B, and I end up connected in host C. In another window I tried step 2 and I get "ssh_exchange_identification: Connection closed by remote host".
    – msb
    Mar 21, 2018 at 0:13
  • ssh: connect to host ... port 22: Connection refused while executing the first command Sep 1, 2018 at 15:34
8

Have you tried with

A$ ssh -Y B
B$ ssh -Y C
C$ xlclock

The -Y flag "Enables trusted X11 forwarding."

3
  • The same result.
    – lexsys
    Aug 12, 2009 at 6:13
  • 2
    This worked for me, but only to discover how slow is X11 Sep 1, 2018 at 16:10
  • add also -C (compression). much faster
    – sivann
    Nov 4, 2022 at 12:42
8

This can easily be accomplished using port forwarding:

A$ ssh -NL 2022:C:22 B &
A$ ssh -X -p 2022 localhost
C$ xclock

Port localhost:2022 is forwarded to C:22 via B SSH to C via localhost:2022 Use X as normal

2
  • 2
    This won't work for the same reasons noted elsewhere in case B (the gateway) does not have the correct sshd forwarding options enabled.
    – user7835
    Jun 3, 2014 at 8:24
  • didn't ask for my password to host B, which is weird; and it didn't work, I got the error message "channel 2: open failed: administratively prohibited: open failed ssh_exchange_identification: Connection closed by remote host"
    – msb
    Mar 21, 2018 at 0:10
5

For newer versions opensshd you have to disable X11UseLocalhost for this to work.

You need to do this on Host C's /etc/ssh/sshd_config and restart sshd for this to work:

X11Forwarding yes
X11UseLocalhost no
4

Assuming the problem is that the middle machine doesn't have X, but it otherwise configured to allow forwarding X11, just install xauth.

on a yum-based system (fedora, redhat, centos):

B$ sudo yum install xauth

on an apt-based system (debian, ubuntu):

B$ sudo apt-get install xauth
4
  • Yay- perfect for headless raspberry pi.
    – cmc
    Apr 21, 2018 at 22:53
  • @cmc or using ssh like a vpn.
    – Jayen
    Apr 22, 2018 at 2:31
  • @cmc do you have yum on a pi?
    – Jayen
    Apr 22, 2018 at 2:31
  • nope- sudo apt-get install xauth
    – cmc
    Apr 22, 2018 at 12:13
3

If you often go from A to C, you can configure B as a proxy:

A:~/.ssh/config:

Host C
  ForwardX11   yes
  ProxyCommand ssh -W %h:%p B

then it's just:

A$ ssh C xclock
2

You could combine -Y/-X command with the -J command line option:

A$ ssh -Y user@C -J user@B
C$ xclock

If you have more Hosts to hop than just do the following:

A$ ssh -Y user@C -J user@B,user@D,...,user@Z
C$ xclock

From man ssh:

-J [user@]host[:port]
     Connect to the target host by first making a ssh connection to
     the jump host and then establishing a TCP forwarding to the
     ultimate destination from there.  Multiple jump hops may be
     specified separated by comma characters.  This is a shortcut to
     specify a ProxyJump configuration directive.

It was introduced in OpenSSH version 7.3 (released in August 2016).

1

You can't forward X11 display if you have X11Forwarding disabled in any sshd you are using.

man sshd_config:

X11Forwarding
  Specifies whether X11 forwarding is permitted. The argument must be “yes”
  or “no”.  The default is “no”.

You have to make sure X11Forwarding is enabled on destination and all intermediate sshds you are using.

Just a small hint: you should try to use VNC, X11 display forwarding is quite bandwidth consuming.

5
  • @AgentK's and @dave's suggestions only require X11Forwarding to be enabled on the final host, as they use an SSH tunnel to bypass the intermediate host. Your suggestion is almost definitely why the OP's method failed at first, but that doesn't mean other people's answers "are not acceptable" Aug 12, 2009 at 9:36
  • their answers were defective and remedied the problem, not solving it. a right and useful answer would consider the original question and solving it, and providing other ways only in case the originals question is not solvable. by the way, neither of them mentioned X11Forwarding, which is essential
    – asdmin
    Aug 12, 2009 at 10:31
  • On some systems the default is "yes". Aug 14, 2009 at 20:09
  • I checked, that X11Forwarding is enabled on B and C and AllowTcpForwarding is set to yes on B. But the result of my commands is the same. And dave's answer works fine for me.
    – lexsys
    Aug 19, 2009 at 6:02
  • then do that, but it's only a remedy. you also can start ssh with parameter '-v', or try echo $DISPLAY all the nested ssh commands to find it out where $DISPLAY get lost
    – asdmin
    Aug 19, 2009 at 6:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .