Package: tightvncserver Version: 1:1.3.10-5+b1 Severity: wishlist Control: found -1 1:1.3.10-3
[Please do not Cc: me, for I’m “on the list,” so to say, and I try to reserve my inbox for private communication only. I’d have set up Mail-Followup-To:, but there doesn’t seem to be a way to make it point to the report being filed.] Xtightvnc(1) concludes with: Probably, the best way to secure Xvnc server is to allow only loopback connections from the server machine (the -localhost option) and to use SSH tunneling for remote access to the Xvnc server. However, it’s arguably even more secure to either use a Unix socket accessible by only the intended user(s) (note that OpenSSH supports Unix to Unix, TCP to Unix, and Unix to TCP socket forwarding; see the -L option in ssh(1)); or a pair of pipes, such as rsync(1) uses (by essentially invoking $ ssh -- REMOTE rsync --server to access the remote.) Moreover, certain lightweight SSH2 servers, such as tinysshd(8), omit support for forwarding altogether, which doesn’t inconvenience tools such as rsync(1) in the least, but which makes the advice above impossible to follow. Unfortunately, the obvious candidate for such usage, the -inetd option, doesn’t quite support it. The cause is twofold. On the one hand, Xtightvnc -inetd still assumes that the communication is done via a TCP socket, uses setsockopt(2) on the file descriptor, and exits when that fails. On the other, contrary to the documentation, -inetd Xvnc is launched by inetd. This option causes Xvnc to redirect network input/output to stdin/stdout. the current implementation uses not stdin and stdout, but rather ‘stdin’ only, for both input and output. Which isn’t a problem when the server is started from inetd(8) proper, as in that case both stdin and stdout point to the same socket; but /is/ a problem in the proposed usage, where stdin and stdout are two separate pipes (incoming and outgoing, respectively.) Xvnc/programs/Xserver/hw/vnc/init.c 361- close stderr. OsInit() will redirect stderr logging to an 362- appropriate log file or /dev/null if that doesn't work. */ 363- 364: dup2(0,3); 365- inetdSock = 3; 366- close(2); 367- Xvnc/programs/Xserver/hw/vnc/sockets.c 101- 102: if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY, 103- (char *)&one, sizeof(one)) < 0) { 104: rfbLogPerror("setsockopt"); 105- exit(1); 106- } 107- (So far as I can tell only a single use of setsockopt(2) in the file is relevant to the problem being described.) As such, my suggestions would be as follows. 1. The setsockopt(2) failure in rfbInitSockets () is downgraded to a warning (from a fatal error.) This alone should be sufficient for running Xtightvnc(1) on a Unix socket via inetd(8), which is already more secure than a localhost-bound TCP port. 2. In place of inetdSock, the code should use separate inetdIn and inetdOut file descriptors, so that it’s possible to use a pair of pipes in place of a socket. It’s also possible to work around the problem at hand by using socat(1) and strace(1) as follows. #!/bin/sh ### tightvnc-ssh-pipe.sh ## Example Xtightvnc tunneling via SSH pipes. ## Connect with: ## $ xvncviewer localhost::12345 LOCAL_PORT=12345 REMOTE=remote.example.net ## . exec socat TCP4-LISTEN:"$LOCAL_PORT",bind=localhost \ EXEC:"ssh -t -- ${REMOTE} \ set -C -e -u -- ; stty raw -echo ; exec 3<> /dev/tty ; \ strace -o /tmp/debug.\"$(date +%s.%N)\" -ft -s95 \ -e trace=dup2 -e trace=setsockopt \ -e inject=setsockopt\\:retval=0\\:when=4 \ -e inject=dup2\\:retval=3\\:when=1 \ -- Xtightvnc \\:99 -auth \"\$HOME\"/.Xauthority \ -geometry 1280x$((1024 - 2 * 24)) -depth 24 \ -dontdisconnect -nevershared -inetd",pty ### tightvnc-ssh-pipe.sh ends here Here, ssh -t, together with the socat(1) ,pty option, forces pseudo-tty allocation on the remote side; exec 3<> /dev/tty redirects file descriptor 3 (which is the number inetdSock is set to) to the pty thus allocated; -e inject=dup2:retval=3 :when=1 turns the dup2(2) call in init.c into a no-op; and -e inject=setsockopt:retval=0:when=4 does the same to the setsockopt(2) call in sockets.c. Also, while we’re at it, note that Xtightvnc above ignores the :99 option and binds to /tmp/.X11-unix/X1, as if :1 were given. It should be noted that the use of pipes, or actually -inetd / inetd.conf(5) ‘nowait’, means that the failure of the underlying connection invariably leads to the termination of the associated X session. (While with the VNC server possessing a listening socket, which is the default case, and also would’ve been one were Xtightvnc(1) to support ‘wait’ inetd.conf(5) option, it’s possible to reconnect.) IME in LAN environments, it’s an acceptable tradeoff. Ideally, this should be complemented by a -command option in xvncviewer(1), to access the remote server by starting the command given in place of opening a TCP connection directly (not unlike ssh_config(5) ProxyCommand option.) But that deserves a separate report IMO. -- FSF associate member #7257 http://am-1.org/~ivan/