How to Set Up a Reverse Proxy with IIS ARR on Windows Server 2022

Internet Information Services (IIS) with Application Request Routing (ARR) and URL Rewrite transforms Windows Server 2022 into a powerful reverse proxy capable of forwarding requests to backend applications, performing SSL offloading, and providing load balancing across server farms. This guide covers the complete ARR setup from module installation through advanced configuration.

Prerequisites and Module Installation

ARR and URL Rewrite are not included with the base IIS installation. Install them before proceeding. IIS itself must be installed via Server Manager or PowerShell:

# Install IIS via PowerShell (run as Administrator)
Install-WindowsFeature -Name Web-Server -IncludeManagementTools

# Verify IIS is running
Get-Service W3SVC

# Check IIS version
Get-ItemProperty HKLM:SOFTWAREMicrosoftInetStp -Name VersionString

Download ARR and URL Rewrite from the Microsoft IIS download center:

  • URL Rewrite 2.1: iis.net/downloads/microsoft/url-rewrite

  • Application Request Routing 3.0: iis.net/downloads/microsoft/application-request-routing

Install both MSIs on the server. The installation order matters: install URL Rewrite first, then ARR. Both installations require an IIS restart. After installation, verify in IIS Manager that “Application Request Routing Cache” and “URL Rewrite” appear in the server-level feature list.

Enabling Proxy in IIS Application Request Routing

ARR ships with proxy functionality disabled. You must enable it explicitly at the server level before any proxy rules will work:

# In IIS Manager:
# 1. Click the server root node (not a site) in the left panel
# 2. Double-click "Application Request Routing Cache" in the center panel
# 3. In the Actions pane (right side), click "Server Proxy Settings"
# 4. Check "Enable proxy"
# 5. Click Apply

# Verify via command line (appcmd)
%SystemRoot%system32inetsrvappcmd.exe list config -section:system.webServer/proxy

You can also enable proxy via the ARR configuration API using PowerShell and the WebAdministration module:

Import-Module WebAdministration

# Enable ARR proxy
Set-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" `
    -Filter "system.webServer/proxy" `
    -Name "enabled" `
    -Value $true

# Verify
Get-WebConfigurationProperty -PSPath "MACHINE/WEBROOT/APPHOST" `
    -Filter "system.webServer/proxy" `
    -Name "enabled"

URL Rewrite Rules for Proxying

URL Rewrite rules define how incoming requests are matched and forwarded. Place these in the web.config of the IIS site acting as the proxy. A basic reverse proxy rule:



  
    
      
        
        
          
          
        
      
    
  

A more selective rule that only proxies requests matching a specific path prefix (e.g., /api/):


  
  
    
    
  

  
  
    
    
  

  
  
    
    
  

Configuring a Backend Server Farm

For load balancing across multiple backend servers, ARR uses a “Server Farm” — a named pool of backend servers with health monitoring and load distribution policies.

Create a server farm in IIS Manager: right-click “Server Farms” under the server node > Create Server Farm. Or configure via applicationHost.config:

# Using appcmd to create a server farm
%SystemRoot%system32inetsrvappcmd.exe set config -section:webFarms /+"[name='MyAppFarm']"

# Add servers to the farm
%SystemRoot%system32inetsrvappcmd.exe set config -section:webFarms /+"[name='MyAppFarm'].servers.[address='192.168.1.101']"
%SystemRoot%system32inetsrvappcmd.exe set config -section:webFarms /+"[name='MyAppFarm'].servers.[address='192.168.1.102']"
%SystemRoot%system32inetsrvappcmd.exe set config -section:webFarms /+"[name='MyAppFarm'].servers.[address='192.168.1.103']"

The server farm configuration in applicationHost.config (under C:WindowsSystem32inetsrvconfig):


  
    
      
    
    
      
    
    
      
    

    
      
      
    
  

When a server farm is defined, ARR automatically creates a URL Rewrite rule that routes matching traffic to the farm. Reference the farm name in the rewrite rule:


  
    
    
  

Health Monitoring

ARR can automatically remove unhealthy backends from the farm and add them back when they recover. Configure health monitoring in the server farm settings:


  
    
  

The health check sends a GET request to the specified URL every 30 seconds. If the response does not contain the string “ok” or returns a non-200 status code, ARR marks that server as unhealthy and stops sending traffic to it. The server is rechecked every 30 seconds and re-added to the farm when it recovers.

SSL Offloading at the Proxy

With SSL offloading, IIS handles HTTPS for clients while communicating with backend servers over plain HTTP. This simplifies certificate management — only the IIS proxy needs a certificate.

Bind an SSL certificate to the IIS site via IIS Manager or PowerShell:

# Import certificate from PFX file
Import-PfxCertificate -FilePath "C:certsexample.com.pfx" `
    -CertStoreLocation "Cert:LocalMachineMy" `
    -Password (ConvertTo-SecureString -String "pfxpassword" -AsPlainText -Force)

# Get the certificate thumbprint
Get-ChildItem Cert:LocalMachineMy | Where-Object { $_.Subject -like "*example.com*" } | Select-Object Thumbprint, Subject

# Bind HTTPS to IIS site (replace thumbprint and site name)
netsh http add sslcert ipport=0.0.0.0:443 certhash= appid='{00000000-0000-0000-0000-000000000000}'

# Or via New-WebBinding in PowerShell:
New-WebBinding -Name "MyProxySite" -Protocol "https" -Port 443 -IPAddress "*"

$cert = Get-ChildItem Cert:LocalMachineMy | Where-Object { $_.Subject -like "*example.com*" }
(Get-WebBinding -Name "MyProxySite" -Protocol "https").AddSslCertificate($cert.Thumbprint, "My")

The backend URL Rewrite rule uses HTTP even though clients connect via HTTPS:



  
  

Preserving X-Forwarded-For Header

By default, backend servers see the proxy’s IP instead of the real client IP. Enable X-Forwarded-For header preservation in the ARR proxy settings:

# In applicationHost.config or web.config at server level:

  

Also add X-Forwarded-Proto so your backend knows whether the original request was HTTP or HTTPS:


  
    
      
      
        
        
      
      
    
  

For server variables to work in URL Rewrite, you must explicitly allow them. Run this in an elevated Command Prompt:

%SystemRoot%system32inetsrvappcmd.exe set config -section:system.webServer/rewrite/allowedServerVariables /+"[name='HTTP_X_FORWARDED_PROTO']"
%SystemRoot%system32inetsrvappcmd.exe set config -section:system.webServer/rewrite/allowedServerVariables /+"[name='HTTP_X_FORWARDED_HOST']"

Proxying to Backend HTTP and HTTPS

If the backend uses HTTPS (self-signed or internal CA), configure ARR to trust the backend certificate:

# Allow ARR to connect to backends with self-signed certificates
# (Not recommended for production unless backend cert is from a trusted internal CA)
%SystemRoot%system32inetsrvappcmd.exe set config -section:system.webServer/proxy /sslFlags:0x8

For production, import the backend’s CA certificate into the server’s Trusted Root Certification Authorities store:

# Import internal CA cert so ARR trusts backend HTTPS
Import-Certificate -FilePath "C:certsinternal-ca.crt" `
    -CertStoreLocation "Cert:LocalMachineRoot"

# Verify it is imported
Get-ChildItem Cert:LocalMachineRoot | Where-Object { $_.Subject -like "*Internal CA*" }

Testing the Reverse Proxy

# Test with curl (must be run from the server itself or an external machine)
curl -v http://proxy.example.com/health
curl -v https://proxy.example.com/api/test

# Check that X-Forwarded-For is being passed through
curl -v http://proxy.example.com/ 2>&1 | grep -i "x-forwarded"

# Test from PowerShell
Invoke-WebRequest -Uri "https://proxy.example.com/health" -UseBasicParsing

# Check IIS logs for proxy activity
# Logs are at C:inetpublogsLogFilesW3SVC1 by default
Get-Content "C:inetpublogsLogFilesW3SVC1u_ex$(Get-Date -Format 'yyMMdd').log" -Tail 20

Troubleshooting ARR

502 Bad Gateway — ARR cannot reach the backend. Verify the backend is running and accessible from the IIS server:

# Test backend reachability from the IIS server
Test-NetConnection -ComputerName 192.168.1.100 -Port 8080

# Check if the backend is listening
netstat -ano | findstr ":8080"

# Check Windows Firewall is not blocking the outbound connection
netsh advfirewall firewall show rule name=all | findstr "8080"

Error: The configuration section ‘system.webServer/rewrite’ cannot be read because it is missing a section declaration — URL Rewrite module is not installed. Reinstall it.

ARR not forwarding requests / proxy rules not matching — Confirm proxy is enabled at server level and check rule order in URL Rewrite. Use IIS’s Failed Request Tracing to get detailed diagnostic output:

# Enable Failed Request Tracing on the site
Enable-WebRequestTracing -Name "MyProxySite"

# Configure tracing for 502 errors
Add-WebConfigurationProperty -PSPath "IIS:SitesMyProxySite" `
    -Filter "system.webServer/tracing/traceFailedRequests" `
    -Name "." `
    -Value @{
        path="*"
        customActionEnabled="false"
    }

# Trace files appear at C:inetpublogsFailedReqLogFilesW3SVC1

IIS ARR provides a robust, enterprise-grade reverse proxy solution for Windows Server 2022. With the server proxy setting enabled, URL Rewrite rules for routing, server farms for load balancing, and proper header forwarding configured, IIS ARR is capable of handling production traffic for applications built on any backend technology stack.