-
Notifications
You must be signed in to change notification settings - Fork 379
How to access X over TCP IP network
This article is currently work in progress. Hints and test reports are appreciated!
In few cases it is desireable to access an X server with an IP adress over TCP/IP instead of using a unix socket.
Xorg
and most other X servers provide (deprecated) option -listen tcp
. With this option enabled an X server can be accessed with an address of the form IP:DISPLAYNUMBER
. A notable exception that does not support -listen tcp
is Xwayland
.
Example:
Xephyr :2 -listen tcp &
sleep 1
DISPLAY=127.0.0.1:2 xterm
Pitfalls:
- This connection is not encrypted. A sniffer might read X content and inject X11 commands. This might be ok in a local network, but should not be exposed to the outer world. For this reason
-listen tcp
is disabled by default in most X server setups. -
-listen tcp
cannot be restricted to localhost but listens to all incoming connections with the mask0.0.0.0
. So a proper authentication setup is needed.- To allow access restrictions at all, a Cookie must be created and specified with X option
-auth
. - While there is basically no proper way to restrict access within localhost (except using cookies), it is possible to additionally allow remote access for specified IP addresses only using
xhost
. - While remote clients cannot change
xhost
settings, every local client is able to allow access to X for everyone with e.g.xhost +
.
- To allow access restrictions at all, a Cookie must be created and specified with X option
If you want to access an X server that does not provide -listen tcp
(Xwayland
) or just did not have enabled it during startup (like most likely your host Xorg
), you can use socat
to provide TCP/IP access.
- One advantage compared to
-listen tcp
is that it can be restricted tolocalhost
access by using IP127.0.0.1
. - One disadvantage compared to
-listen tcp
is that remote connection access cannot be configured withxhost
. (The reason is that the X server is not aware of the TCP setup and believes that every client is a local one.) Instead, authentication cookies can be used. But if the cookie is given to third parties or stolen by a network sniffer, anyone could connect from anywhere if he provides the cookie.
Example for access to currently running X server:
- Check current
DISPLAY
:
$ echo $DISPLAY
:0.0
The number after :
and before .
is your display number, in this case 0
.
- The according X unix socket is located at
/tmp/.X11-unix/X0
.
$ ls -l /tmp/.X11-unix/X0
srwxrwxrwx 1 root root 0 12. Jul 09:15 /tmp/.X11-unix/X0
- Create a TCP/IP connection with
socat
. Use a custom new display number:
Newdisplaynumber=111
socat TCP-LISTEN:$((6000+Newdisplaynumber)),fork,bind=127.0.0.1 UNIX-CONNECT:/tmp/.X11-unix/X0
- Try to access X over TCP/IP with the new display number:
DISPLAY=127.0.0.1:111 xterm
At this point you might or might not get an X authentication issue. Don't let this happen randomly but check X authentication.
xhost
does not restrict X access but allows additional access to an X server that is protected otherwise by cookie authentication.
It opens holes into X security settings.
- In general I recommend to use X cookie authentication only and to disable all
xhost
based access. This is especially true for all local setups. - In one setup
xhost
is to be preferred over cookie authentication:- If a remote client is allowed to access the X server, the hostname or IP of the remote client should be allowed with
xhost
. - If it would be authenticated with a cookie instead, the cookie could be (ab)used from other IP addresses, too.
- Remember that the traffic is unencrypted and a sniffer could extract the cookie.
- If a remote client is allowed to access the X server, the hostname or IP of the remote client should be allowed with
- Note that for a useful
xhost
setup the X server must be configured to use a cookie as well, even if the cookie is not provided to any client at all. Otherwise the X server would have no authentication setup that would cause him to refuse connections. - Local X clients can change
xhost
settings. Remote clients can not.- This is only true for
-listen tcp
setups. - With a
socat
TCP/IP setup the X server is not aware that it is accessed over TCP and believes that every client is a local one.
- This is only true for
Now a follow-up for the socat
TCP/IP setup to check and remove xhost
based authentication:
$ # check current settings
$ xhost
access control enabled, only authorized clients can connect
SI:localuser:lauscher
- It seems my debian system has allowed X access for local user
lauscher
(me). Let's disable this local user based access:
$ # disallow local user access
$ xhost -SI:localuser:lauscher
localuser:lauscher being removed from access control list
$ # check
$ xhost
access control enabled, only authorized clients can connect
$ # fails as intended
$ DISPLAY=127.0.0.1:111 xterm
No protocol specified
xterm: Xt error: Can't open display: 127.0.0.1:111
Below we'll set up a cookie to authenticate X access.
In worst case xhost +
is set and would allow arbitrary access for everyone around the world. This is fatal for -listen tcp
setups.
The socat
TCP/IP setup is not affected but should be set up with localhost
/ 127.0.0.1
only.
$ # DEAR CHILDS, DON'T TRY THIS AT HOME
$ xhost +
access control disabled, clients can connect from any host
$ # revoke
$ xhost -
access control enabled, only authorized clients can connect
Note that every local X client is allowed to set xhost +
.
For local setups better than using xhost
is to set up an X authentication cookie. Some information is also given on wiki page X authentication with cookies and xhost ("No protocol specified" error).
- Let's bake a cookie for the localhost socat TCP setup:
Newdisplaynumber=111
# remove cookie file if it exists
rm ~/mycookie
# Let Xorg generate a trusted cookie that has to be used within 3600 seconds the first time.
xauth -i -f ~/mycookie generate $DISPLAY . trusted timeout 3600
# Extract part of cookie without DISPLAY and hostname information
Cookie="$(xauth -i -f ~/mycookie list | awk '{print $3}')"
# delete new cookie file
rm ~/mycookie
# create new cookie file with our new custom display number and extracted cookie part
xauth -i -f ~/mycookie add :$Newdisplaynumber MIT-MAGIC-COOKIE-1 "$Cookie"
# replace host identification with ffff / family wild
Cookie="$(xauth -i -f ~/mycookie nlist | sed -e 's/^..../ffff/')"
echo "$Cookie" | xauth -i -f ~/mycookie nmerge -
# restrict access to cookie to current user only
chmod 600 ~/mycookie
- Run with new cookie
DISPLAY=127.0.0.1:111 XAUTHORITY=~/mycookie xterm
Hurray, it works! However, this connection is still unencrypted and almost as insecure as a -listen tcp
setup. A sniffer can still intercept the connection and even steal our cute cookie whenever an X client submits it to the X server. Only if using localhost
/ 127.0.0.1
this socat
setup is more secure than a -listen tcp
setup.
A cookie can also be used to authenticate remote connections. Issues:
- The remote client might give the cookie to a third party. Others could connect remotely, too.
- A sniffer might extract the cookie from the unencrypted connection and could use it to access the X server.
Unfortunately applications somehow freeze if they try to access the GPU through the socat
connection. It seems they wait forever on some sort of event. Enable software rendering with LIBGL_ALWAYS_SOFTWARE=1
. Example:
DISPLAY=127.0.0.1:111 XAUTHORITY=~/mycookie LIBGL_ALWAYS_SOFTWARE=1 glxgears
As long as socat
binds the TCP socket to localhost
/ 127.0.0.1
, there might be no way to access X from outside even if xhost +
is set. At least in my test runs I could not access it even if trying to access with my local ethernet IP adress (e.g. DISPLAY=192.168.178.30:111
).
However, if you set up an outgoing network connection with a public IP address, it will not be entirely secure even if you disable xhost
settings and set up a cookie as described above.
The issue is: If an authorizied client accesses X over IP with the cookie, it is allowed to set xhost +
and thus disabling authorization at all, exposing the X server to the entire world.
This is at least true for the socat
setup where the X server itself is not aware that it is also accessed over TCP. If the setup is done with -listen tcp
instead, the X server should deny xhost
commands from outside and allow local clients only to change xhost
settings.