Archive for October, 2009

Fun with NX stuff

2009-10-15

So, I was trying out various NX servers because I’d had very good luck with NX in the past and generally found it faster than VNC, RDP, or X11 over SSH. My options appeared to be:

  • NoMachine’s server (here), which is free-as-in-beer but supports only 2 simultaneous sessions.
  • FreeNX made from the components that NoMachine GPLed. It’s open souce, but apparently is a total mess and notoriously hard to set up. However, it doesn’t limit you to two sessions, as far as I know.
  • neatX, implemented from scratch in Python/bash/C by Google for some internal project because apparently FreeNX was just too much of a mess. Like FreeNX, it lacks the two-session limitation; however, it doesn’t handle VNC or RDP, only X11.

NoMachine’s server was a cinch to set up (at least on Fedora). The only thing I remember having to do is put my local hostname (idiotbox) in /etc/hosts. Performance was very good (though I haven’t tried RDP or VNC over a slower link yet – only a LAN with VirtualBox’s built-in RDP server).

neatX was a bit tougher to set up, primarily because the documentation I saw was very sparse. This blog post was helpful. It advised that you should make sure you could log in with SSH manually before checking anything else, which gave me a starting point for my problems.

I took these notes on how I made it work:

  1. Install all of the dependencies it says. ALL OF THEM!
  2. Follow the other instructions in “INSTALL”.
  3. Go to /usr/local/lib/neatx and run ./nxserver-login
    If it looks like this, you’re probably good:

    [hodapp@idiotbox neatx]$ ./nxserver-login
    HELLO NXSERVER - Version 3.3.0 - GPL
    NX> 105

    If not, you may need to install some dependencies or check paths of some things. If it complains about not being able to import neatx.app, add something like this to the top of nxserver-login:

    import sys
    sys.path.append("/usr/local/lib/python2.6/site-packages")

    Replace that path with your own if it’s different, of course.
  4. Set up password-less login for user ‘nx‘ using something like ‘ssh-keygen -t rsa’ and putting the private & public keys someplace easy to find. Check that this works properly from another host (i.e. put the public key in the server’s authorized_keys file in ~nx/.ssh, copy the private key to the client, and use ‘ssh -i blahblahprivatekey nx@server’ there to log in. It should look something like this:

    chris@momentum:~$ ssh -i nx.key nx@10.1.1.40
    Last login: Sun Oct 11 13:11:49 2009 from 10.1.1.20
    HELLO NXSERVER - Version 3.3.0 - GPL
    NX> 105

    If it asks for a password, something’s wrong.
    If it terminates the connection immediately, SSH is probably okay, but something server-side with neatX is still messed up. SSH logs can sometimes tell things.

Once I’d done all this, neatX worked properly. However, I had some issues with it – for instance, sometimes the entire session quit accepting mouse clicks, certain windows quit accepting keyboard input, or things would turn very sluggish at random. But for the most part it worked well.

After setting up SSH stuff, FreeNX server worked okay from Fedora’s packages after some minor hackery (i.e. setting user the login shell for user ‘nx‘ to /usr/libexec/nx/nxserver. I haven’t yet had a chance to test it over a slow link, whether with X11 or RDP or VNC, but it worked in a LAN just fine. Someone in the IRC channel on FreeNode assures me that it runs flawlessly over a 256 kilobit link.

Then, for some reason I really don’t remember, I decided I wanted to run all three servers at once on the same computer. As far as I know, all of the NX clients log in to the server initially by passing a private key for user ‘nx‘. The server then runs the login shell set in /etc/passwd for nx – so I guess that shell determines which NX server handles the session.

So, amidst a large pile of bad ideas, I finally came up with this workable idea for making the servers coexist:  I would set the login shell to a wrapper script which would choose the NX server to then run. The only data I could think of that the NX client could pass to the server were the port number and the private key, and this wrapper script would somehow have to get this data.

Utilizing the port number would probably involve hacking around with custom firewall rules or starting multiple SSH servers, so I opted to avoid this method. It turns out if you set LogLevel to VERBOSE in sshd_config (at least in my version), it’ll have lines like this after every login from the NX client:
Oct 14 18:11:33 idiotbox sshd[15681]: Found matching DSA key: fd:e9:5d:24:59:3c:3c:35:c5:29:74:ef:6d:92:3c:e4
You can get that key fingerprint with ‘ssh-keygen -lf foo.pub‘ where foo.pub is the public key.

So I generated 3 keys (one for neatX, NoMachine’s server, and FreeNX), added them all to authorized_keys, found the fingerprints, and ended up with a script that was something like this:

#!/bin/sh
FINGERPRINT=$(grep "Found matching RSA key" /var/log/secure |
     tail -n 1 | egrep -o "(..:){15}..")
if [ $FINGERPRINT == "26:dd:67:82:c1:2d:cc:c0:c6:13:ac:d4:49:0e:79:a3" ]; then
    SERVER="/usr/local/lib/neatx/nxserver-login-wrapper"
elif [ $FINGERPRINT == "35:fb:bd:45:c5:71:91:ce:d6:d9:7f:0b:dc:84:f4:b3" ]; then
    SERVER="/usr/NX/bin/nxserver"
elif [ $FINGERPRINT == "b5:d7:a5:18:0d:c4:fa:18:19:58:20:00:1d:3b:3c:84" ]; then
    SERVER="/usr/libexec/nx/nxserver"
fi
$SERVER

I saved this someplace, set it executable, and set the login shell for nx in /etc/passwd to point to it. Make sure the home directory points someplace sensible too, as the install script for some NX servers are liable to point it somewhere else. But as far as I can tell, the only thing they use the home directories for is the .ssh directory and all the other data they save is in locations that do not conflict.So I copied the three public keys to the client and manually did ‘ssh -i blah.key nx@whatever‘ on each key.

chris@momentum:~$ ssh -i freenx-key nx@10.1.1.40
HELLO NXSERVER - Version 3.2.0-74-SVN OS (GPL, using backend: 3.3.0)
NX> 105
chris@momentum:~$ ssh -i neatx-key nx@10.1.1.40
HELLO NXSERVER - Version 3.3.0 - GPL
NX> 105
chris@momentum:~$ ssh -i nomachine-key nx@10.1.1.40
HELLO NXSERVER - Version 3.4.0-8 - LFE
NX> 105

The different versions in each reply were a good sign, so I tried the same keys in the client, and stuff indeed worked (at least according to my totally non-rigorous testing). Time will tell whether or not I completely overlooked some important details or interference.