mirror of
https://git.proxmox.com/git/mirror_novnc
synced 2025-08-16 07:37:13 +00:00

Try to be more consistent in how we capitalize things. Both the "Title Case" and "Sentence case" styles are popular, so either would work. Google and Mozilla both prefer "Sentence case", so let's follow them.
235 lines
7.6 KiB
Bash
Executable File
235 lines
7.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Copyright (C) 2018 The noVNC authors
|
|
# Licensed under MPL 2.0 or any later version (see LICENSE.txt)
|
|
|
|
usage() {
|
|
if [ "$*" ]; then
|
|
echo "$*"
|
|
echo
|
|
fi
|
|
echo "Usage: ${NAME} [--listen [HOST:]PORT] [--vnc VNC_HOST:PORT] [--cert CERT] [--ssl-only]"
|
|
echo
|
|
echo "Starts the WebSockets proxy and a mini-webserver and "
|
|
echo "provides a cut-and-paste URL to go to."
|
|
echo
|
|
echo " --listen [HOST:]PORT Port for proxy/webserver to listen on"
|
|
echo " Default: 6080 (on all interfaces)"
|
|
echo " --vnc VNC_HOST:PORT VNC server host:port proxy target"
|
|
echo " Default: localhost:5900"
|
|
echo " --cert CERT Path to combined cert/key file, or just"
|
|
echo " the cert file if used with --key"
|
|
echo " Default: self.pem"
|
|
echo " --key KEY Path to key file, when not combined with cert"
|
|
echo " --web WEB Path to web files (e.g. vnc.html)"
|
|
echo " Default: ./"
|
|
echo " --ssl-only Disable non-https connections."
|
|
echo " "
|
|
echo " --file-only Disable directory listing in web server."
|
|
echo " "
|
|
echo " --record FILE Record traffic to FILE.session.js"
|
|
echo " "
|
|
echo " --syslog SERVER Can be local socket such as /dev/log, or a UDP host:port pair."
|
|
echo " "
|
|
echo " --heartbeat SEC send a ping to the client every SEC seconds"
|
|
echo " --timeout SEC after SEC seconds exit when not connected"
|
|
echo " --idle-timeout SEC server exits after SEC seconds if there are no"
|
|
echo " "
|
|
echo " --web-auth enable authentication"
|
|
echo " --auth-plugin CLASS authentication plugin to use"
|
|
echo " --auth-source ARG plugin configuration"
|
|
echo " "
|
|
echo " active connections"
|
|
echo " "
|
|
exit 2
|
|
}
|
|
|
|
NAME="$(basename $0)"
|
|
REAL_NAME="$(readlink -f $0)"
|
|
HERE="$(cd "$(dirname "$REAL_NAME")" && pwd)"
|
|
HOST=""
|
|
PORT="6080"
|
|
LISTEN="$PORT"
|
|
VNC_DEST="localhost:5900"
|
|
CERT=""
|
|
KEY=""
|
|
WEB=""
|
|
proxy_pid=""
|
|
SSLONLY=""
|
|
RECORD=""
|
|
SYSLOG_ARG=""
|
|
HEARTBEAT_ARG=""
|
|
IDLETIMEOUT_ARG=""
|
|
TIMEOUT_ARG=""
|
|
WEBAUTH_ARG=""
|
|
AUTHPLUGIN_ARG=""
|
|
AUTHSOURCE_ARG=""
|
|
FILEONLY_ARG=""
|
|
|
|
|
|
die() {
|
|
echo "$*"
|
|
exit 1
|
|
}
|
|
|
|
cleanup() {
|
|
trap - TERM QUIT INT EXIT
|
|
trap "true" CHLD # Ignore cleanup messages
|
|
echo
|
|
if [ -n "${proxy_pid}" ]; then
|
|
echo "Terminating WebSockets proxy (${proxy_pid})"
|
|
kill ${proxy_pid}
|
|
fi
|
|
}
|
|
|
|
# Process arguments
|
|
|
|
# Arguments that only apply to chrooter itself
|
|
while [ "$*" ]; do
|
|
param=$1; shift; OPTARG=$1
|
|
case $param in
|
|
--listen) LISTEN="${OPTARG}"; shift ;;
|
|
--vnc) VNC_DEST="${OPTARG}"; shift ;;
|
|
--cert) CERT="${OPTARG}"; shift ;;
|
|
--key) KEY="${OPTARG}"; shift ;;
|
|
--web) WEB="${OPTARG}"; shift ;;
|
|
--ssl-only) SSLONLY="--ssl-only" ;;
|
|
--file-only) FILEONLY_ARG="--file-only" ;;
|
|
--record) RECORD="${OPTARG}"; shift ;;
|
|
--syslog) SYSLOG_ARG="--syslog ${OPTARG}"; shift ;;
|
|
--heartbeat) HEARTBEAT_ARG="--heartbeat ${OPTARG}"; shift ;;
|
|
--idle-timeout) IDLETIMEOUT_ARG="--idle-timeout ${OPTARG}"; shift ;;
|
|
--timeout) TIMEOUT_ARG="--timeout ${OPTARG}"; shift ;;
|
|
--web-auth) WEBAUTH_ARG="--web-auth" ;;
|
|
--auth-plugin) AUTHPLUGIN_ARG="--auth-plugin ${OPTARG}"; shift ;;
|
|
--auth-source) AUTHSOURCE_ARG="--auth-source ${OPTARG}"; shift ;;
|
|
-h|--help) usage ;;
|
|
-*) usage "Unknown chrooter option: ${param}" ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
|
|
if [ "$LISTEN" != "$PORT" ]; then
|
|
HOST=${LISTEN%:*}
|
|
PORT=${LISTEN##*:}
|
|
# if no host was given, restore
|
|
[ "$HOST" = "$PORT" ] && HOST=""
|
|
fi
|
|
|
|
# Sanity checks
|
|
if [ -z "${HOST}" ]; then
|
|
if bash -c "exec 7<>/dev/tcp/localhost/${PORT}" &> /dev/null; then
|
|
exec 7<&-
|
|
exec 7>&-
|
|
die "Port ${PORT} in use. Try --listen PORT"
|
|
else
|
|
exec 7<&-
|
|
exec 7>&-
|
|
fi
|
|
fi
|
|
|
|
trap "cleanup" TERM QUIT INT EXIT
|
|
|
|
# Find vnc.html
|
|
if [ -n "${WEB}" ]; then
|
|
if [ ! -e "${WEB}/vnc.html" ]; then
|
|
die "Could not find ${WEB}/vnc.html"
|
|
fi
|
|
elif [ -e "$(pwd)/vnc.html" ]; then
|
|
WEB=$(pwd)
|
|
elif [ -e "${HERE}/../vnc.html" ]; then
|
|
WEB=${HERE}/../
|
|
elif [ -e "${HERE}/vnc.html" ]; then
|
|
WEB=${HERE}
|
|
elif [ -e "${HERE}/../share/novnc/vnc.html" ]; then
|
|
WEB=${HERE}/../share/novnc/
|
|
else
|
|
die "Could not find vnc.html"
|
|
fi
|
|
|
|
# Find self.pem
|
|
if [ -n "${CERT}" ]; then
|
|
if [ ! -e "${CERT}" ]; then
|
|
die "Could not find ${CERT}"
|
|
fi
|
|
elif [ -e "$(pwd)/self.pem" ]; then
|
|
CERT="$(pwd)/self.pem"
|
|
elif [ -e "${HERE}/../self.pem" ]; then
|
|
CERT="${HERE}/../self.pem"
|
|
elif [ -e "${HERE}/self.pem" ]; then
|
|
CERT="${HERE}/self.pem"
|
|
else
|
|
echo "Warning: could not find self.pem"
|
|
fi
|
|
|
|
# Check key file
|
|
if [ -n "${KEY}" ]; then
|
|
if [ ! -e "${KEY}" ]; then
|
|
die "Could not find ${KEY}"
|
|
fi
|
|
fi
|
|
|
|
# try to find websockify (prefer local, try global, then download local)
|
|
if [[ -d ${HERE}/websockify ]]; then
|
|
WEBSOCKIFY=${HERE}/websockify/run
|
|
|
|
if [[ ! -x $WEBSOCKIFY ]]; then
|
|
echo "The path ${HERE}/websockify exists, but $WEBSOCKIFY either does not exist or is not executable."
|
|
echo "If you intended to use an installed websockify package, please remove ${HERE}/websockify."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using local websockify at $WEBSOCKIFY"
|
|
else
|
|
WEBSOCKIFY_FROMSYSTEM=$(which websockify 2>/dev/null)
|
|
WEBSOCKIFY_FROMSNAP=${HERE}/../usr/bin/python2-websockify
|
|
[ -f $WEBSOCKIFY_FROMSYSTEM ] && WEBSOCKIFY=$WEBSOCKIFY_FROMSYSTEM
|
|
[ -f $WEBSOCKIFY_FROMSNAP ] && WEBSOCKIFY=$WEBSOCKIFY_FROMSNAP
|
|
|
|
if [ ! -f "$WEBSOCKIFY" ]; then
|
|
echo "No installed websockify, attempting to clone websockify..."
|
|
WEBSOCKIFY=${HERE}/websockify/run
|
|
git clone https://github.com/novnc/websockify ${HERE}/websockify
|
|
|
|
if [[ ! -e $WEBSOCKIFY ]]; then
|
|
echo "Unable to locate ${HERE}/websockify/run after downloading"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using local websockify at $WEBSOCKIFY"
|
|
else
|
|
echo "Using installed websockify at $WEBSOCKIFY"
|
|
fi
|
|
fi
|
|
|
|
# Make all file paths absolute as websockify changes working directory
|
|
WEB=`realpath "${WEB}"`
|
|
[ -n "${CERT}" ] && CERT=`realpath "${CERT}"`
|
|
[ -n "${KEY}" ] && KEY=`realpath "${KEY}"`
|
|
[ -n "${RECORD}" ] && RECORD=`realpath "${RECORD}"`
|
|
|
|
echo "Starting webserver and WebSockets proxy on${HOST:+ host ${HOST}} port ${PORT}"
|
|
${WEBSOCKIFY} ${SYSLOG_ARG} ${SSLONLY} ${FILEONLY_ARG} --web ${WEB} ${CERT:+--cert ${CERT}} ${KEY:+--key ${KEY}} ${LISTEN} ${VNC_DEST} ${HEARTBEAT_ARG} ${IDLETIMEOUT_ARG} ${RECORD:+--record ${RECORD}} ${TIMEOUT_ARG} ${WEBAUTH_ARG} ${AUTHPLUGIN_ARG} ${AUTHSOURCE_ARG} &
|
|
proxy_pid="$!"
|
|
sleep 1
|
|
if [ -z "$proxy_pid" ] || ! ps -eo pid= | grep -w "$proxy_pid" > /dev/null; then
|
|
proxy_pid=
|
|
echo "Failed to start WebSockets proxy"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "$HOST" ]; then
|
|
HOST=$(hostname)
|
|
fi
|
|
|
|
echo -e "\n\nNavigate to this URL:\n"
|
|
if [ "x$SSLONLY" == "x" ]; then
|
|
echo -e " http://${HOST}:${PORT}/vnc.html?host=${HOST}&port=${PORT}\n"
|
|
else
|
|
echo -e " https://${HOST}:${PORT}/vnc.html?host=${HOST}&port=${PORT}\n"
|
|
fi
|
|
|
|
echo -e "Press Ctrl-C to exit\n\n"
|
|
|
|
wait ${proxy_pid}
|