Guide to Tunnelling with xvpweb

  1. Introduction
  2. Architecture in Detail
  3. Configuring SELinux
  4. Configuring xvp and xvpweb
  5. Tunnelling over HTTP
  6. Tunnelling over HTTPS
  7. Round-Robin, Web Caching, and Reverse Proxy Scenarios

1. Introduction

This document explains how you can set up xvp, xvpweb and an Apache web server so that all communication between xvpweb and xvp goes via the web server, instead of having VNC console connections made directly from xvpweb to xvp. This involves tunnelling (or tunneling, if you're American) of the VNC connections over HTTP or HTTPS, and is supported in xvp release 1.3.0 and later.

xvpappliance release 1.5.1 and later has tunnelling support built in, so if you're using this, you do not need to carry out any of the configuration steps below, but you may wish to read on for interest.

Note: Standard version 2.2 of the Apache Web Server (at least up to version 2.2.15, at the time of writing) supports tunnelling over HTTP but not over HTTPS. It is possible, however, to build a patched Apache which will support HTTPS-based SSL-encrypted tunnelling. This feature will be included as standard in Apache 2.4. If you're not able to patch Apache 2.2, you will need to stick with tunnelling over HTTP, or wait to upgrade to Apache 2.4 when it is released.

For more general information about xvp, return to the Main Page.


2. Architecture in Detail

When deploying xvp with the xvpweb web-based front end, there are two alternative ways in which the xvpviewer Java applet (included with xvpweb) can make a VNC connection to xvp, in order to display virtual machine consoles:

  1. Directly

    This is the default behaviour. The applet connects directly to a VNC port on xvp, and communicates using the standard protocol for VNC, which is RFB (Remote Frame Buffer), plus XVP extensions to the RFB protocol (for example, to perform shutdown, reboot, etc).

    This is illustrated in the first diagram below, where this VNC connection is shown by a solid line (RFB+XVP), and the other related connections by dashed lines.

    This arrangement has the advantage that the web server needs to know nothing about the VNC connection. It also allows a choice of having xvp listen on multiple VNC ports (one per virtual machine) or a single multiplexing port: whichever is more convenient depends partly on who is meant to be able to connect to which virtual machines and how you want to manage any firewalls.

  2. Tunnelling via the Web Server

    If you configure this behaviour, then xvpviewer tunnels its VNC connection via its existing HTTP or HTTPS connection to the web server, and the web server then forwards the connection to xvp.

    This is shown in the next diagram below. Again, the solid lines represent the path of the console connection between the applet and xvp.

    This arrangement means that you only need to allow the web browsers and Java applets to access one port on one server, typically port 80 for HTTP or port 443 for HTTPS. You still have the choice of allowing xvp to listen on multiple ports or just one, although if you're not using any VNC clients other than xvpviewer, it's probably simplest to use a single multiplexing port.

    This tunnelling arrangement is likely to be preferred by firewall administrators. However, it does complicate the web server configuration: this is particularly the case if you want to use HTTPS, as explained further below.

Note:

Regardless of which of the two architectures you deploy, the xvp proxy server needs, as far as web clients are concerned, to run on the same machine as the web server. Some round-robin, web caching, and reverse proxying alternatives are possible: there are more details about this at the end of this document.


3. Configuring SELinux

If you are running Apache on a Red Hat, CentOS or Fedora Linux distribution, with SELinux set to enforcing, the default policy will prevent Apache from connecting out, and thus disable its HTTP CONNECT support. You can check by typing the following 2 commands as root, and seeing if the output is as shown:

    # getenforce
    Enforcing
    # getsebool httpd_can_network_connect
    httpd_can_network_connect --> off

If this is what you see, you must allow Apache to connect out, by typing:

    # setsebool -P httpd_can_network_connect 1

If you omit this step, then xvpviewer launched from xvpweb will display Network Error: Proxy reports "HTTP/1.1 502 Bad Gateway" and fail to connect.


4. Configuring xvp and xvpweb

If you wish to use tunnelling, you need a line in your xvp.conf file, as seen by both xvpweb and xvp, to tell them this. If you're using VNC clients other than the xvpviewer applet in xvpweb as well, this should read:

    OTP ALLOW IPCHECK HTTP [ time-window ]

or if you want to restrict access to xvpweb, use:

    OTP REQUIRE IPCHECK HTTP [ time-window ]

The examples below assume you will use the default VNC port (5900), as a single multiplexing port, in which case the above line in xvp.conf needs to be followed by one saying:

    MULTIPLEX 5900

For more information about this, refer to the xvp.conf manual page, and also see the xvpdiscover manual page (xvpdiscover can help you write an xvp.conf file).

Because tunnelling over HTTPS is more complicated to set up than over HTTP, I suggest you test using HTTP first, and then convert to or add HTTPS support.


5. Tunnelling over HTTP

Start by configuring xvp and xvpweb for tunnelling, as described above, and ensure that client web browsers can access the main page of xvpweb at the relevant URL, e.g. http://www.mycompany.com/xvpweb.

For security reasons, you probably want to force clients to authenticate before they can access this page and related ones. One simple option, e.g for inside a company network with a few authorised users, would be to add to your Apache configuration something like:

    <Location /xvpweb>
      AuthType Digest
      AuthName "xvpweb"
      AuthDigestDomain /xvpweb/
      AuthDigestProvider file
      AuthUserFile /etc/xvpusers.digest
      Require valid-user
    </Location>

In reality, something like this is sensible to use whether you are using tunnelling or not. For the example as shown, you would use the htdigest command-line tool to create and add user entries to the /etc/xvpusers.digest file. The permissions on the digest file should be such that only root can update it and only the Apache user account can read it, e.g.

  # ls -l /etc/xvpusers.digest
  -rw-r----- 1 root apache 137 Nov 27 09:23 /etc/xvpusers.digest

If you are using a standard Linux distribution Apache on Red Hat, CentOS or Fedora Linux, the above additions to your Apache configuration can simply be placed in a new file /etc/httpd/conf.d/xvpweb.conf, and then Apache restarted to pick up the change.

To actually enable tunnelling, you need to enable proxy requests in Apache, using ProxyRequests.

Warning:

If you just enable ProxyRequests, without securing your server, then you will create an open proxy, through which anybody from anywhere can connect to anywhere else. This would be very dangerous for you, and for everybody else on the Internet. The example configuration below is secure: be careful in adapting it.

A complete example is shown below. You would add these lines to your Apache configuration, as with the authentication statements suggested above, e.g. append to your /etc/httpd/conf.d/xvpweb.conf. In this example, we have a company with Internet domain mycompany.com, and an internally-hosted web server www.mycompany.com. It is running xvp on multiplexing port 5900, and we want to allow tunnelling access only for users from within the company's domain:

    ProxyRequests On
    AllowCONNECT 5900
    
    <Proxy *>
      Deny from all
    </Proxy>
    
    <Proxy www.mycompany.com:5900>
      Deny from all
      <Limit CONNECT>
        Order Deny,Allow
        Deny from all
        Allow from 127.0.0.1 mycompany.com
      </Limit>
    </Proxy>

    <Proxy www:5900>
      Deny from all
      <Limit CONNECT>
        Order Deny,Allow
        Deny from all
        Allow from 127.0.0.1 mycompany.com
      </Limit>
    </Proxy>

    <Proxy localhost:5900>
      Deny from all
      <Limit CONNECT>
        Order Deny,Allow
        Deny from all
        Allow from 127.0.0.1
      </Limit>
    </Proxy>

Note in particular the Deny from all inside the <Proxy *> block, which denies all proxying by default, and the statements inside the <Limit CONNECT> blocks, which ensure that only HTTP CONNECT proxying is allowed (as opposed to general HTTP or FTP proxying), and only from computers on our trusted domain.

For completeness, as well as allowing proxying through www.mycompany.com, the above configuration also allows internal clients referring to the web server as just www to successfully tunnel, and allows a web browser running on the server itself to do so by using the localhost hostname. Depending on your environment, you may not need to include the final two blocks.


6. Tunnelling over HTTPS

Tunnelling over HTTPS is potentially more secure than using HTTP tunnelling or direct VNC console connections, because all the VNC data is then SSL-encrypted. Although passwords are handled securely by the VNC (RFB) protocol itself (using a random challenge and an encrypted response), the subsequent dialog, including all keyboard and mouse input and display output, is not transmitted in encrypted form unless SSL is used, and so could potentially be intercepted.

Assuming you have tunnelling working over HTTP, the configuration of xvp itself, and the authentication and connection-forwarding configuration for Apache, are the same.

Your first step is to configure Apache to accept web connections over HTTPS as well as HTTP, so that client browsers can access the main page of xvpweb at the relevant secure URL, e.g. https://www.mycompany.com/xvpweb.

The main difficulty is that, at the time of writing, standard distributions of Apache (at least up to 2.2.15) only support tunnelling over HTTP, not over HTTPS. Support for HTTPS-based tunnelling is due to appear in Apache 2.4, as a result of considerable demand from administrators. It is, however, possible to safely patch Apache 2.2 source and build a custom version that does support HTTPS tunnelling. There is information about this on the Apache web site at:

https://issues.apache.org/bugzilla/show_bug.cgi?id=29744

and postings there include versions of the patch for various standard Apache releases. If you are running Apache on CentOS 5.4, then the xvpsource web site has a suitable patch file and updated RPM spec file. To build a patched Apache on CentOS 5.4 using these:

  1. Right click on the above two links to download and save the files.

  2. Download the latest source RPM of httpd from the 5.4 updates area of a mirror of the CentOS web site.

  3. Login as root on the CentOS 5.4 system you want to patch Apache for (you'll need to be root for all the following steps).

  4. Install the source RPM using:

        # rpm -ivh httpd-version.src.rpm
    

    where version is the relevant version number.

  5. Copy the downloaded patch file into the directory /usr/src/redhat/SOURCES, with name httpd-2.2.3-proxytunnel.patch.

  6. Carefully update the file /usr/src/redhat/SPECS/httpd.spec by merging in the changes from the spec file you downloaded.

  7. Build the patched binary RPMs:

        # cd /usr/src/redhat
        # rm -f RPMS/*/*.rpm
        # rpmbuild -bb --define='dist .el5.centos' SPECS/httpd.spec
    

    This may fail immediately, saying "Failed build dependencies". In this case, install the prerequisite RPMs and try again. To install them on a 32-bit system, type:

        # yum install name name ...
    

    or on a 64-bit system:

        # yum install name.x86_64 name.x86_64 ...
    

    using the name of each missing dependency (e.g. apr-devel), and then repeat the rpmbuild command. Check that building was successful: at the end it should say "Wrote: ..." with the names of 5 RPM files.

  8. Go into the directory containing the built RPMs and install them, e.g.

        # cd /usr/src/redhat/RPMS/x86_64
        # rpm -Fvh *.rpm
    
  9. Finally, restart Apache:

        # service httpd restart
    

Note: if you later install a more recent build of Apache, as part of downloading regular CentOS updates, you'll undo your good work, and will need to repeat the above steps, starting from the newer source RPM.

If you can install a patched Apache, and you have configured it to use a SSL certificate signed by a well-known Certificate Authority (CA), then everything that works with xvpweb using HTTP should also work using HTTPS, and you may then wish to force users to use HTTPS (by using mod_rewrite to redirect in Apache itself, or by blocking port 80 with a firewall).

However, if you are using a self-signed SSL certificate, or one signed by an untrusted CA, the xvpweb Java applet will not be able to connect using tunnelling, unless you install the CA certificate (or the self-signed one if there is no CA in the certificate chain) into the Java keystore on each client computer. Some notes on how to do this can be found in the troubleshooting page on the xvpsource web site.


7. Round-Robin, Web Caching, and Reverse Proxy Scenarios

If you have a set of servers, all serving a website such as www.mycompany.com, each with a different IP address and with round-robin configured using DNS, simply install xvp and xvpweb with identical configurations on all of the servers, and you should have no problems.

If you have one or more reverse proxy servers, acting as load balancers, sitting in front of a set of backend web servers, such that the address www.mycompany.com resides on the load balancers, you need to be a little more careful. In this situation, you must install xvpweb on each of the backend servers, and xvp itself on the load balancers. Your xvp.conf file needs to be present on both front end and backends (and be the same on both). If you have a xvpusers.conf file, this is needed on the backends only. HTTP or HTTPS requests are sent to the load balancers, and reverse-proxied through to the backends. If you are using tunnelling, then the tunnel will go from the client through the front end to the backend, and from there the web server will connect to the console over VNC (RFB) to xvp back on the front end. This means that when the backend looks up the address of www.mycompany.com it must, like the clients, get the address of (one of) the front end(s). If you are not using tunnelling, the client will expect to be able to connect to consoles using VNC (RFB) directly to xvp, at the address of www.mycompany.com (i.e. on a load balancer).

If you have a web cache server in front of your web server(s), to reduce the load on them, then this is a similar situation to using reverse proxies (in fact, the two roles can be combined), and you need to install xvp itself on the front end cache server.

In understanding all this, be aware that a Java applet such as xvpviewer, running in a web browser, is restricted for security reasons to only make network connections to the server the applet itself was obtained from. In the above scenarios, this is still the case as far as the client is concerned: you're simply hiding the details of your server infrastructure from it.


Return to Main Page