Configuring nginx reverse proxy for Exchange 2010
2016-NOV-16

This will be a quick post that I hope other might find usefully when deploying nginx as a reverse proxy for Exchange 2010 SP3. With my particular setup, we had two reverse proxy servers; one on the DMZ, and the other was on the LAN and firewall rules that only allow them to communicate with each other through standard HTTP/S ports.

Here's quick dirty diagram of the final setup:

Internet -> Firewall -> DMZ -> Reverse Proxy 1 -> Firewall -> Reverse Proxy 2 -> Exchange

nginx conf

Reverse proxy 1

server {
        listen 443 ssl;
        server_name outlookserver.com;
        ssl_certificate /path/to/outlookserver.crt;
        ssl_certificate_key /path/to/outlookserver.key;
        ssl_prefer_server_ciphers On;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
        ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
        ssl_dhparam /path/to/dhparam.pem;
        ssl_session_cache shared:SSL:10m;
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options ALLOW;

        location / {
                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;

                # Fix the "It appears that your reverse proxy set up is broken" error.
                proxy_pass https://reverseproxy2;
                proxy_read_timeout 360;

                error_log /var/log/nginx/owa-ssl-error.log;
                access_log /var/log/nginx/owa-ssl-access.log;
    }
}

Reverse proxy 1

server {
        server_name outlookserver.com;
        listen 443;

        ssl on;
        ssl_certificate /path/to/outlookserver.crt;
        ssl_certificate_key /path/to/outlookserver.key;
        ssl_session_timeout 5m;
        location / {
                return 301 https://outlookserver.com/owa;
        }

        proxy_http_version 1.1;
        proxy_read_timeout 360;
        proxy_pass_header Date;
        proxy_pass_header Server;
        proxy_pass_header Authorization;
        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_pass_request_headers on;
        more_set_input_headers 'Authorization: $http_authorization';
        proxy_set_header Accept-Encoding "";
        more_set_headers -s 401 'WWW-Authenticate: Basic realm="outlookserver.com"';
        # proxy_request_buffering off;
        proxy_buffering off;
        proxy_set_header Connection "Keep-Alive";

        location ~* ^/owa { proxy_pass https://exchangeserver; }
        location ~* ^/Microsoft-Server-ActiveSync { proxy_pass https://exchangeserver; }
        location ~* ^/ecp { proxy_pass https://exchangeserver; }
        location ~* ^/rpc { proxy_pass https://exchangeserver; }

        error_log /var/log/nginx/owa-ssl-error.log;
        access_log /var/log/nginx/owa-ssl-access.log;
}