IIS’te Reverse Proxy Yapılandırması: ARR Modülü ile Adım Adım Kurulum
Yıllar önce bir müşterimizin sunucusunda klasik bir sorunla karşılaştım: birden fazla web uygulaması, birden fazla port, ve kullanıcıların sürekli “neden 8080 yazmak zorundayız?” sorusu. O gün ARR modülünü ciddiye almaya başladım. IIS üzerinde reverse proxy kurulumu, başta karmaşık görünse de, doğru adımları takip ettiğinizde son derece temiz ve yönetilebilir bir yapı ortaya çıkıyor.
ARR Nedir ve Neden Kullanıyoruz?
Application Request Routing (ARR), Microsoft’un IIS için geliştirdiği bir modüldür. Temel olarak gelen HTTP/HTTPS isteklerini arka taraftaki sunuculara veya uygulamalara yönlendirmenizi sağlar. Nginx’teki proxy_pass direktifinin IIS karşılığı diyebiliriz, ancak GUI tabanlı yönetimi ve Windows ekosistemiyle olan entegrasyonu bazı senaryolarda onu daha pratik kılar.
ARR’ın gerçek hayatta kullanıldığı tipik senaryolar şunlardır:
- Node.js veya Python uygulamalarını IIS arkasına almak: Uygulama 3000 portunda çalışıyor, siz 80/443 üzerinden servis etmek istiyorsunuz
- Birden fazla uygulamayı tek IP’den sunmak:
app1.sirket.comveapp2.sirket.comaynı sunucudan farklı backend’lere gidiyor - SSL sonlandırma: Sertifika yönetimini tek noktada toplamak
- Load balancing: Birden fazla backend sunucu arasında yük dağıtımı
- Legacy uygulamaları modern URL yapısına uyarlamak
Ön Gereksinimler
Başlamadan önce şunların hazır olması gerekiyor:
- Windows Server 2016/2019/2022 (veya Windows 10/11 üzerinde IIS etkin)
- IIS 7.0 ve üzeri (tercihen 10.x)
- İnternet bağlantısı veya offline kurulum paketleri
- Yönetici hakları
IIS’in kurulu olup olmadığını kontrol etmek için PowerShell’den:
Get-WindowsFeature -Name Web-Server | Select-Object Name, InstallState
Eğer kurulu değilse:
Install-WindowsFeature -Name Web-Server -IncludeManagementTools -IncludeAllSubFeature
ARR ve URL Rewrite Modüllerinin Kurulumu
ARR tek başına yeterli değil. URL Rewrite modülü de şart. İkisi birlikte çalışarak yönlendirme mantığını oluşturuyor. ARR proxy mekanizmasını sağlarken, URL Rewrite kuralların nasıl eşleşeceğini tanımlıyor.
Web Platform Installer (WebPI) ile kurulum:
WebPI hala çalışıyor ancak Microsoft artık aktif olarak geliştirmediği için direkt indirme yolunu tercih ediyorum. Microsoft’un resmi sayfasından ARR 3.0 paketini indirip kurabilirsiniz. URL Rewrite için de aynı şekilde.
Kurulum sonrası IIS Manager’ı yeniden başlatın. Sol panelde sunucu düzeyinde “Application Request Routing Cache” ve site/sunucu düzeyinde “URL Rewrite” seçeneklerinin geldiğini göreceksiniz.
PowerShell ile kurulum durumunu doğrulamak için:
Get-WebConfiguration -Filter "system.webServer/proxy" | Select-Object enabled
Bu komut bir şey döndürmüyorsa veya hata veriyorsa ARR düzgün kurulmamış demektir.
ARR Proxy’yi Aktif Etmek
Modül kuruldu ama proxy özelliği varsayılan olarak kapalı geliyor. Bunu açmak için IIS Manager’da sunucu adına tıklayın (site değil, sunucunun kendisi), “Application Request Routing Cache” ikonuna çift tıklayın, sağ taraftaki “Server Proxy Settings” linkine tıklayın ve “Enable proxy” kutucuğunu işaretleyin.
Aynı işlemi PowerShell ile yapabilirsiniz:
Set-WebConfiguration -Filter "system.webServer/proxy" -Value @{enabled="True"} -PSPath "IIS:"
Bu adımı atlayanların en sık yaptığı hata: her şeyi doğru yapıyorlar ama proxy çalışmıyor. Nedeni genellikle bu adımın atlanmış olması.
İlk Reverse Proxy Kuralını Yazmak
Şimdi asıl işe geliyoruz. Diyelim ki şu senaryomuz var: Sunucumuzda localhost:3000 portunda çalışan bir Node.js uygulaması var ve bunu myapp.sirket.com üzerinden dışarıya açmak istiyoruz.
Önce IIS’te myapp.sirket.com için yeni bir site oluşturun veya mevcut bir sitenin bindings’ine bu host header’ı ekleyin. Ardından bu sitenin URL Rewrite bölümüne gelin.
web.config dosyasına manuel olarak kural eklemek her zaman daha hızlı ve kontrol edilebilir. Site kök dizinindeki web.config dosyasını düzenleyin:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxy_NodeApp" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:3000/{R:1}" />
</rule>
</rules>
</rewrite>
<proxy>
<preserveHostHeader>true</preserveHostHeader>
</proxy>
</system.webServer>
</configuration>
{R:1} ifadesi URL’nin geri kalan kısmını temsil ediyor. (.*) ile yakaladığımız grubun birinci eşleşmesi. Bu sayede myapp.sirket.com/api/users isteği localhost:3000/api/users adresine iletiliyor.
Path Bazlı Yönlendirme
Daha gerçekçi bir senaryo: Tek bir domainle birden fazla uygulamaya yönlendirme. sirket.com/api/ istekleri backend API’ye, sirket.com/admin/ istekleri ayrı bir admin paneline, geri kalan her şey ise ana web sitesine gitsin.
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="API_Backend" stopProcessing="true">
<match url="^api/(.*)" />
<action type="Rewrite" url="http://localhost:5000/api/{R:1}" />
</rule>
<rule name="Admin_Panel" stopProcessing="true">
<match url="^admin/(.*)" />
<action type="Rewrite" url="http://192.168.1.50/admin/{R:1}" />
</rule>
<rule name="Main_Site" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:8080/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Burada kural sırası kritik. IIS kuralları yukarıdan aşağıya işler. stopProcessing="true" bir kural eşleştiğinde diğerlerini denemeyi bırakır. Bunu koymazsanız, eşleşen bir kuraldan sonra bile diğer kurallar deneniyor ve beklenmedik sonuçlar çıkabiliyor.
Header Yönetimi ve Gerçek IP Sorunu
Reverse proxy kullanımında en çok gözden kaçan konu: backend uygulamanız client’ın gerçek IP adresini göremez. ARR sunucusunun IP’sini görür. Bu, loglama ve güvenlik açısından sorun yaratır.
ARR, X-Forwarded-For header’ını otomatik ekleyebilir. Bunu etkinleştirmek için:
Set-WebConfigurationProperty -Filter "system.webServer/proxy" `
-Name "includePortInXForwardedFor" `
-Value $true `
-PSPath "IIS:"
Web.config tarafında ise bazı header’ları temizlemek veya eklemek için outboundRules kullanabilirsiniz:
<rewrite>
<outboundRules>
<rule name="Remove_Server_Header">
<match serverVariable="RESPONSE_Server" pattern=".+" />
<action type="Rewrite" value="MyCustomServer" />
</rule>
</outboundRules>
</rewrite>
Bu örnek Server response header’ını gizliyor. Güvenlik taraması yapan ekipler genellikle sunucu tipini açık eden header’ları sorun olarak işaretler. ARR varsayılan olarak backend sunucunun header bilgilerini geçirdiği için bunu özellikle ele almak gerekiyor.
Backend’e gönderilen request header’larını manipüle etmek için serverVariables kullanabilirsiniz:
<rule name="API_Backend_With_Headers" stopProcessing="true">
<match url="^api/(.*)" />
<serverVariables>
<set name="HTTP_X_REAL_IP" value="{REMOTE_ADDR}" />
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
</serverVariables>
<action type="Rewrite" url="http://localhost:5000/api/{R:1}" />
</rule>
serverVariables bloğunu kullanabilmek için önce IIS’te bu değişkenlere izin vermeniz gerekiyor. Bunu yapmadan 500 Internal Server Error alırsınız:
Add-WebConfigurationProperty `
-Filter "system.webServer/rewrite/allowedServerVariables" `
-Name "." `
-Value @{name="HTTP_X_REAL_IP"} `
-PSPath "IIS:"
Add-WebConfigurationProperty `
-Filter "system.webServer/rewrite/allowedServerVariables" `
-Name "." `
-Value @{name="HTTP_X_FORWARDED_PROTO"} `
-PSPath "IIS:"
WebSocket Desteği
Modern uygulamaların büyük çoğunluğu artık WebSocket kullanıyor. ARR, WebSocket trafiğini varsayılan olarak iletmiyor. IIS’te WebSocket desteği için önce Windows özelliğini etkinleştirin:
Install-WindowsFeature -Name Web-WebSockets
Ardından ARR WebSocket desteği için web.config’e şunu ekleyin:
<system.webServer>
<webSocket enabled="true" />
<rewrite>
<rules>
<rule name="WebSocket_Proxy" stopProcessing="true">
<match url="^ws/(.*)" />
<conditions>
<add input="{HTTP_UPGRADE}" pattern="websocket" />
</conditions>
<action type="Rewrite" url="ws://localhost:3000/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
Burada {HTTP_UPGRADE} koşulu önemli. WebSocket handshake isteğinde Upgrade: websocket header’ı geliyor. Bunu koşul olarak ekleyerek sadece WebSocket isteklerini bu kural kapsamına alıyoruz.
SSL/TLS ve Mixed Content Sorunları
Kullanıcı HTTPS ile bağlanıyor, ARR backend’e HTTP ile gönderiyorsa mixed content uyarıları alabilirsiniz. Özellikle backend uygulama absolute URL üretiyorsa. Bunu yönetmenin birkaç yolu var.
web.config‘de HTTPS’i HTTP’ye yönlendiren kuralı düzgün yazmak:
<rule name="HTTP_to_HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
Bu kural HTTPS proxy kurallarınızın üzerinde değil, altında durmalı. Yoksa proxy kurallarına hiç ulaşamazsınız. Sıralamayı kontrol edin.
ARR SSL offloading yapıyorsa, yani HTTPS’i IIS’te sonlandırıp backend’e HTTP gönderiyorsa, backend’e bunu belirtmek önemli. X-Forwarded-Proto: https header’ını eklemek bu sorunu çözer. Yukarıda gösterdiğim serverVariables örneğinde bunu zaten ele aldık.
Load Balancing ile ARR Kullanımı
ARR’ın asıl güçlü özelliklerinden biri server farm tanımlayarak birden fazla backend arasında yük dağıtımı yapabilmesi. Bir web farm oluşturalım:
IIS Manager’da “Server Farms” kısmına sağ tıklayın, “Create Server Farm” deyin, bir isim verin (örneğin BackendFarm) ve sunucularınızı ekleyin. Bunun GUI üzerinden yapılması daha kolay ancak sonuçta applicationHost.config dosyasına şunun benzeri bir yapı yazılıyor:
<webFarms>
<webFarm name="BackendFarm" enabled="true">
<server address="192.168.1.10" enabled="true">
<applicationRequestRouting httpPort="8080" />
</server>
<server address="192.168.1.11" enabled="true">
<applicationRequestRouting httpPort="8080" />
</server>
<applicationRequestRouting>
<loadBalancing algorithm="RoundRobin" />
<healthCheck url="http://192.168.1.10:8080/health" interval="30" />
</applicationRequestRouting>
</webFarm>
</webFarms>
Server farm tanımladıktan sonra URL Rewrite kuralında hedef olarak farm adını kullanabilirsiniz:
<action type="Rewrite" url="http://BackendFarm/{R:1}" />
Health check URL’si kritik. Backend sunuculardan biri düşerse, ARR health check’ten başarısız yanıt aldığında o sunucuyu havuzdan çıkarıyor. /health endpoint’iniz basitçe 200 OK döndüren bir sayfa olsun yeterli.
Troubleshooting: Sık Karşılaşılan Hatalar
502.3 – Bad Gateway: Backend uygulama yanıt vermiyor veya ARR proxy etkin değil. İlk kontrol noktası: Enable proxy seçeneği işaretli mi?
HTTP 500 – serverVariable hatası: İzin verilmemiş server variable kullanıyorsunuz. allowedServerVariables listesine ekleyin.
URL Rewrite kuralı çalışmıyor: Failed Request Tracing en değerli araç. IIS’te Failed Request Tracing Rules ekleyin, hata durumunda detaylı log tutmasını sağlayın. Log dosyaları C:inetpublogsFailedReqLogFiles altında oluşuyor.
Failed Request Tracing’i PowerShell ile aktif etmek:
Enable-WebRequestTracing -Name "myapp.sirket.com" -StatusCodes "400-599"
ARR cache sorunları: ARR, statik içerikleri cache’lemeye çalışabilir ve bu bazen istenmeyen sonuçlar doğurur. Eğer dinamik içerikleriniz cache’leniyor gibi görünüyorsa, ARR cache’ini temizleyin:
Remove-Item -Path "C:WindowsSystem32inetsrvconfigARRCache" -Recurse -Force
veya IIS Manager’dan “Application Request Routing Cache” > “Clear Disk Cache” yolunu kullanın.
Performans Önerileri
ARR’ı production’a almadan önce birkaç ayarı gözden geçirmek gerekiyor:
- Connection timeout: Varsayılan değer çoğu senaryo için yeterli ancak uzun süren API istekleriniz varsa artırın.
applicationRequestRoutingbölümündetimeoutdeğerini saniye cinsinden belirleyin.
- Disk cache’i devre dışı bırakın: Dinamik uygulama proxy’si yapıyorsanız disk cache genellikle yük getiriyor, fayda sağlamıyor. Server Proxy Settings > “Enable disk cache” kutucuğunu kaldırın.
- HTTP/2 backend bağlantıları: ARR, backend ile HTTP/1.1 konuşur. Bu çoğu durumda sorun yaratmaz ama yüksek trafikli senaryolarda connection reuse’u optimize etmek fark yaratabilir.
- Kernel mode authentication devre dışı: Proxy senaryolarında Kernel mode authentication genellikle sorun yaratır. Application Pool’un ilgili authentication ayarlarını kontrol edin.
Sonuç
ARR modülü, Windows tabanlı altyapılarda reverse proxy ihtiyacını karşılamak için olgun ve güvenilir bir çözüm. Nginx veya HAProxy’nin esnekliğine ulaşamasa da, Windows ekosistemiyle olan entegrasyonu ve GUI yönetimi bazı ortamlar için gerçek bir avantaj.
Pratikte en çok karşılaştığım durum: legacy .NET uygulamalarının yanına modern Node.js veya Python servisleri eklenmesi ve bunların IIS arkasında birleştirilmesi. ARR bu köprüyü kurmakta oldukça işlevsel.
Dikkat edilmesi gereken temel noktalar: kural sıralaması, stopProcessing kullanımı, header yönetimi ve mutlaka Failed Request Tracing ile sorun giderme. Bu dördünü kafaya koyduğunuzda ARR ile ciddi sorun yaşamazsınız.
Production ortamına almadan önce, basit bir test senaryosu ile curl veya PowerShell Invoke-WebRequest ile yanıt header’larını inceleyin. Backend’den gelmemesi gereken bilgilerin dışarıya sızıp sızmadığını kontrol edin. Ve evet, X-Forwarded-For ile gerçek IP’yi logladığınızdan emin olun; ileride güvenlik olayı incelemesi yapmanız gerektiğinde bu çok önemli.
