How to Configure Multi-Hop SSH X11 Forwarding for Remote GUI Applications


2 views

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:

  1. Each SSH connection creates its own DISPLAY environment variable
  2. The X11 forwarding channel isn't properly propagated
  3. 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:

  1. The DISPLAY variable isn't properly forwarded through multiple hops
  2. Xauth cookies aren't being transferred correctly
  3. 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.