Secure VNC configuration for RHEL7

Latest response

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

Hello

>Shortcomings:
- VNC password is not encrypted (but it's not plain text)
A shortcoming of VNC rather than the description I think. and hence the section on using SSH.
- 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.
I will mention this point to the software maintainers.
- Configuration is not user independent, one config for each user.
I'll mention this, but I think this is a systemd issue rather than a VNC issue.
- Transport not encrypted (at least with Windows vnc viewer from realvnc)
Hence the section on using SSH. Is there no SSH for Windows?
- Logout does not work (at least on my test server)
I did not notice this when I tested the procedures. Is there something I should add?

Goals:
- User authentication upon connection
- Encrypted traffic using ssh port forwarding
Would using SSH cover the above two goals?
- User independent configuration
I will mention this, see response above.

Close

Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.