2023-10-19 - Remote Tech Support (updated 2024-02-23) I occasionally need to do remote tech support for people I know. Of course, there are commercial programs like TeamViewer that allow easy remote desktop access, but I wanted a free software alternative. There seem to be a lot of remote desktop programs, but most of them never really worked properly for me. In the end, I settled on a VNC server together with two SSH tunnels. Two SSH tunnels are necessary because generally, both computers will be behind firewalls that don't allow direct access, so the connection needs to be routed through a separate server. This would probably also be possible with something like WireGuard, but I've never used that, so I just stuck with SSH for now. Terminology: In this guide, local will refer to my own computer, remote will refer to the computer of the person I'm doing tech support for, and server will refer to the server I tunnel the connection through. First, an unprivileged user account needs to be created on the server for the person you're doing tech support for. This user does not need to have a real shell set. On OpenBSD, I set the shell to /sbin/nologin to lock down the account a bit. On other systems, this may be located at /usr/sbin/nologin. The SSH configuration can also be locked down for this user by adding the following section to the end of /etc/ssh/sshd_config (where the user account is called 'unprivileged'): Match User unprivileged PasswordAuthentication no AllowTcpForwarding yes X11Forwarding no PermitTTY no AllowAgentForwarding no PermitOpen localhost:5900 ForceCommand echo nologin 5900 is the port that will be used by the VNC server, so we only need to allow that for the port forwarding. I'm not sure if there are still other things that could be done to lock the account down. Next, the remote computer needs to be prepared. I used TigerVNC[0], but a different VNC server could also be used. The nice thing about TigerVNC is that it has a mode for sharing the current X session instead of creating a new one, so it supports true screen sharing where both people see the same screen and can control it at the same time. Apparently, x11vnc also supports this, but I haven't tried it yet. On OpenBSD, the package 'tigervnc' can be installed, on Debian-based systems, 'tigervnc-scraping-server' needs to be installed. Note that the VNC commands may be slightly different depending on the system you're using. Debian-based systems usually use update-alternatives to link generic commands like 'vncviewer' to a command from a specific package. UPDATE (2024-02-23): I found that on some Debian-based systems, it is also necessary to install tigervnc-common to get the 'vncpasswd' (or 'tigervncpasswd', depending on the system) command. It is also a good idea to install autossh to make sure the ssh session doesn't die. To make setting up the SSH tunnel convenient, create a password-less SSH key with ssh-keygen and add the public key to ~/.ssh/authorized_keys in the unprivileged user account on the server. Since the server is locked down pretty well, this *probably* shouldn't cause any major security issues. Before a VNC server can be run, a password needs to be configured. To do this, simply run 'vncpasswd' and give a password (it also asks if you want to create a view-only password, but you don't need that). When all this is done the following script can be created: #!/bin/sh x0vncserver -localhost yes -rfbauth ~/.vnc/passwd autossh -Nf -R 5900:localhost:5900 unprivileged@server.name read tmp x0vncserver -kill :* pkill -x autossh UPDATE (2024-02-23): The script originally said 'pkill -x ssh', which only kills the actual ssh client, which is then restarted by autossh. x0vncserver is the special VNC server that shares the current X session instead of creating a new one. This should usually run on port 5900 (5900 + number of current X display, which normally is 0). If this is different for some reason, the port will need to be changed in all other commands that use it. If '-localhost yes' is given, x0vncserver only accepts connections from localhost, so other computers should only be able to connect through the SSH tunnel, although there have apparently been some exploits that spoofed packets from localhost in the past[1]. This is actually the default behavior, but I guess it doesn't hurt to specify it explicitly. I suppose there also isn't really any added security benefit by using the default VNC authentication when the connection is tunneled through SSH anyways, so it might make more sense to just add '-SecurityTypes none' and use it without a password. When the VNC server has started, an SSH reverse tunnel to the server is created, where 'unprivileged' is the unprivileged user account, and 'server.name' is the address of the server. The line with 'read' is just there to block execution until enter is pressed, after which everything is killed again. I'm not sure if there's a better way to kill ssh than 'pkill -x ssh'. Maybe it would be possible to remove the '-f' flag, use & to start the process in the background, and then use $! to get the exact pid of the process, but that seems somewhat ugly as well. Most desktop environments should allow you to create some sort of launcher for running a script in a terminal. Alternatively, another script could be created that opens a terminal and runs the script. With either one of these options, the user just has to run that launcher/script, and then wait for the tech support person to connect to the VNC server. Make sure to run the script at least once while setting it up, otherwise the user will have to accept the public key of the server when the SSH tunnel is set up the first time. Also, if the public key of the server changes for some reason, you will need to find a way to update ~/.known_hosts on the remote computer so the user doesn't get a scary warning when trying to run the script. That brings us to our last step, setting up the local computer. This is really the easiest part. Once the script on the remote computer is running, another tunnel must be created from the local computer to the server: autossh -NL 5900:localhost:5900 user@server.name In this case, 'user' is whatever user account you use to log in to the server. Then, you can connect to the VNC server with the following command (on OpenBSD, this command is part of the package 'tigervnc', on Debian-based systems, it is included in 'tigervnc-viewer'): vncviewer localhost:0 When this asks for a password, the password that was given to 'vncpasswd' on the remote computer needs to be entered. After that, you should see the screen of the remote computer. To stop the VNC server, the user of the remote computer just needs to press enter in the terminal window running the script (this can even be done by the tech support person since the connection is only terminated once enter has been pressed). Feel free to contact me if you have any better suggestions or think that there are glaring security problems with this setup. [0] https://tigervnc.org [1] https://serverfault.com/questions/411658/can-localhost-be-spoofed/752076#752076