9

I connect (via ssh -Y ...) from a machine (=client) to another machine (=server, actually in my LAN, but it is irrelevant); then I start a new network namespace (NNS, for short) on the server, I start an xterm (from the default namespace) which is displayed perfectly on my client, and lastly, from within the xterm, I join the non-default NNS,

ip netns exec NNSName bash

I can check that I am in the new NNS,

ip netns identify $$

and I can run complex programs like, for instance, OpenVPN from within the new NNS.

The rub is here: I would like to start a graphical application (even just xeyes, for the moment) from within the new NNS, but I can't, I am always told: Unable to open DISPLAY=...

Admittedly, I have only tried the obvious:

DISPLAY=:0.0
DISPLAY=:10.0
DISPLAY=localhost:10.0
DISPLAY=localhost:20.0
DISPLAY=ClientName:10.0
DISPLAY=ClientIPAddress:10.0

always with xhost + on the client, for pure debugging purposes.

I have no problems:

  1. connecting via ssh -Y .... from client to server, running xeyes on the server and displaying it on the client;

  2. starting a new NNS on the server, and starting graphical applications within the NNS to be displayed on the server (i.e., in this case forget about the client).

It is when I put these two things together (ssh and namespace) that I cannot display on the client applications running in the server's new NNS.

It appears the standard TCP port 6010 belongs to the ssh session with the default NNS, while the new NNS ought to get its own. I can surely start an ssh server in the new NNS and connect directly from the client to the server's new NNS, but I was wondering: is there any easier way to do this, i.e. to display graphical applications running in the server's new NNS on the client's X11-server?

2 Answers 2

3

I was on a similar situation, here is how I work around it.

Some background: I had to span several selenium Firefox instances within namespaces for binding them with different IP addresses. But as you know I was having the error:

Error: Can't open display: localhost:10.0

Instead of working with unix sockets as Marius suggested I have just bound SSHD X11Forwarding to * instead of localhost (adding "X11UseLocalhost no" to the config) and redirected simple TCP connections with socat.

Attention to the security consequences of doing this!!!!

After this change on sshd, the DISPLAY will automatically change when you login from this:

 DISPLAY=localhost:10.0

To something like:

 DISPLAY=10.0.0.1:10.0

After that I just have to do redirect the :

ip netns exec my-NNS socat tcp-listen:6010,reuseaddr,fork tcp:192.168.5.130:6010 &

Then you should be able to work with xeyes, firefox, x-whatever-you-want...:

ip netns exec my-NNS xeyes &

And voilà!

1

Actually, there does not seem to be any standard way of doing.

There is a most obvious solution: from within the network namespace, start an ssh server, then connect to it from any remote machine with the usual option,

ssh -Y [email protected]

then any graphical program can be started on the remote machine's X11 server. All sorts of variations on the same theme, like vnc, also work.

Alternatively, one can use the usual instruments: iptables, netcat, socat. Here is one way to do it with socat: the trick is that, while the localhost spaces on the server and on its new network namespace have been separated, their X11 unix sockets have not. In fact, from the network namespace you can immediately open graphical applications which will be displayed on the X server of its parent machine. So, by forcing the network namespace to write to a new unix socket on its parent machine, we can redirect data sent to the new socket to the client X server by means of the usual ssh X11-forwarding on the server machine, without even connecting the new network namespace, giving a simpler solution.

It is done as follows: in the new network namespace,

export DISPLAY=:1

This will write to a new Unix socket, /tmp/.X11-unix/X1, which is not connected to anything yet. In the remote client, use the command

socat exec:'ssh me@remoteserver socat unix-l\:/tmp/.X11-unix/X1 -' unix:/tmp/.X11-unix/X0

(notice the escaping of the :). The above command sends the input of the unix/:1 socket on the server, to the unix/:0 socket on the client. You may have to relax local (= on client) xhost controls and check ownership of the unix/:1 (= :1 = /tmp/.X11-unix/X1) socket. This is considerably simpler than the previous method: no need of setting up an ssh server on the new network namespace, nor even of its getting an IP address. It also bypasses all issues of X11 authorization, like using xhost to allow some remote users or the use of MIT magic cookies with socat (I am not even sure this can be done).

There are other ways to do this (for instance by suppressing the -nolisten tcp option on the client X server, then use socat to forward the :1 unix socket to the client's port TCP6000, for instance) but, even neglecting that they cause serious security problems, they are not standard by any stretch of imagination.

You must log in to answer this question.

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