Skip to content

How to access X over TCP IP network

Martin Viereck edited this page Aug 10, 2022 · 9 revisions

This article is currently work in progress. Hints and test reports are appreciated!

How to access X over TCP/IP

In few cases it is desireable to access an X server with an IP adress over TCP/IP instead of using a unix socket.

-listen tcp

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 mask 0.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 +.

socat TCP/IP setup

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 to localhost access by using IP 127.0.0.1.
  • One disadvantage compared to -listen tcp is that remote connection access cannot be configured with xhost. (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.

check xhost based 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.
  • 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.

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.

xhost +

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 +.

XAUTHORITY cookie based access

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.

Disable GPU access

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

Security note

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.

Clone this wiki locally