novnc / noVNC

VNC client web application
https://novnc.com
Other
11.67k stars 2.31k forks source link

vnc_auto.html succeeds when vnc.html fails when tokens are used #1397

Closed fedelep closed 4 years ago

fedelep commented 4 years ago

noVNC Developers,

While trying to stand up a server to help students access a networking tool using Chromebooks, I have run into an odd problem. Without tokens, I am able to open multiple instances of noVNC over many ports using websockify and vnc.html. When I add the token, however, only vnc_auto.html connects and vnc.html fails before offering a password dialogue.

Both the server and client are Linux. I have tried various configuration settings for vnc.html, three different browsers (Brave, Chrome, Firefox), disabled plugins, UFW, etc. Everything was working before the tokens, including wss (as tested in Wireshark), and I can connect up to 20 clients with no stability issues using vnc_auto.html. However, the program that I am using requires the application of the Alt key every so often, so this needs to work with vnc.html.

The command that I used to start websockify was: websockify -D --web=/usr/share/novnc/ --cert=/etc/ssl/novnc.pem 192.168.0.63:11000 --token-plugin=TokenFile --token-source=/etc/websockify

The command that I used to start VNC (tiger) was: /usr/bin/vncserver -passwd /home/user1/.vnc/passwd -geometry 1024x790 -rfbport 10001 :1

The demo token file looks like: user1: localhost:10001 user2: localhost:10002 user3: localhost:10003 user4: localhost:10004 user5: localhost:10005 user6: localhost:10006 user7: localhost:10007 user8: localhost:10008 user9: localhost:10009 user10: localhost:10010 user11: localhost:10011 user12: localhost:10012 user13: localhost:10013 user14: localhost:10014 user15: localhost:10015 user16: localhost:10016 user17: localhost:10017 user18: localhost:10018 user19: localhost:10019 user20: localhost:10020

Any help or advice would be appreciated. Screenshots enclosed. Thanks in advance.

Screenshot_2020-04-30_10-33-25vnc Screenshot_2020-04-30_10-32-46vnc_auto

CendioOssman commented 4 years ago

The fact that you mention vnc_auto.html means that this is not the current version of noVNC. Could you please try the latest stable noVNC and see if that works better?

fedelep commented 4 years ago

Thanks for the quick reply Cendio. I obtained noVNC through a PPA located on launchpad for Ubuntu 20.04:

https://launchpad.net/ubuntu/+source/novnc

Is this not the latest stable release? Do I need to download the latest source? Here are the relevant specs of my machine:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04 LTS
Release:    20.04
Codename:   focal

$ dpkg -l | grep novnc
ii  novnc                                1:1.0.0-2                                     all          HTML5 VNC client - daemon and programs
ii  python3-novnc                        1:1.0.0-2                                     all          HTML5 VNC client - Python 3.x libraries

$ dpkg -l | grep websockify
ii  python3-websockify                   0.9.0-0ubuntu2                                amd64        WebSockets support for any application/server - Python 3
ii  websockify                           0.9.0-0ubuntu2                                amd64        WebSockets support for any application/server

$ dpkg -l | grep tiger
ii  tigervnc-common                      1.10.1+dfsg-3                                 amd64        Virtual network computing; Common software needed by servers
ii  tigervnc-standalone-server           1.10.1+dfsg-3                                 amd64        Standalone virtual network computing server
CendioOssman commented 4 years ago

I'm afraid it is not. We released 1.1.0 last year with a lot of bug fixes. So I'm afraid you'll have to install that manually. Fortunately noVNC doesn't need to be compiled so it should just be a matter of replacing the files you have.

fedelep commented 4 years ago

Sorry Cendio, I only made things worse. Tried both 1.1.0 and master branch. Now neither vnc.html nor vnc_lite.html are happy using Brave, Chrome, or Firefox in Linux. In fact, there is an error regarding Safari in the screenshots, which I don't have. Fortunately this is just a VirtualBox image, and I have made a copy.

More screenshots attached. Screenshot_2020-05-01_17-36-12 Screenshot_2020-05-01_17-35-47 Screenshot_2020-05-01_17-33-50 Screenshot_2020-05-01_17-32-40

Stopped using tokens using killall websockify, fired a new instance up:

$ websockify -D --web=/usr/share/novnc/ --cert=/etc/ssl/novnc.pem 192.168.0.63:11001 localhost:10001 WebSocket server settings:

and voila! noVNC 1.1 is happy again. Screenshot_2020-05-01_18-19-41

Note the Windows key which does not appear in 1.0.

It appears that my websockify 0.9 is up to date. I would really like to get this working with tokens, as opposed to opening 20 websockify ports (previous working version).

As you may be able to tell by the screenshots, the server that I am making (gratis) is for Cisco Academy instructors who are serving students that have access only to Chromebooks and are not able to complete their work during the Covid-19 lockdowns.

At minimum, I need the Alt key available to the program so that it can simulate IoT device activation with Alt+Click. vnc_lite.html only provides Ctrl+Alt+Del, but I am comparing the source with vnc.html to see what can be added.

samhed commented 4 years ago

Note that those errors in your screenshots look like cache problems. Clearing your browser cache should fix those.

fedelep commented 4 years ago

Samhed,

Clearing the cache on the browsers did make those errors go away, however the connection problem still persists. With tokens, vnc.html 1.0.0 flashes "Connecting...." for a tiny fraction of a second, then displays "Failed to connect to server". vnc_lite.html 1.0.0 logs in with no issues. The updated vnc.html 1.1.0 also flashes "Connecting...." then fails in the same manner, while vnc_lite.html 1.1.0 fails with "Something went wrong, connection is closed".

Using tcpdump, I was able to capture the conversations. The streams can be followed using Wireshark.

PacketCaptures.zip

There are four pcap files included, one for vnc.html 1.0.0, one for vnc_lite.html 1.0.0, one for vnc.html 1.1.0, and one for vnc_lite.html 1.1.0. The only connection that succeeds was captured in vnc_lite.html 1.0.0. I can also confirm that everything works in both versions when tokens are not used in Websockify.

If you would like a link to my VMs, let me know.

CendioOssman commented 4 years ago

Thank you for those captures. They show that the token simply isn't included in any of the cases that fail. How have you specified which token to use when using vnc.html 1.1.0?

fedelep commented 4 years ago

Thank you so much for looking at the pcap files! As someone who also contributes to open-source software, I value the time and effort that you are putting in to resolving this issue.

Sorry, but I am not sure what you mean by "How have you specified which token to use when using vnc.html 1.1.0?" so I will show you exactly what I am doing.

To initiate Websockify at startup, I have created a systemd unit at /lib/systemd/system/websockify.service

[Unit] Description=Websockify After=network.target [Service] User=administrator Group=administrator Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/websockify.sh [Install] WantedBy=multi-user.target

This service simply calls a script at /usr/local/bin/websockify.sh which contains

ip_address=$(ip a | grep inet | grep brd | awk '{print $2}' | cut -d '/' -f 1) /usr/bin/websockify -D --web=/usr/share/novnc/ --cert=/etc/ssl/novnc.pem $ip_address:11000 --token-plugin=TokenFile --token-source=/usr/local/share/websockify exit 0

The first line determines the IP address of the system and passes it into the $ip_address to be used by the Websockify command. Websockify starts in daemon mode (-D), using tokens located at /usr/local/share/websockify/ Finally, the script exits.

$ ls /usr/local/share/websockify/ user1 user11 user13 user15 user17 user19 user20 user4 user6 user8 user10 user12 user14 user16 user18 user2 user3 user5 user7 user9

cat /usr/local/share/websockify/user1 user1: localhost:10001

Each user also has their own systemd unit.

[Unit] Description=PacketTracer service After=network.target [Service] User=user1 Group=user1 Type=forking ExecStart=/usr/local/bin/user1.sh [Install] WantedBy=multi-user.target

Each unit starts a shell script which is owned by each user

$ ls /usr/local/bin/ menu user1.sh user11.sh user13.sh user15.sh user17.sh user19.sh user20.sh user4.sh user6.sh user8.sh websockify.sh packettracer user10.sh user12.sh user14.sh user16.sh user18.sh user2.sh user3.sh user5.sh user7.sh user9.sh

Each shell script starts an instance of VNC on a different port starting at 10001

cat /usr/local/bin/user1.sh /usr/bin/vncserver -passwd /home/user1/.vnc/passwd -geometry 1024x790 -rfbport 10001 :1

Finally, each instance of VNC refers to /etc/X11/Xvnc-session, which offers a very stripped down desktop based on ICEWM. PacketTracer is started, and when it is closed, the environment is reset and it is started again.

! /bin/bash

test x"$SHELL" = x"" && SHELL=/bin/bash test x"$1" = x"" && set -- default user=$(whoami) let display=$(echo $user | sed 's/user//') while true do rm -rf /home/$user/.cache/ rm -rf /home/$user/.config/ rm -rf /home/$user/.local/ rm -rf /home/$user/.packettracer rm -rf /home/$user/.pki/ rm -rf /home/$user/pt/pt.conf rm -rf /home/$user/pt/logs rm -rf /home/$user/pt/uuid rm -rf /home/$user/pt/nets exec /usr/bin/icewm& exec /usr/local/bin/packettracer& until [ $(ps -aux | grep -w "$(echo $user)" | grep PacketTracer | awk '{print $11}'| head -n1) == "./PacketTracer7" ] do sleep 2 done 2>/dev/null while [ $(ps -aux | grep -w "$(echo $user)" | grep PacketTracer | awk '{print $11}'| head -n1) == "./PacketTracer7" ] do sleep 2 done 2>/dev/null killall -u $user icewm done

The systemd units appear to be working fine.

$ sudo systemctl status websockify.service ● websockify.service - Websockify Loaded: loaded (/lib/systemd/system/websockify.service; enabled; vendor preset: enabled) Active: active (exited) since Tue 2020-05-05 14:12:41 UTC; 1 day 23h ago Main PID: 700 (code=exited, status=0/SUCCESS) Tasks: 2 (limit: 19170) Memory: 52.5M CGroup: /system.slice/websockify.service ├─ 1015 /usr/bin/python3 /usr/bin/websockify -D --web=/usr/share/novnc/ --cert=/etc/ssl/novnc.pem 192.168.0.65:11000 --token-plugin=> └─88218 /usr/bin/python3 /usr/bin/websockify -D --web=/usr/share/novnc/ --cert=/etc/ssl/novnc.pem 192.168.0.65:11000 --token-plugin=>

May 05 14:12:40 packettracer systemd[1]: Starting Websockify... May 05 14:12:41 packettracer websockify.sh[725]: WebSocket server settings: May 05 14:12:41 packettracer websockify.sh[725]: - Listen on 192.168.0.65:11000 May 05 14:12:41 packettracer websockify.sh[725]: - Web server. Web root: /usr/share/novnc May 05 14:12:41 packettracer websockify.sh[725]: - SSL/TLS support May 05 14:12:41 packettracer websockify.sh[725]: - Backgrounding (daemon) May 05 14:12:41 packettracer systemd[1]: Finished Websockify.

$ sudo systemctl status user1.service ● user1.service - PacketTracer service Loaded: loaded (/lib/systemd/system/user1.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2020-05-05 19:31:37 UTC; 1 day 17h ago Process: 83260 ExecStart=/usr/local/bin/user1.sh (code=exited, status=0/SUCCESS) Tasks: 40 (limit: 19170) Memory: 56.1M CGroup: /system.slice/user1.service ├─ 83283 /usr/bin/Xtigervnc :1 -desktop packettracer:1 (user1) -auth /home/user1/.Xauthority -geometry 1024x790 -depth 24 -rfbwait > ├─ 83302 /usr/bin/perl /usr/bin/vncserver -passwd /home/user1/.vnc/passwd -geometry 1024x790 -rfbport 10001 :1 ├─ 83303 /bin/bash /etc/X11/Xvnc-session ├─ 83318 /usr/bin/icewm ├─ 83319 /bin/bash /usr/local/bin/packettracer ├─ 83327 ./PacketTracer7 ├─ 83332 /opt/pt/bin/QtWebEngineProcess --type=zygote --webengine-schemes=this-sm:sLC;pt-sm:sLC;file-sm:sLC;user-app:sLC;wlc-3504:s> ├─ 83334 /opt/pt/bin/QtWebEngineProcess --type=zygote --webengine-schemes=this-sm:sLC;pt-sm:sLC;file-sm:sLC;user-app:sLC;wlc-3504:s> ├─ 83351 dbus-launch --autolaunch 5adffa86456a404da7923c97c72c13e6 --binary-syntax --close-stderr ├─ 83352 /usr/bin/dbus-daemon --syslog-only --fork --print-pid 5 --print-address 7 --session └─1305159 sleep 2

May 05 19:31:33 packettracer systemd[1]: Starting PacketTracer service... May 05 19:31:33 packettracer user1.sh[83261]: Cleaning stale pidfile '/home/user1/.vnc/packettracer:1.pid'! May 05 19:31:34 packettracer user1.sh[83261]: New 'packettracer:1 (user1)' desktop at :1 on machine packettracer May 05 19:31:34 packettracer user1.sh[83261]: Starting applications specified in /etc/X11/Xvnc-session May 05 19:31:34 packettracer user1.sh[83261]: Log file is /home/user1/.vnc/packettracer:1.log May 05 19:31:34 packettracer user1.sh[83261]: Use xtigervncviewer -SecurityTypes VncAuth -passwd /home/user1/.vnc/passwd :10001 to connect to the> May 05 19:31:34 packettracer dbus-daemon[83352]: [session uid=1001 pid=83350] AppArmor D-Bus mediation is enabled May 05 19:31:37 packettracer systemd[1]: Started PacketTracer service.

Up to 20 users are able to simultaneously interact with their own instance of VNC on separate desktops. At the moment, I have two running.

$ pstree systemd─┬─NetworkManager───2[{NetworkManager}] ├─2[Xtigervnc───16[{Xtigervnc}]] ├─accounts-daemon───2[{accounts-daemon}] ├─agetty ├─apache2───5[apache2] ├─atd ├─avahi-daemon───avahi-daemon ├─cron ├─3[dbus-daemon] ├─2[dbus-launch] ├─fwupd───5[{fwupd}] ├─irqbalance───{irqbalance} ├─multipathd───6[{multipathd}] ├─networkd-dispat ├─polkitd───2[{polkitd}] ├─rsyslogd───3[{rsyslogd}] ├─sshd───sshd───sshd───bash───pstree ├─systemd───(sd-pam) ├─systemd-journal ├─systemd-logind ├─systemd-network ├─systemd-resolve ├─systemd-timesyn───{systemd-timesyn} ├─systemd-udevd───systemd-udevd ├─unattended-upgr───{unattended-upgr} ├─vncserver───Xvnc-session─┬─icewm │ ├─packettracer───PacketTracer7─┬─QtWebEngineProc───QtWebEngineProc │ │ └─13[{PacketTracer7}] │ └─sleep ├─vncserver───Xvnc-session─┬─icewm │ ├─packettracer───PacketTracer7─┬─QtWebEngineProc───QtWebEngineProc │ │ └─16*[{PacketTracer7}] │ └─sleep ├─websockify───websockify └─wpa_supplicant

So, while this may not have been your original intent in writing this software, everything appears to be working for all 20 users (See screenshot). At least until I implement tokens, at which point only 1.0.0 vnc_lite.html appears to be happy with tokens. Even if I try passing them manually in the URL, the others fail. If I have implemented something incorrectly, somehow this one version of noVNC is compensating.

Again, if you would like a copy of the VM to poke at, it is less than 800MB (without PacketTracer). It is based on a very stripped down Ubuntu 20.04. Outside of this little hiccup, I find your solution far superior to Tomcat/Guacamole. Screenshot_2020-05-07_09-49-19

CendioOssman commented 4 years ago

I was thinking about the client side of things. The browser/noVNC needs to know the token somehow. How do users go about connecting to the correct session?

fedelep commented 4 years ago

Insightful question. I am running an Apache server with php extensions which provides this interface: Screenshot_2020-05-07_11-05-34

The intent is to assign each student a different device and password. As you can see by the mouse over user2, the IP address of the machine is displayed, along with the port followed by /?token=user2. The reason for the missing html file is that I have copied vnc_lite.html as index.html. I have done the same with vnc.html without tokens and it worked, and I have tried using the URL of 192.168.0.65:11000/vnc_lite.html?token=user2 which also works fine.

However, when using tokens, I manually verify the URL as 192.168.0.65:11000/vnc.html?token=user2 and the failure that I described occurs.

Thank you for being so thourough. I am definitely open to the possibility that I have done something wrong in the implementation

.

CendioOssman commented 4 years ago

Ah, then I see the issue. The token argument was very non-standard and was removed some time ago. You need to use the path argument instead with a combined websocket path and token argument instead. E.g. 192.168.0.65:11000/vnc.html?path=/websockify?token=user2. (you may need to replace that second ? with 0x3f depending on how lenient your browser is).

So please change your URLs and it should work fine.