Featherweight Linux VNC services

This article describes how to set up a very lightweight VNC service under CentOS/Red Hat.

Virtual_Network_Computing_(logo).svg

Intro

In Red Hat Enterprise Linux (and derivates, I use CentOS) you can run a VNC service to allow graphical connections to a linux system. I was looking for a very lightweight VNC service (no fancy desktop with all the bells and whistles, just something that lets me do some stuff that requires an X session and run an Xterm – such as installing Oracle or running Swingbench, without using another host with an X client). In other words, a typical service for virtual machines that run as servers (such as database servers, web servers, etc).

CentOS standard method

I tried the standard documented way to do this in CentOS: CentOS Virtual Network Computing using the standard tigervnc-server method, but found a few issues with the way they set it up:

  • For every user requiring VNC services, you need to customize the configuration
  • If one user deletes or corrupts his VNC password file, the whole service stops working (fix via normal SSH login but requires skilled user)
  • If a user messes up his xstartup file he is locked out (fix via normal SSH login but requires skilled user)
  • Users need 2 passwords: for their (own) VNC service, and the usual one for Linux
  • Their X window and VNC processes are always running and thus eating resources even if not used
  • If their X session hangs (i.e. window manager killed, or simple logout) it’s hard or even impossible to clean up and restart (see section 4 in the mentioned article: Recovery from a logout) without resetting the whole VNC service
  • Every user requires a separate, unique TCP port

All by all, nice and easy for a small test server with a few users, but no good for larger environments. The good thing is that the desktops are persistent, i.e. you may disconnect and reconnect later and the VNC session will be as you left it. And you can install lighter desktop environments (twm or openmotif) instead of the huge and heavy Gnome desktop.

But I was looking for something better.

CentOS LTSP method

The other option is to use the non-persistent method described in the CentOS article under “5. Remote login with vnc-ltsp-config”. Instead of using a VNC password, it offers a desktop login screen if you connect to the VNC service. It also does not require any per-user setup, so that’s good!

So I tried that method as well, and also found it still less-than-ideal:

  • It requires to install the entire Gnome desktop. I think that’s enormous overkill for the need to run an Xterm in a VNC session.
  • It requires to run in Linux runlevel 5 with a graphical login on the VM’s admin console open at all times. More resources wasted as usually no-one will ever login via the VM’s console.
  • No way to have persistent desktops any more. If you log out, session is killed.
  • It’s only available via the EPEL repository for CentOS / Red Hat 5.x. 6.x does not provide the package (however if you install the 5.x package on 6.x it works fine).

Dirty Cache method

As my blog is all about doing more with less, I took up the gauntlet and started to figure out how I could have the best of all worlds. My service is called “lightvnc” and is available as an RPM package via my repository (see Software tab on this blog). If you don’t care how it works but just want to use it, just install the rpm and off you go. I recommend reading the man page for configuration details.

Lightvnc offers:

  • Login manager XDM
  • Window manager Openmotif (spartan, simple but very lightweight)
  • Based on xinetd and xdm, no other daemons or services required until a connection is made
  • VNC service on default port 5900, non-persistent, Multiple simultaneous users
  • VNC service on port 5901, persistent (static), one user at a time, password protected
  • Near-zero mem/cpu resources after the last user logs out
  • Both the persistent and nonpersistent VNC service can be easily enabled/disabled
  • Screen resolution adjustable
  • On a CentOS minimal install, it requires 77 MB in 30 additional packages (mostly the X libraries, fonts, and the tigervnc-server itself and the majority of packages are dependencies for tigervnc). Not too bad ey?

Lightvnc internals

How does it work? I needed to sort out a lot of nasty details to get it going. First of all, the standard “gdm” X display manager only seems to support Gnome. I tried using Openmotif with gdm but couldn’t get it to work properly. Decided to ditch gdm and go for XDM instead. However, using XDM resulted in pitch black VNC windows that would not respond to anything. Hard troubleshooting teached me the following:

# cat /etc/X11/xdm/xdm-config
...
! SECURITY: do not listen for XDMCP or Chooser requests
! Comment out this line if you want to manage X terminals with xdm
DisplayManager.requestPort: 0

The port setting of 0 somehow results in XDM trying to listen on IPv6 (which is not configured on my system). The Xvnc server seems to get an X login on an IPv4 port. Setting it hardcoded to 177 (the standard XDMCP port anyway) did the trick.

Other things that I needed to make it work (all in the RPM package):

  • /etc/X11/xdm/Xservers is only used for local attached screens, removing the only entry prevents from X trying to start an X desktop on the system console.
  • /etc/X11/xdm/Xaccess: should listen on 0.0.0.0 (forcing it to listen on IPv4 any network) and allow any access.
  • /etc/init/prefdm.conf is configured to start on runlevel 5 only, changed to start at levels 3 and 5 so we don’t need to change runlevels. I guess runlevel 5 is only for systems serving desktops on directly attached screens. Using an override file (/etc/init/prefdm.override) to avoid RPM updates to “initscripts” breaking this setting or breaking other packages.
  • Added /etc/sysconfig/desktop with an entry to change the default display manager to XDM
  • Added a line to /etc/services for port 5901 (5900 already there). Needed for xinetd.
  • Added entries to support openmotif in /etc/X11/xdm/Xsession pointing to xclient-mwm that starts an openmotif / mwm session if users login.
  • Wrote a script /usr/bin/vncwrapper that is called by xinetd and parses /etc/sysconfig/vncservers configuration before executing Xvnc in turn
  • Wrote a script /usr/bin/vnc-setpass that needs to be run (as root) to create a system-wide /etc/vncpass file before connections to the static service can be allowed
  • Created /etc/xinetd.d/vnc and ./vnc-static configuration files for xinetd.
  • Wrote a SPEC file to build an RPM package (lightvnc-*.rpm) with the above items.

Some CLI stuff and screenshots

After installation:

# ps aux|grep -iE "xdm|vnc"|grep -v grep
root 1509 0.0 0.0 48452 1784 ? Ss 19:47 0:00 /usr/bin/xdm -nodaemon

No services are running except xdm. Memory usage is very low.

# netstat -apt|grep vnc
tcp 0 0 *:vnc-server *:* LISTEN 1230/xinetd
tcp 0 0 *:vnc-static *:* LISTEN 1230/xinetd

inetd listens on both ports.

For the sake of this blogpost I changed the resolution on the VNC service to 300×200 to allow smaller pictures. The default resolution is 1024×768.

lightvnc-login

X screen with very simple login. Note that root is not allowed (I didn’t do that, probably an XDM feature).

lightvnc-desktop

The lightvnc desktop. Fancy stuff, ey? Show THIS at the next Linux install party!

Xterm and right-click menu

Xterm and right-click menu

Let’s take a look at the resources consumed by all this eye candy:

nobody 1766 0.1 0.6 87232 11836 ? Ss 20:27 0:00 /usr/bin/Xvnc -inetd -query localhost -SecurityTypes None -desktop centosvm -geometry 400x300
root 1783 0.0 0.1 92452 3248 ? Ss 20:27 0:00 -centosvm:0
bart 1798 0.0 0.0 106060 1340 ? Ss 20:31 0:00 /bin/sh /etc/X11/xdm/xclient-mwm
bart 1817 0.0 0.0 57700 740 ? Ss 20:31 0:00 /usr/bin/ssh-agent /etc/X11/xdm/xclient-mwm
bart 1820 0.0 0.2 163100 5004 ? S 20:31 0:00 mwm
bart 1837 0.4 0.3 160944 7080 ? S 20:36 0:00 xterm

The first 5 processes is what every logged-in user needs. Xterm is something we started as an extra.

Let’s login to the static VNC desktop:

(from another Linux machine)

vncviewer centosvm:1

VNC Viewer Free Edition 4.1.1 for X - built Feb  5 2012 20:01:21
Copyright (C) 2002-2005 RealVNC Ltd.
See http://www.realvnc.com for information on VNC.

Wed Jul  2 20:44:45 2014
CConn:       connected to host centosvm port 5901
CConnection: Server supports RFB protocol version 3.8
CConnection: Using RFB protocol version 3.8
Password:
Wed Jul  2 20:44:55 2014
main:        No password configured for VNC Auth

No password = no connections allowed. Create a (system-wide) password first!

# vnc-setpass 
Usage: vnc-setpass 
Sets the password for static VNC services on port 5901 (vnc :1)
# vnc-setpass dirtycache
# ls -al /etc/vncpass 
-r-------- 1 nobody root 8 Jul  2 20:46 /etc/vncpass

Now you can connect to screen 1 as usual. If you disconnect, the session will stay active (no timeout). Re-connect to <host>:1 and you can continue where you left. That’s why there is a system-wide password; otherwise you could login as “foo”, and disconnect, and “bar” could pick up your session without passwords…

You can enable/disable both services with chkconfig:

# chkconfig

xinetd based services:
...
...
time-dgram: off
time-stream: off
vnc: on
vnc-static: on

# chkconfig vnc off
# chkconfig
...
...
time-dgram: off
time-stream: off
vnc: off
vnc-static: on

otherhost $ vncviewer centosvm
...
main:        unable to connect to host: Connection refused (111)

Note that I logged out from the VNC-static service by ending the MWM session. The VNC desktop shows the login screen again. For the static session, the login screen will wait until a VNC session reconnects:

# ps aux | grep nobody

nobody 1996 0.1 0.8 90648 15476 ? Ss 20:44 0:00 /usr/bin/Xvnc -inetd -query localhost -PasswordFile /etc/vncpass -desktop centosvm

You may kill this session without problems. It will restart as soon as you connect on 5901. Note that a “chkconfig vnc-static off” will also result in ending this process (through xinetd).

Want to change resolution or other Xvnc options? Edit /etc/sysconfig/vncservers:

# VNCSERVERS="2:myusername"
# VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -localhost"
VNCSERVERARGS[0]="-geometry 400x300 -nolisten tcp -localhost"

TigerVNC uses this config file anyway (for the standard CentOS method) and I decided to just re-use this file for the same purpose. Here you can see how I changed the geometry for VNC session 0 to create smaller screenshots for the blog. Note that nolisten, tcp, localhost are ignored by lightvnc as they are handled by xinetd. Other options are passed on to Xvnc. If for example you want to change the resolution for vnc-static, make an entry for VNCSERVERARGS[1].

Final note

Running VNC services this way, even with passwords, transfers data over the network UNENCRYPTED! Only use it on trusted networks, or wrap the traffic in some sort of encrypted tunnel. You have been warned.

If you know Linux, VNC and xinetd a bit, you probably will figure out how to have a 1024×768 screen on default port 5900, a 1280×1024 on vnc-static port 5901, and an additional non-persistent service on port 5902 with 1600×1200 resolution. Shouldn’t be that hard anymore.

Update 2014-10-24

– Some people seem to end up with a black window (moving X cursor only, no login screen). Seems to be network related – for sure xdm is sensitive for correct DNS forward/reverse solving etc. But haven’t catched the root cause yet. If you have this issue, let me know so we can resolve it.

– Only works on RHEL/CentOS/OEL v6 (version 7 seems to be missing the XDM package).

Enjoy!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: