Displaying remote X app on local Cygwin

Let's say there is an X-based program, like xclock, that resides on a remote server. You would like to run the app on the server but redirect its display to your local Windows PC.

Furthermore, let's say that the remote server is in runlevel 3, not runlevel 5. Wait a second? Can you run X apps on the server even if it's not in runlevel 5? Yes. An X client just needs an X server to connect to, it does not have to be its local server, it can be any host running X server.

Furthermore, let's say there is a firewall between your PC and the server. The firewall blocks all ports except ssh.

The procedure

  1. Install and launch Cygwin/X on your PC. You can verify by opening a local cygwin shell and running "xclock" or "telnet localhost 6000" to connect to the local X server. You'll need to download "telnet" and "xclock" from Cygwin if you don't already have them.
  2. If you can run "xclock" but "telnet localhost 6000" fails with an access denied error (the port is not open), this means the Cywin/X server is not listening on a tcp port. Instead it is listening on a local unix socket found in /tmp/.X11-unix/X0, where "0" refers to the display number as explained below.
  3. By default, newer versions of Cygwin listen on a unix socket instead of tcp port 6000. Either way is okay. If you prefer the old-style behavior, then you can add the "-listen inet" option to the script that starts the Xserver.
  4. On the PC, download "xhost" from cygwin, and run "xhost +" to allow the remote server to be able to connect to the local X server
  5. At this point, notice that port 6000 is not running on the remote host. We will fix it as follows.
  6. Set up an ssh tunnel that opens port 6000 on the remote server and redirects it to port 6000 or the unix socket on your PC: from the PC, run "ssh [remote server ip] -R 6000:localhost:6000" or run "ssh [remote server ip] -R 6000:/tmp/.X11-unix/X0". On the remote server, you may need to modify /etc/ssh/sshd_config for "GatewayPorts yes"
  7. Now you have port 6000 running on the remote host and it is connecting to the Xserver running on your PC.
  8. In a cygwin shell on your PC, run "echo $DISPLAY" to determine which display the X server listens on. The response will be something like "localhost:0" or ":0". The localhost in this case refers to your PC. If the localhost is absent it means it's using the unix socket. We are interested only in the number(s) that comes after, which in this example is ":0".
  9. on the remote server, run the X app as follows (using xclock as an example): "DISPLAY="localhost:0" xclock" or "DISPLAY=":0" xclock". Note that localhost here refers to the remote host not the PC. We are telling xclock to use its local port 6000. Be sure to specify the correct display number you obtained in the previous step.

You now should see the xclock app displaying on your PC and you are able to interact with it with your mouse and keyboard.

We have set up port forwarding to achieve this. Note that this also works inside an existing ssh tunnel, for example if you are tunneling from your PC through a jumphost to a different remote server, you can run X applications on that remote server and have them display on your PC.