qemu VNC with native websockets & noVNC

so, if you’ve attempted to get noVNC working with qemu’s native websockets support… believe it or not, but it can actually be made to work. I had to find some esoteric documentation, read a few qemu source files in git, qemu –help, even the man page.

most shitty sticking points:

  • ca-crl.pem must exist
  • ca-cert.pem must be trusted on client machine
  • no sort of vnc related err/warning output from qemu, odd because it seemed to be there in the code.

so, first off. maybe you tried to get it working unencrypted? maybe that went alright if you were not accessing the vnc.html file over https (something i didn’t even bother testing because it is pointless). if you use https, the browser won’t let you use websockets w/o tls.

next up, the qemu command line, we’re looking at the -vnc option.

working:

-vnc
 # listen for VNC on 0.0.0.0:5910
  :10,
 # listen for WebSocket VNC on 0.0.0.0:5710
  websocket,
 # use TLS server credentials in directory
  x509=/etc/ssl/qemu/<HOST>,
  # not using password or sasl
  nopassword,nosasl,
  # completely optional i think
  share=allow-exclusive

other options:  
  tls: must not be used,
    specifies another encryption (VeNCrypt) after TLS,
    refused by noVNC.
  password: could be used probably, untested
  sasl: hard to imagine novnc support
  x509verify: don't use. 
    unclear how novnc would support a client certificate

so what goes into the credentials directory? well, isn’t it amazing how many efforts have been made to secure VNC … so badly? it’s really a coordination problem, but anyway. now that i have a functional config, i will probably go back and attempt to get higher quality keys and certs. my initial attempts w/ high-secure credentials segfaulted qemu on connect.

the required files are listed in ui/qemu-x509.h

#define X509_CA_CERT_FILE “ca-cert.pem”
#define X509_CA_CRL_FILE “ca-crl.pem”
#define X509_SERVER_KEY_FILE “server-key.pem”
#define X509_SERVER_CERT_FILE “server-cert.pem”

get ready to dive into some gnutls certtool and bust out some piss poor creds.

# make credentials dir
mkdir -p /etc/ssl/qemu/<HOST>  
cd /etc/ssl/qemu/<HOST>

# make a CA signing key
certtool --generate-privkey --sec-param high > ca-key.pem

# make a CA self signed cert
cat > ca.info <<EOF  
cn = SOME NAME  
ca  
cert_signing_key  
EOF  
certtool --generate-self-signed --load-privkey ca-key.pem \  
  --template ca.info --outfile ca-cert.pem

# make a (n empty) CA cert revocation list
certtool --generate-crl --load-ca-privkey ca-key.pem \  
  --load-ca-certificate ca-cert.pem --outfile ca-crl.pem
crl number ... 1000? why not.

# make a server key
certtool --generate-privkey \  
  --sec-param high > server-key.pem

# make a server certificate, signed by CA
cat > HOST.info <<EOF  
cn = <HOSTNAME>  
tls_www_server  
encryption_key  
signing_key  
EOF  
certtool --generate-certificate \  
  --load-ca-certificate ca-cert.pem \
  --load-ca-privkey ca-key.pem \
  --load-privkey server-key.pem \
  --template HOST.info --outfile server-cert.pem

# chmod the keys?
chmod go-rwx ca-key.pem server-key.pem

# now copy the ca-cert.pem file to your client machines, 
#   change the extension to cert.
# on a Mac, double click the cert file,
#   add it in Keychain Access

in noVNC, some things

Setting “True Color” must be used. It triggers the use of tightvnc encoding in noVNC, seems to be required by qemu.
Make sure you are using the 57xx port (not 59xx) and the exact HOSTNAME that you used in the server certificate .info file
Error “Server Disconnected: 1006″ is incredibly meaningless, anything from connection refused to … well … anything. You can sometimes get a realer inkling of actual error conditions from the javascript console. don’t be fooled by noVNC attempting a dummy connect to a maybe weird url, it’s just determining whether you have websockets there.
openssl s_client -connect HOST:57xx can be helpful for debugging so yeah, now you just might be able to use noVNC to connect to your qemu VNC.

UPDATE: further testing has shown that symlinks work, leading me to restructure the PKI stuff like so:

/etc/ssl/qemu/
/etc/ssl/qemu/HOST        # REAL FILES
/etc/ssl/qemu/HOST/HOST_wss.crt
/etc/ssl/qemu/HOST/HOST_wss.info
/etc/ssl/qemu/HOST/HOST_wss.key
/etc/ssl/qemu/ca          # REAL FILES
/etc/ssl/qemu/ca/ca-cert.pem
/etc/ssl/qemu/ca/ca-crl.pem
/etc/ssl/qemu/ca/ca-key.pem
/etc/ssl/qemu/ca/ca.info
/etc/ssl/qemu/vm_host1    # ALL SYMLINKS
/etc/ssl/qemu/vm_host1/ca-cert.pem
/etc/ssl/qemu/vm_host1/ca-crl.pem
/etc/ssl/qemu/vm_host1/server-cert.pem
/etc/ssl/qemu/vm_host1/server-key.pem
/etc/ssl/qemu/vm_host2    # ALL SYMLINKS
/etc/ssl/qemu/vm_host2/ca-cert.pem
/etc/ssl/qemu/vm_host2/ca-crl.pem
/etc/ssl/qemu/vm_host2/server-cert.pem
/etc/ssl/qemu/vm_host2/server-key.pem