Compartir el puerto 443: Apache y Exchange

Cuando se complica la infraestructura de servidores puede ocurrir que diferentes servicios necesiten compartir el mismo puerto. Es el caso de Exchange y un servidor web seguro (HTTPS).

Actualmente dispongo de un servidor web, en el puerto 80 de la ip pública y de un servidor de Exchange en el puerto 443. El problema viene cuando en el servidor web queremos servir webs seguras (HTTPS) con certificados SSL. Esto se hace también por el puerto 443, por lo que entra en conflicto con Exchange. Soluciones:

  1. Contratar una segunda IP pública, y ejecutar el servidor web en una IP y el servidor Exchange en la otra
  2. Cambiar el puerto de Exchange al 444, por ejemplo. Microsoft no facilita este cambio, pero si buscas en internet verás que se puede hacer a través del registro de Windows. La desventaja de esta solución es que tendrás que reconfigurar todos los dispositivos (PCs, móviles…) para que ahora apunten al nuevo puerto.
  3. Configuar un proxy inverso que escuche en el puerto 443, que se encargue de atender las solicitudes y derivarlas a quién correspondan, derivarla al servidor web o al servidor de Exchange según corresponda. Esta es la solución que yo he elegido.

Para montar el Proxy reverse he elegido Debian 8 Jessie con Apache haciendo de Reverse Proxy. Configurar el proxy reverse para que por ejemplo atienda diferentes solicitudes HTTP y HTTPS y las derive a diferentes servidores web de la LAN es relativamente sencillo y hay un montón de tutoriales en la red. Configurar un Reverse Proxy para que funcione con Exchange es un infierno. Exchange utiliza RPC sobre HTTP, pero como suele ocurrir con Microsoft, una versión «muy suya», no el estándar. Esa es básicamente la clave para hacerlo funcionar, entender que el RPC de Exchange no es el normal.

Los pasos que yo he seguido son:

1. Crear certificado Let’s Encrypt con certbot en la máquina Apache que ejecuta el Reverse Proxy

2. Exportar el certificado a pfx con openssl para poder usarlo en Exchange:

openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem

Como veis el mismo certificado tiene que estar instalado en la máquina que hace de Proxy Reverse y en la de Exchange

3. Instalar el certificado pfx en Exchange (yo lo hago a través de IIS)

4. Habilitar los módulos necesarios en Apache para poder hacer Reverse Proxy

a2enmod ssl
a2enmod proxy
a2enmod proxy_balancer
a2enmod proxy_http

Y el super importante para que funcione Exchange:

apt-get install libapache2-mod-proxy-msrpc
a2enmod proxy_msrpc

Ojo porque dependiendo de la distrubición de Linux que uses puede ser que este módulo tengas que configurarlo a mano. En mi caso Debian lo incluye.

5. Crear un Virtual Host en Apache para que haga Reverse Proxy, enlazando el certificado creado y redirigiendo las peticiones a la máquina que ejecute Exchange:

<VirtualHost *:80>
ServerName mail.midominiopublico.es
ServerAlias autodiscover.midominiopublico.es
ServerAdmin tomascrespo@midominiopublico.es

ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined

Header always set X-Frame-Options SAMEORIGIN

Header set Server Apache

Header unset X-AspNet-Version
Header unset X-OWA-Version
Header unset X-Powered-By

# Nachfolgende zeile löst den "Expectation Failed Apache 417" Fehler beim AutoDiscover etc.
RequestHeader unset Expect early

# Nachfolgende Zeilen sind um die Authentifizierung zu ermöglichen - NTLM-Funktioniert durch den Proxy nicht, deshalb Basis-Authentifizierung erzwingen
SetEnvIf User-Agent ".*MSIE.*" value BrowserMSIE
Header unset WWW-Authenticate
Header add WWW-Authenticate "Basic realm=midominiopublico.es"

ProxyRequests Off

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/owa(.*) https://midominiopublico.es/owa$1 [R,L]
RewriteRule ^/ecp(.*) https://midominiopublico.es/ecp$1 [R,L]
RewriteRule ^/Microsoft-Server-ActiveSync(.*) https://midominiopublico.es/Microsoft-Server-ActiveSync$1 [R,L]

DocumentRoot /var/www/midominiopublico.es/web

<Directory />
 Order deny,allow
 Deny from all
</Directory>

<Directory /var/www/midominiopublico.es/web>
 DirectoryIndex index.php index.html
 Options -Indexes +FollowSymLinks
 Order allow,deny
 Allow from all
</Directory>

<Proxy *>
 Order deny,allow
 Allow from all
</Proxy>

</VirtualHost>


<VirtualHost *:443>

ServerName midominiopublico.es
ServerAlias autodiscover.midominiopublico.es


ServerAdmin tomascrespo@midominiopublico.es

ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined

Header always set X-Frame-Options SAMEORIGIN

Header set Server Apache

Header unset X-AspNet-Version
Header unset X-OWA-Version
Header unset X-Powered-By

RequestHeader unset Expect early

#SetEnvIf User-Agent ".*MSIE.*" value BrowserMSIE
Header unset WWW-Authenticate
Header add WWW-Authenticate "Basic realm=midominiopublico.es"

ProxyRequests Off
ProxyPreserveHost On


SSLProxyEngine On
# Problemen mit Kommunikation zwischen Apache-Proxy und Exchange-Server aus dem Wege gehen
# Alle SSL Prüfungen werden damit ausgeschaltet
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off

# owa
ProxyPass /owa https://maquinaexchange.local/owa
ProxyPassReverse /owa https://maquinaexchange.local/owa
ProxyPass /OWA https://maquinaexchange.local/OWA
ProxyPassReverse /OWA https://maquinaexchange.local/OWA
ProxyPass /Owa https://maquinaexchange.local/Owa
ProxyPassReverse /Owa https://maquinaexchange.local/Owa

# Einstellungen um per OWA das Kennwort zu aendern
ProxyPass /iisadmpwd https://maquinaexchange.local/iisadmpwd
ProxyPassReverse /iisadmpwd https://maquinaexchange.local/iisadmpwd

# ecp
ProxyPass /ecp https://maquinaexchange.local/ecp
ProxyPassReverse /ecp https://maquinaexchange.local/ecp
ProxyPass /ECP https://maquinaexchange.local/ECP
ProxyPassReverse /ECP https://maquinaexchange.local/ECP
ProxyPass /Ecp https://maquinaexchange.local/Ecp
ProxyPassReverse /Ecp https://maquinaexchange.local/Ecp

# ews -> Exchange Web Services
ProxyPass /ews https://maquinaexchange.local/ews
ProxyPassReverse /ews https://maquinaexchange.local/ews
ProxyPass /EWS https://maquinaexchange.local/EWS
ProxyPassReverse /EWS https://maquinaexchange.local/EWS
ProxyPass /Ews https://maquinaexchange.local/Ews
ProxyPassReverse /Ews https://maquinaexchange.local/Ews
ProxyPass /exchange https://maquinaexchange.local/exchange
ProxyPassReverse /exchange https://maquinaexchange.local/exchange
ProxyPass /Exchange https://maquinaexchange.local/Exchange
ProxyPassReverse /Exchange https://maquinaexchange.local/Exchange
ProxyPass /exchweb https://maquinaexchange.local/exchweb
ProxyPassReverse /exchweb https://maquinaexchange.local/exchweb
ProxyPass /public https://maquinaexchange.local/public
ProxyPassReverse /public https://maquinaexchange.local/public

# oab (Offline Address Book)
ProxyPass /oab https://maquinaexchange.local/oab
ProxyPassReverse /oab https://maquinaexchange.local/oab
ProxyPass /OAB https://maquinaexchange.local/OAB
ProxyPassReverse /OAB https://maquinaexchange.local/OAB

# Microsoft-Server-ActiveSync
ProxyPass /Microsoft-Server-ActiveSync https://maquinaexchange.local/Microsoft-Server-ActiveSync connectiontimeout=600
ProxyPassReverse /Microsoft-Server-ActiveSync https://maquinaexchange.local/Microsoft-Server-ActiveSync

<Directory /Microsoft-Server-ActiveSync>
# Problem mit dem Versenden von Dateianhängen > 128KByte per ActiceSync umgehen (neuer Wert 30MByte)
SSLRenegBufferSize 31457280
</Directory>

# RPC over http(s) / Outlook Anywhere
OutlookAnywherePassthrough On
ProxyPass /rpc https://maquinaexchange.local/rpc
ProxyPassReverse /rpc https://maquinaexchange.local/rpc

# AutoDiscover -> Autodiscover for non-AD integrated Clients (Mac, eg.)
ProxyPass /autodiscover https://maquinaexchange.local/autodiscover
ProxyPassReverse /autodiscover https://maquinaexchange.local/autodiscover
ProxyPass /Autodiscover https://maquinaexchange.local/Autodiscover
ProxyPassReverse /Autodiscover https://maquinaexchange.local/Autodiscover
ProxyPass /AutoDiscover https://maquinaexchange.local/AutoDiscover
ProxyPassReverse /AutoDiscover https://maquinaexchange.local/AutoDiscover

# Zeichensatz spezifieren fuer Umlaute
AddDefaultCharset ISO-8859-1

DocumentRoot /var/www/midominiopublico.es/web

<Directory />
 Order deny,allow
 Deny from all
</Directory>

<Directory /var/www>
 DirectoryIndex index.php index.html
 Options -Indexes +FollowSymLinks
 Order allow,deny
 Allow from all
</Directory>

<Proxy *>
 SetEnv proxy-nokeepalive 1
 SetEnv force-proxy-request-1.0 1
 Order deny,allow
 Allow from all
</Proxy>

SSLEngine on

Include /etc/letsencrypt/options-ssl-apache.conf
 SSLCertificateFile /etc/letsencrypt/live/midominiopublico.es/fullchain.pem
 SSLCertificateKeyFile /etc/letsencrypt/live/midominiopublico.es/privkey.pem


 BrowserMatch "MSIE [2-6]" \
 nokeepalive ssl-unclean-shutdown \
 downgrade-1.0 force-response-1.0
 # MSIE 7 and newer should be able to use keepalive
 BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

# old Server config
 #BrowserMatch ".*MSIE.*" \
 # nokeepalive ssl-unclean-shutdown \
 # downgrade-1.0 force-response-1.0
</VirtualHost>

Como veis también hay un VirtualHost para el puerto 80, que lo único que hace es redirigir las peticiones HTTP para que se conviertan en HTTPS, al puerto 443 que es por donde deben de ir.

6. Probar y añadir sal al gusto.

 

Notas:

Los PC con Outlook fuera de la LAN usan Outlook Anywhere para conectarse, o lo que es lo mismo RPC sobre HTTP

Los Mac con Outlook fuera de la LAN usan Exchange Web Services (EWS) para conectarse.

Tanto Outlook AnyWhere como Exchange Web Services (EWS) y Offline Address Book (OAB) tienen que tener habilitada la Autenticación Básica, pues Apache Reverse Proxy no es capaz de manejar la Autenticación NTLM.

La Autenticación Básica de EWS y OAB se habilita en IIS, en el directorio virtual /EWS, en el apartado Autenticación

A mi actualmente me está funcionando todo desde fuera de la oficina:

  • Outlook Web Access (OWA)
  • iPhones, móviles Android y móviles Windows Phone con ActiveSync
  • Portátiles de los jefes MacBook Air que usan EWS (con Outlook for Mac)
  • Portátiles Windows  con Outlook, que usan Outlook Anywhere

Referencias: Apache2 als Reverse Proxy für Exchange 2010 2013 inklusive Outlook Anywhere RPC over http

Convert letsencrypt .pem certificate to .pfx

I use Let’s Encrypt certificates in my Windows and Linux serves. This week I had to use the same certificate in two machines, one IIS server (Windows) and one Apache2 server (Linux Debian).

I create the certificate in Linux using certbot utility, ant it gave me four files:

  • cert.pem
  • chain.pem
  • fullchain.pem
  • privkey.pem

I installed to Apache with no problems.

But then I tried to install the certificate to IIS 6.1 and I realized that Windows did not want that type of file. With some research on the Internet I found a solution, using the command openssl (in Linux):

openssl pkcs12 -export -out certificateforwindows.pfx -inkey privkey.pem -in cert.pem -certfile fullchain.pem

I wish this helps someone