IIS with ARR and URL Rewrite
Background
Section titled “Background”This configuration makes IIS on Windows Server 2025 act as a secure reverse proxy in front of several internal HTTPS services running on different localhost ports.
It solves these problems:
- It exposes multiple backend applications through one public IIS site on standard HTTPS port
443, instead of requiring users to access8443,8450,8446or8445directly. - It routes requests by path, so
/access,/saml,/oidc,/forms,/pwdresetand/portaleach go to the correct internal service. Requests to/will be routed to/portal. - It preserves the original public host header, which many applications need for URL generation, redirects, SAML, cookies, and validation logic.
- It adds
X-Forwarded-Proto: httpsandX-Forwarded-Port: 443, so backend apps know the original client connection was HTTPS on the public endpoint, even though IIS is proxying the request internally. - It allows IIS/ARR to connect to backend HTTPS services even if those internal certificates are self-signed, expired, or have hostname mismatches.
In practical terms, this is useful when you want users to access one external URL such as https://yourserver/access while the real applications stay bound internally to https://localhost:8443, https://localhost:8450, and https://localhost:8445.
The main issue it solves is publishing internal web apps securely behind a single IIS entry point without changing the applications to listen directly on the public interface.
Pre-reqs
Section titled “Pre-reqs”Windows 2025 with Admin privileges
Installation and Configuration
Section titled “Installation and Configuration”Install the required modules
Section titled “Install the required modules”- IIS
- URL Rewrite
- Application Request Routing (ARR)
Official downloads:
Enable reverse proxy in ARR
Section titled “Enable reverse proxy in ARR”In IIS Manager:
- Select the server
- Open Application Request Routing Cache
- Click Server Proxy Settings
- Check Enable proxy
Preserve the original Host header
Section titled “Preserve the original Host header”Run as Administrator:
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/proxy /preserveHostHeader:"True" /commit:apphostAdd X-Forwarded-Proto and X-Forwarded-Port
Section titled “Add X-Forwarded-Proto and X-Forwarded-Port”In IIS, on the site used (such as Default Web Site):
- Open
URL Rewrite - Click
View Server Variables... - Add:
HTTP_X_FORWARDED_PROTOHTTP_X_FORWARDED_PORT
- Create
web.configfor the site used (C:\inetpub\wwwrootforDefault Web Site) with this content:
<configuration> <system.webServer> <caching enabled="false" enableKernelCache="false" /> <urlCompression doStaticCompression="false" doDynamicCompression="false" />
<rewrite> <rules> <rule name="Proxy access" stopProcessing="true"> <match url="^access(/.*)?$" /> <serverVariables> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <set name="HTTP_X_FORWARDED_PORT" value="443" /> </serverVariables> <action type="Rewrite" url="https://127.0.0.1:8443/{R:0}" /> </rule>
<rule name="Proxy saml" stopProcessing="true"> <match url="^saml(/.*)?$" /> <serverVariables> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <set name="HTTP_X_FORWARDED_PORT" value="443" /> </serverVariables> <action type="Rewrite" url="https://127.0.0.1:8443/{R:0}" /> </rule>
<rule name="Proxy oidc" stopProcessing="true"> <match url="^oidc(/.*)?$" /> <serverVariables> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <set name="HTTP_X_FORWARDED_PORT" value="443" /> </serverVariables> <action type="Rewrite" url="https://127.0.0.1:8443/{R:0}" /> </rule>
<rule name="Proxy forms" stopProcessing="true"> <match url="^forms(/.*)?$" /> <serverVariables> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <set name="HTTP_X_FORWARDED_PORT" value="443" /> </serverVariables> <action type="Rewrite" url="https://127.0.0.1:8450/{R:0}" /> </rule>
<rule name="Proxy portal" stopProcessing="true"> <match url="^portal(/.*)?$" /> <serverVariables> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <set name="HTTP_X_FORWARDED_PORT" value="443" /> </serverVariables> <action type="Rewrite" url="https://127.0.0.1:8445/{R:0}" /> </rule>
<rule name="Proxy pwdreset" stopProcessing="true"> <match url="^pwdreset(/.*)?$" /> <serverVariables> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <set name="HTTP_X_FORWARDED_PORT" value="443" /> </serverVariables> <action type="Rewrite" url="https://127.0.0.1:8446/{R:0}" /> </rule>
<rule name="Proxy root" stopProcessing="true"> <match url=".*" /> <serverVariables> <set name="HTTP_X_FORWARDED_PROTO" value="https" /> <set name="HTTP_X_FORWARDED_PORT" value="443" /> </serverVariables> <action type="Rewrite" url="https://127.0.0.1:8445/{R:0}" /> </rule> </rules> </rewrite> </system.webServer></configuration>Disable reverseRewriteHostInResponseHeaders
Section titled “Disable reverseRewriteHostInResponseHeaders”In IIS Manager:
- Go to server node
- Open Configuration Editor
- Navigate to:
system.webServer/proxy - Set
reverseRewriteHostInResponseHeaders = False
OPTIONAL - Disable SSL validation against the backend
Section titled “OPTIONAL - Disable SSL validation against the backend”If you want IIS to ignore CN/name mismatch, expired certificates, and unknown CA errors, run this as Administrator:
reg add "HKLM\SOFTWARE\Microsoft\IIS Extensions\Application Request Routing\Parameters" /v SecureConnectionIgnoreFlags /t REG_DWORD /d 13056 /fRestart IIS
Section titled “Restart IIS”Issue iisreset as administrator in order to restart the IIS.
iisresetVerify configuration
Section titled “Verify configuration”Go to one of the url patterns previously configured and verify the service is reachable
Example: https://servername.company.org/portal