Layout for PMG, Exchange and Active Sync

larsen

Well-Known Member
Feb 28, 2020
160
19
58
Hello,

we are currently running a local Exchange installation. Mail is fetched via Popcon (so there is an annoying delay when receiving mails). Active Sync is possible through Port Forwarding on our firewall to the Exchange host (access is restricted to our VPN and some IP ranges of carriers for mobile access).

Of course, not the setup you would want to use today. I plan on using PMG and making it possible to instantly receive mails.

I don't have much experience in this field. What would be the best way to configure things to have mails delivered directly to PMG and still be able to use Active Sync on Exchange?

Code:
Firewall
 |
 |---  DMZ (Orange)
 |     |
 |     |----- PMG
 |     |----- Exchange
 |
 |- Switch (Green)
        |----- local network

- PMG would use the external ports 25, etc.
- PMG would forward mails to Exchange
- Exchange would use the external ports for Active Sync
- Outlook-clients would connect to Exchange from Green into the DMZ
- There would be no traffic from DMZ into Green

Is this feasible?
 
Last edited:
After some more reading I learnt that it would be a bad idea to put an Exchange server into the DMZ (as it needs a connection to the DC (amongst others)).

So, will have to find out how to proxy Active Sync. Anyone using this?
 
I got this working some time ago. As I stumbled upon this thread again, I thought a little how-to might help someone someday. Probably not complete (and I didn't translate some comments). Using a separate VM for PMG, HAProxy, and Exchange.

1)
Firewall 25 -> PMG
Firewall 26 -> PMG
Firewall 443 -> HAProxy (Let's Encrypt, Exchange-Features (Autodiscover, Active Sync, Outlook Anywhere, OWA))


2)
/etc/haproxy/haproxy.cfg

Code:
global
    # HTTP-Requests loggen, aber später über rsyslog nur die bzgl. tarpit in haproxy-tarpit.log schreiben.
    # Die restlichen Log-Einträge werden weiterhin normal in haproxy.log geschrieben.
    log /dev/log    local0 info

    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

    # Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    # generated 2021-12-22, Mozilla Guideline v5.6, HAProxy 2.2.9, OpenSSL 1.1.1k, intermediate configuration
    # https://ssl-config.mozilla.org/#server=haproxy&version=2.2.9&config=intermediate&openssl=1.1.1k&guideline=5.6
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305HE-RSA-AES128-GCM-SHA256HE-RSA-AES256-GCM-SHA384
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets


defaults
    log global
    mode    http
    option  httplog
    option  dontlognull
    timeout http-request 5s
    timeout connect 5s
    # Connection Resets durch höhere Timeouts vermeiden, siehe
    # https://discourse.haproxy.org/t/high-number-of-connection-resets-during-transfers-exchange-2013/1158/6
    # Timeouts Client/Server waren vorher auf 50 Sekunden eingestellt. Probleme sind dabei zumindest nicht aufgefallen.
    timeout client 1000s
    timeout server 1000s


listen stats
    bind *:9000
    mode http
    stats enable
    stats uri /
    stats auth admin:b6a28614642527def6629179551d16f3


frontend fe

    # SSL: Angabe eines Verzeichnisses lädt alle darin vorhandenen Zertifikate.
    # HAProxy verwendet je nach angefragter Domain das passende Zertifikat.
    bind :80
    bind :443 ssl crt /etc/haproxy/ssl/


    # Let's Encrypt für Proxmox Mail Gateway durchreichen.
    # Wird dort verarbeitet.
    acl domain_is_mailgateway hdr_dom(host) -i mail.example.com


    # Let's Encrypt für alles andere
    acl is_certbot path_beg /.well-known/acme-challenge/

    # Von http auf https umleiten
    # 301 für "Moved Permanently"
    http-request redirect scheme https code 301 unless { ssl_fc } or is_certbot or domain_is_mailgateway


    # Je nach Bedingung oder Domain auf entsprechenden Zielserver weiterleiten
    use_backend ProxmoxMailGateway if domain_is_mailgateway
    use_backend certbot if is_certbot


    # Konfiguration für Exchange
    # Verwendet "exchange.example.com" und "autodiscover.example.com"

    no option httpclose

    acl eas path_beg -i /Microsoft-Server-ActiveSync
    acl autodiscover path_beg -i /autodiscover
    acl ews path_beg -i /ews
    acl mapi url_beg /mapi
    acl oab path_beg -i /oab
    acl owa path_beg -i /owa
    acl rpc path_beg -i /rpc/rpcproxy.dll
    acl ecp path_beg -i /ecp
    acl owa path_beg -i /favicon.ico

    use_backend ExchangeActiveSync if eas
    use_backend ExchangeAutoDiscover if autodiscover
    use_backend ExchangeECP if ecp
    use_backend ExchangeEWS if ews
    use_backend ExchangeMAPI if mapi
    use_backend ExchangeOAB if oab
    use_backend ExchangeOWA if owa
    use_backend OutlookAnywhere if rpc


    # Der Rest (Angriffe, Scans, etc.) landet im Tarpit.
    default_backend tarpit


backend certbot
    server certbot 127.0.0.1:9080

backend ProxmoxMailGateway
    server srv-pmg 192.168.0.5



# Exchange-Backends
# Quelle:
# https://www.bayreuth.tk/home/linux-und-bsd/haproxy-als-loadbalancer-und-ssl-offloader-fuer-microsoft-exchange-cas-server.html
# Da wir nur einen Exchange-Server verwenden, alles mit Sticky-Table entfernt.

backend ExchangeActiveSync
    option httpchk HEAD /Microsoft-Server-ActiveSync
    http-check expect status 401
    server srv-exchange 192.168.0.3:443 ssl verify none

backend ExchangeOWA
    option http-server-close
    option redispatch
    option httpchk GET /owa
    http-check expect status 301
    server srv-exchange 192.168.0.3:443 ssl verify none

# Anfragen auf ECP werden aus Sicherheitsgründen nicht weitergeleitet, da hierüber die Administration erfolgt.
# Blockt auch Sachen wie die Erkennung von Abwesenheiten, aber das ist für uns unwichtig.
backend ExchangeECP
    http-request deny if TRUE

backend ExchangeEWS
    option httpchk GET /ews
    http-check expect status 401
    server srv-exchange 192.168.0.3:443 ssl verify none

backend ExchangeAutoDiscover
    server srv-exchange 192.168.0.3:443 ssl verify none

backend ExchangeOAB
    server srv-exchange 192.168.0.3:443 ssl verify none

backend ExchangeMAPI
    server srv-exchange 192.168.0.3:443 ssl verify none

backend OutlookAnywhere
    option redispatch
    server srv-exchange 192.168.0.3:443 ssl verify none

# Tarpit: Angreifer ausbremsen
# https://www.haproxy.com/de/blog/use-haproxy-response-policies-to-stop-threats/
# Würde sonst auf "fe/<NOSRV>" landen und 503-Fehler bekommen, aber nicht verzögert werden.
# Bietet keinen Schutz, aber bindet auf Angreifer-Seite Ressourcen (auch bei uns etwas).
backend tarpit
    timeout tarpit 10s
    http-request tarpit deny_status 403 if TRUE


3)
/etc/haproxy/prepareLetsEncryptCertificates.sh

Code:
#!/bin/bash
# Loop through all Let's Encrypt certificates
for CERTIFICATE in $(find /etc/letsencrypt/live/* -type d); do
    CERTIFICATE=$(basename $CERTIFICATE)
    # Combine certificate and private key into single file
    cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /etc/haproxy/ssl/$CERTIFICATE.pem
done
# Reload
/usr/sbin/haproxy -c -f /etc/haproxy/haproxy.cfg && /usr/sbin/service haproxy reload


4)
certbot certonly --standalone -m lets@example.com --preferred-challenges http --http-01-address 127.0.0.1 --http-01-port 9080 --post-hook "/etc/haproxy/prepareLetsEncryptCertificates.sh" -d ${DOMAIN}