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.