Note: Cool Solutions are articles documenting additional functionality based on Univention products. Not all of the shown steps in the article are covered by Univention Support. For questions about your support coverage contact your contact person at Univention before you want to implement one of the shown steps.
Introduction
With the release of UCS 4.2 the portal page was introduced to UCS to enable companies, schools or organizations to offer a customized page to access available services. But wether it is the portal page, SAML authentifications, services like web mail or IMAP, it becomes increasingly important to give your users access to available services both from internal networks as well as from the internet. Therefore the goal of this cool solution is in presenting you with a way of making your services accessible independent of your users location. Starting off by explaining the conceptual idea and the related parts of your network infrastructure, we will give you an idea of how to implement a reverse proxy for external access.
Conceptual realization
In this section we want to give you an overview of the conceptual setup of your network infrastructure. For details on how this setup will be implemented see the section implementation.
Example network overview
The grafic below gives a conceptual overview of an example network infrastructure called company.example.org. The services that are provided for your users run on the servers located in the internal network. Users can either access them with clients of the internal private network or via the internet. If your users accesses your services through an internal network, the address of their request is translated by an internal DNS server to the corresponding IP address of the corresponding server, that runs the service. An examplary configuration can be seen in the graph. If a user types webmail.company.example.org into their web browser, the DNS will direct this to right host, which in this case is ucssl-03.
In case your user comes from the internet the request, for example webmail.company.example.org, ends up on the reverse proxy. The reverse proxy is configured to connect the browser of the user to the corresponding server ucssl-03. The configuration of the proxy is explained below in the section implementation. It is not obligatory to use one of the reverse proxy implementations below, anything that can be configured in the way explained above, for example a firewall or a load balancing appliance, might also be suitable for this job.
Furthermore for SSL certificates there has to be a difference between internal and external network. For the internal network you can use the preinstalled UCS Root CA and server certificates, that are enrolled on all of your systems. Usually you have enough control over your internal client computers to deploy the UCS Root CA certificate on all of them, so the certificate chain can be verified by the clients. Your reverse proxy on the other hand should be equipped with a public SSL certificate, that is trusted by every client out-of-the-box, even those you don’t control. You might want to use the Let’s Encrypt App from the Univention App Center for this.
Implementation
We provide example configurations for a reverse proxy server below. Please review and adjust them to your own needs.
Example configuration for HAProxy
In this example, we use a UCS memberserver for the reverse proxy role. To make this work, we disable the default webserver Apache2 on the memberserver, because the reverse proxy HAProxy needs to listen on the default web ports 80 and 443:
# Disable Apache2:
ucr set apache2/autostart=no
systemctl stop apache2.service
# Install HAProxy
ucr set repository/online/unmaintained='yes'
univention-install haproxy
systemctl status haproxy.service
This is an example for /etc/haproxy/haproxy.cfg
. The default configuration provided by the Debian package is extended by blocks that start and end with ###
.
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
### Start manual additions - global section
maxconn 2048
tune.ssl.default-dh-param 2048
### End manual additions - global section
defaults
log global
mode http
### Start manual additions - defaults section
option forwardfor
option http-server-close
stats enable
stats uri /haproxystats
stats realm Haproxy\ Statistics
stats auth <username>:<password>
### End manual additions - defaults section
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
### Start manual additions - proxy section
frontend http-in
bind <IP-of-Reverse-Proxy-Server>:80
reqadd X-Forwarded-Proto:\ http
# Define hosts
acl host_portal hdr(host) -i portal.example.org
acl host_webmail hdr(host) -i webmail.example.org
## figure out which one to use
use_backend portal_servers if host_portal
use_backend webmail_servers if host_webmail
default_backend portal_servers
frontend https-in
bind <IP-of-Reverse-Proxy-Server>:443 ssl crt /etc/haproxy/cert.pem
reqadd X-Forwarded-Proto:\ https
# Define hosts
acl host_portal hdr(host) -i portal.example.org
acl host_webmail hdr(host) -i webmail.example.org
## figure out which one to use
use_backend portal_servers if host_portal
use_backend webmail_servers if host_webmail
default_backend portal_servers
backend portal_servers
redirect scheme https if !{ ssl_fc }
server portal ucsme05.company.example.org:443 ssl verify none check
backend webmail_servers
redirect scheme https if !{ ssl_fc }
server webmail ucssl03.company.example.org:443 ssl verify none check
### End manual additions - proxy section
Please note:
- Replace
<IP-of-Reverse-Proxy-Server>
with the IP address of your reverse proxy server. - The file
/etc/haproxy/cert.pem
needs to contain the certificate and the private key in PEM format. - Replace the entry
stats auth <username>:<password>
with a username and a good password. This is used to access the HAProxy stats page. - Verify your configuration with
haproxy -f /etc/haproxy/haproxy.cfg -c
Example configuration for nginx (as Reverse Proxy)
In this example we use a FreeBSD (v11.1) for the reverse proxy role. The basic installation is followed by Chapter 2. Installing FreeBSD. After the successful installation of FreeBSD, we install ngix with pkg install nginx
.
At this point we have a basic FreeBSD with a nginx. The following settings configure ngix as a reverse proxy. This is an example for /usr/local/etc/nginx/nginx.conf
:
user www;
worker_processes 2;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 60;
# redirect all to HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
charset utf-8;
### SSL log files ###
access_log /var/log/ssl-access.log;
error_log /var/log/ssl-error.log;
### SSL cert files ###
ssl_certificate /etc/ssl/example.org/fullchain.pem;
ssl_certificate_key /etc/ssl/example.org/privkey.pem;
ssl_protocols TLSv1.2; # don't use SSLv3 ref: POODLE, only use TLSv1.2, the latest and greatest
ssl_ciphers 'kEECDH+ECDSA:kEECDH:kEDH:HIGH:!SHA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!DSS:!PSK:!SRP:!kECDH:!CAMELLIA:!RC4';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_dhparam /usr/local/etc/nginx/dhparams.pem;
### Size Limits ###
client_max_body_size 40M;
client_body_timeout 120s;
client_body_temp_path /tmp/;
client_body_in_file_only clean;
client_body_buffer_size 512K;
# example.org
server {
### server port and name ###
listen <IP-of-Reverse-Proxy-Server>:443;
server_name portal.example.org;
ssl on;
keepalive_timeout 60;
### We want full access to SSL via backend ###
location / {
proxy_pass https://ucsme-05.example.org;
### force timeouts if one of backend is died ##
### such died, many backend, very timeouts ##
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
### Set headers ####
proxy_set_header Accept-Encoding "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Front-End-Https on;
### By default we don't want to redirect it ####
proxy_redirect off;
}
}
}
Please note:
- Replace
<IP-of-Reverse-Proxy-Server>
with the external IP address of your reverse proxy server. - The file
/etc/ssl/example.org/fullchain.pem
needs to contain the full chain of the certificate in PEM format. - The file
/etc/ssl/example.org/privkey.pem
should be the private key in PEM format. - Verify your configuration with
nginx -t
and restart your ngix to apply the new configurationservice ngix restart
Related articles
If you are interested in further information about improving your network security and performance with a Reverse Proxy you can also read following related articles about the topic in the Univention Blog:
Improved Network Security and Performance with a Reverse Proxy