Documentation

Server 2.x

Version 2.x of eduVPN is End of Life (EOL). Switch to "Server 3.x" Documentation!

Port Sharing#

This document describes how to configure your VPN server in such a way as to make it most likely people can connect to it. This is done by making it possible to connect to the VPN service using both udp/443 and tcp/443. A complication here is that the web server claims tcp/443, so we need to share tcp/443 between the web server and OpenVPN. We’ll use sslh for this task.

In larger deployments you’ll want to use multiple machines where the portal and API run on a different machine from the OpenVPN backend server(s) so port sharing is not needed, i.e. OpenVPN can claim tcp/443 directly.

VPN#

We need to edit /etc/vpn-server-api/config.php and modify vpnProtoPorts and set exposedVpnProtoPorts. The vpnProtoPorts option includes the protocols and ports the OpenVPN processes actually listen on, and exposedVpnProtoPorts is what the client will get. So here we do not expose tcp/1194, but tcp/443 instead:

'vpnProtoPorts' => [
    'udp/443',
    'tcp/1194',
],

...

'exposedVpnProtoPorts' => [
    'udp/443',
    'tcp/443',
],

In vpnProtoPorts we make OpenVPN listen on tcp/1194 and NOT on tcp/443, we need tcp/443 for sslh to listen on. It will forward connections to tcp/443 to tcp/1194 internally (or to the web server, depending on what makes the request).

You may also want to modify the range setting. For 4 OpenVPN processes we recommend to use a /24 IP range. For the IPv6 range nothing needs to change as the default is a /64 which is big enough.

If you specify any of the “special” ports, i.e. udp/443, tcp/443, udp/53 or tcp/80 they are ALWAYS added to the generated client configuration next to one “normal” UDP and TCP port. This way, when the connection to the normal ports fails, there is a fallback to the special ones which have a higher chance of working.

Web Server#

CentOS / Fedora#

Modify /etc/httpd/conf.d/ssl.conf and modify Listen 443 https to Listen 8443 https.

In /etc/httpd/conf.d/vpn.example.conf, where vpn.example is your actual VPN hostname, you modify <VirtualHost *:443> to <VirtualHost *:8443>.

Debian#

Modify /etc/apache2/ports.conf and change the Listen lines to Listen 8443 from Listen 443.

In /etc/apache2/sites-available/vpn.example.conf, where vpn.example is your actual VPN hostname, you modify <VirtualHost *:443> to <VirtualHost *:8443>.

Proxy#

CentOS/Fedora#

Install sslh:

$ sudo yum -y install sslh

Configure sslh, we use the following configuration file in /etc/sslh.cfg:

verbose: false;
foreground: true;
inetd: false;
numeric: false;
transparent: false;
timeout: 5;
user: "sslh";
listen:
(
    { host: "0.0.0.0"; port: "443"; },
    { host: "::"; port: "443"; }
);
protocols:
(
     { name: "openvpn"; host: "localhost"; port: "1195"; },
     { name: "ssl"; host: "localhost"; port: "8443"; log_level: 0; }
);

Debian#

Install sslh:

$ sudo apt -y install sslh

Modify /etc/default/sslh by changing DAEMON_OPTS:

DAEMON_OPTS="--user sslh --listen 0.0.0.0:443 --listen [::]:443 --tls 127.0.0.1:8443 --openvpn 127.0.0.1:1194 --pidfile /var/run/sslh/sslh.pid"

Let’s Encrypt#

CentOS/Fedora#

If you are using Let’s Encrypt with automatic certificate renewal you should modify your /etc/sysconfig/certbot and set the PRE_HOOK and POST_HOOK to stop/start sslh and httpd:

PRE_HOOK="--pre-hook 'systemctl stop sslh httpd'"
POST_HOOK="--post-hook 'systemctl start sslh httpd'"

Debian#

I have no idea how to properly configure certificate renewal on Debian…

SELinux#

On CentOS/Fedora you need to modify SELinux to allow OpenVPN to listen on udp/443, or any of the other ports you decided to use, e.g.:

$ sudo semanage port -a -t openvpn_port_t -p udp 443

Firewall#

You need to update the firewall to allow access to udp/443. Look here.

Applying#

CentOS/Fedora#

$ sudo systemctl restart httpd
$ sudo systemctl enable --now sslh

To apply the configuration changes:

$ sudo vpn-maint-apply-changes

If the command is not available, install the vpn-maint-scripts package first.

Debian#

On Debian, make sure to disable mod_status, otherwise /server-status will be accessible to the whole world. It is enabled by default, and restricted to localhost, which is exactly where web request appear to be coming from when using sslh.

$ sudo a2dismod status
$ sudo systemctl restart apache2
$ sudo systemctl restart sslh

To apply the configuration changes:

$ sudo vpn-maint-apply-changes

If the command is not available, install the vpn-maint-scripts package first.