Cool Solution - Reverse Proxy for UCS Portal and Services

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.

Reverse_proxy

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 configuration service 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

Cool Solution – Squid as Reverse SSL Proxy

1 Like

This topic was automatically closed after 24 hours. New replies are no longer allowed.

Mastodon