Secure VNC configuration for RHEL7
Hello
I want to deploy a secure vnc configuration on my RHEL7 servers.
We use Windows clients with Putty and VNC Viewer from RealVNC Ltd.
I don't really like the standard configuration for tigervnc as it is documented here:
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/ch-TigerVNC.html
Shortcomings:
- VNC password is not encrypted (but it's not plain text)
- No system authentication (session is started upon service start)
eg. start service for given user, lock account of user, connect with vnc client, guess what happens.
- Configuration is not user independent, one config for each user.
- Transport not encrypted (at least with Windows vnc viewer from realvnc)
- Logout does not work (at least on my test server)
Goals:
- User authentication upon connection
- Encrypted traffic using ssh port forwarding
- User independent configuration
In RHEL6, I used a configuration based on xinetd.
Now that I'm starting to use RHEL7 it's time to get familiar with systemd.
This is what I got so far:
Create systemd service:
The configuration uses a systermd socket instead of inetd, as described here:
http://0pointer.de/blog/projects/inetd.html
/etc/systemd/system/vncserver-gdm-local.socket
[Unit] Description=vncserver socket with gdm listening on localhost [Socket] ListenStream=127.0.0.1:5900 Accept=yes [Install] WantedBy=sockets.target
Second is the service definition.
Because I did not find how to bind the xdmcp and X service only to localhost I made a dependency to firewalld
If firewlld is stopped it will be started - if firewalld is stopped, vncserver will be killed.
Uncomment one of the ExecStart lines, depending if you want a pre-authentication with vnc (-securitytypes=VncAuth -rfbauth=/etc/vncpasswd) or not.
/etc/systemd/system/vncserver-gdm-local@.service
[Unit] Description=vncserver with gdm and firewalld dependency Requires=firewalld.service Requires=gdm.service [Service] #ExecStart=-/usr/bin/Xvnc -inetd -query localhost -geometry 1024x768 -depth 16 -once -securitytypes=VncAuth -rfbauth=/etc/vncpasswd #ExecStart=-/usr/bin/Xvnc -inetd -query localhost -geometry 1024x768 -depth 16 -once -securitytypes=none User=nobody Group=tty StandardInput=socket
For pre-authentication create the password file
# vncpasswd /etc/vncpasswd # chown nobody /etc/vncpasswd
Make gdm ready for network connection.
/etc/gdm/custom.conf
[xdmcp] Enable=true [security] DisallowTCP=false
Start service
# systemctl daemon-reload # systemctl restart gdm.service # systemctl enable vncserver-gdm-local.socket # systemctl start vncserver-gdm-local.socket
Connect with vnc viewer.
On Windows, I use a wrapper scrip to connect, see below.
Check:
# systemctl status vncserver-gdm-local.socket vncserver-gdm-local.socket - vncserver socket with gdm listening on localhost Loaded: loaded (/etc/systemd/system/vncserver-gdm-local.socket; enabled) Active: active (listening) since Wed 2015-05-13 14:52:40 CEST; 5min ago Listen: 127.0.0.1:5900 (Stream) Accepted: 3; Connected: 1 May 13 14:52:40 example.com systemd[1]: Listening on vncserver socket with gdm listening on localhost.
Things that do not work:
- Screen resolution, same as:
https://access.redhat.com/discussions/1261403
- Copy/paste in gdm:
I want to use vncconfig to enable copy/paste for the login screen, but I had no luck with the gdm configuration.
Open points:
- Is it really secure?
- Is there another way to run gdm in vncserver (without using xdmcp)?
- Is there a way to configure gdm and Xvnc to listen only on localhost?
Regards
Kolja
Windows wrapper:
@echo off mode con: cols=40 lines=10 set server=%1 if "%server%" == "" ( set /p server= "Enter Servername: " ) set remote_user=adm_%username% set port=5901 goto :check_portfree :inc set /a port=(%port% + 1) :check_portfree netstat -tnoa|findstr "127.0.0.1:%port%"|findstr LISTEN if ERRORLEVEL 1 ( echo port %port% free goto :run_wrapper ) else ( echo port %port% used goto :inc ) goto :eof :run_wrapper set prog=start /MIN "vnc tunnel: %server%@%port%" "C:\Program Files\PuTTY\plink" -4 -L %port%:127.0.0.1:5900 %remote_user%@%server% -N %prog% rem wait until port is used :check_portused netstat -tnoa|findstr "127.0.0.1:%port%"|findstr LISTEN if ERRORLEVEL 1 ( echo Waiting for plink ping -n 2 localhost > nul goto :check_portused ) for /F "tokens=5" %%c in ('netstat -tnoa^|findstr "127.0.0.1:%port%"^|findstr LISTEN') do set plink_pid=%%c "C:\Program Files\RealVNC\VNC Viewer\vncviewer.exe" -SecurityNotificationTimeout=0 WarnUnencrypted=0 127.0.0.1:%port% taskkill /PID %plink_pid%
Responses