Many developers encounter this scenario when working with remote servers:
Local Machine (A) → Jump Server (B) → Target Server (C)
While basic SSH connections work fine, X11 forwarding breaks in this chain. Your display gets lost after the first hop because:
- Each SSH connection creates its own DISPLAY environment variable
- The X11 forwarding channel isn't properly propagated
- Authentication cookies aren't transferred between hops
Method 1: Single Command with ProxyJump /h2>
Modern OpenSSH (7.3+) supports ProxyJump:
ssh -J user@B -X user@C
This establishes a direct tunnel from A to C through B with proper X11 forwarding.
Method 2: Manual Multi-Hop Configuration /h2>
For older SSH versions, configure your ~/.ssh/config:
Host ServerB HostName B.example.com User bob ForwardX11 yes ForwardX11Trusted yes Host ServerC HostName C.example.com User charlie ProxyCommand ssh -W %h:%p ServerB ForwardX11 yes ForwardX11Trusted yes
Now connect with:
ssh -Y ServerC xclock & # Should display on your local machine
If you still get "Can't open display" errors:
# On each server in the chain, verify: echo $DISPLAY # Should show something like localhost:10.0 # Check X11 forwarding is enabled: ssh -v -X user@host 2>&1 | grep -i x11 # Verify xauth is installed: which xauth
- Use
-Y
(trusted) only when necessary - it bypasses some security checks - For sensitive environments, consider alternatives like VNC or noMachine
- Monitor your X11 connections with
xlsclients
For better performance over slow connections:
ssh -XC -c blowfish-cbc,arcfour user@host
This enables compression and faster cipher algorithms.
When working with nested SSH connections, X11 forwarding can break in unexpected ways. Consider this common setup:
- Local machine (Host A) can only directly SSH to Host B
- Host B can SSH to Host C (your target machine)
- You want to run GUI applications on C and see them on A
The straightforward method doesn't work:
A$ ssh -X B
B$ ssh -X C
C$ xclock
Error: Can't open display:
The issue occurs because:
- The DISPLAY variable isn't properly forwarded through multiple hops
- Xauth cookies aren't being transferred correctly
- SSH creates new X11 forwarding channels at each hop
Modern SSH versions (7.3+) support the ProxyJump directive:
ssh -J B -X C
This establishes a direct tunnel from A→C through B while maintaining X11 forwarding.
For older SSH versions, set up forwarding manually:
A$ ssh -X -t B ssh -X C
The -t
flag forces pseudo-terminal allocation, which is often needed for interactive sessions.
Check these components:
# On each host:
echo $DISPLAY
# Should show localhost:10.0 or similar
xauth list
# Should show matching entries across hosts
- X11Forwarding yes must be set in /etc/ssh/sshd_config on all servers
- Firewalls must allow TCP connections on display ports
- Try using
-Y
instead of-X
for trusted forwarding
Add to your ~/.ssh/config:
Host C
HostName c.example.com
ProxyJump B
ForwardX11 yes
ForwardX11Trusted yes
Then simply run:
ssh C
Try these test programs after successful connection:
xeyes &
xterm &
gedit &
Remember that network latency will affect performance of graphics-heavy applications.