XPRA is a handy tool to have a remote X client. But having an XPRA server inside a network where you cannot access the XPRA server from outside directly, you need a workaround.

UPDATE: well, no workaround needed anymore!

Possible network situation
Your situation might look like this

There are 2 3 solutions you can consider…:

Update: Solution 0: Proxy query string

There is a way to have a one-liner do an xpra attach via a proxy. But a bug in xpra prevents this method from working. But there is a workaround!

The manual says to use an ssh proxy, specify this query string:
?proxy=ssh://[USERNAME[:PASSWORD]@]HOST[:SSH_PORT]

But the bug makes the ssh:// part being parsed into the username. A workround is to omit the ssh:// part. So the query string becomes:
?proxy=[USERNAME[:PASSWORD]@]HOST[:SSH_PORT]

Example: xpra attach ssh://target-user@target-host:22/20?proxy=proxy-user@proxy-host

Thanks you, play docker, for making me find this workaround!

Solution 1: XPRA Proxy?

XPRA has a built-in proxy which must be exposed directly via TCP with xpra proxy. I haven’t researched this proxy any further as having SSH’s port exposed is enough attack surface for hackers, so I wanted a solution that works over safe SSH and not “another open TCP port to some software”.

Solution 2: SSH’s ProxyJump!

The next idea was to use SSH’s relatively new ProxyJump functionality that uses an SSH gateway to the network where your destination XPRA server is behind.

Unfortunately, XPRA doesn’t support ProxyJump / SSH gateways. So a direct ProxyJump is (afaik) not (easily) possible. XPRA does the name resolution itself, instead of asking SSH to do the work. So XPRA treated my imaginary ProxyJump name xpra.example.com as a DNS query, and obviously fails as that’s not a DNS name, but an imaginary ProxyJump name:

# xpra attach ssh/xpra.example.com/20

xpra initialization error:
 cannot get  address of('xpra.example.com', 22): [Errno -2] Name or service not known

XPRA’s misses ProxyJump support – Workaround:

The working workaround is to expose the SSH port of the server that hosts the XPRA server (called “XPRA host” from now on) with ProxyJump via an SSH gateway – don’t worry: an SSH gateway is just a standard funcatiionality of a standard SSH server.

That’s how to expose the port XPRA hosts’s SSH port to the local machine:

ssh -L 2222:localhost:22 xpra.example.com

This command redirects port 22 of the XPRA host’s SSH server itself to the machine’s port 2222.

So now you can attach with XPRA over your ProxyJump’d exposed SSH port:

# xpra attach ssh/localhost:2222/20

This command connects to the exposed SSH port 2222 and connects to XPRA’s fake display 20.

That’s it!

You should not be connected to your once unreachable XPRA host with the help of an SSH gateway with ProxyJump. But if it’s not working for you, then it comes to… :

Troubleshooting

XPRA won’t connect with “not a valid RSA private key file” error:

xpra initialization error:
 connection failed: not a valid RSA private key file

XPRA tries to use localhost’s public key for authentification. Unfortunately, you’re not really connecting to localhost, but to the XPRA host which is behind a ProxyJump.

My dirty solution is to add a loopback IP address to the local machine to have a unique IP address that SSH did not already add a public key to it. I used “127.0.0.2” for it. To add a temporary local IP address to you machine, execute the following:

# sudo ip a add 127.0.0.2/8 dev lo

This adds another IP address (parallel to the infamous 127.0.0.1) to your loop device. Don’t worry, nobody can access this IP address other than from your machine itself.

First you have to expose the tunnel in another way, by telling SSH to bind the exposed SSH port to the new IP address (127.0.0.2) only:

# ssh -L 127.0.0.2:2222:localhost:22 xpra.example.com

This command added a 127.0.0.2: after the -L argument, which binds the port to the given IP only.

Now connect attach to the new IP address:

# xpra attach ssh/127.0.0.2:2222/20

Still not working?

Try this workaround I discovered while blindly debugging (replace both <username> with the XPRA host’s username that you want to login with):

# xpra attach ssh/<username>@127.0.0.2:2222/20 --ssh="ssh -l <username>"

This magically works. I can’t figure out why. This sets the username for the ssh session, so nothing that directly affects the public key resolution.

Questions, critique, you have a better solution?

Please don’t keep your thoughts to yourself. Comment below!