IIS’te WebSocket Desteği Etkinleştirme

Bir proje üzerinde çalışırken “WebSocket bağlantısı kurulamıyor” hatası aldığınızda, ilk şüphelenilecek yer genellikle uygulama kodudur. Ama birçok durumda asıl sorun IIS tarafındadır; WebSocket protokolü kurulu değildir ya da yanlış yapılandırılmıştır. Özellikle Windows Server ortamlarında IIS üzerinde çalışan .NET, Node.js veya SignalR tabanlı uygulamalar geliştiren ekiplerin bu sorunla karşılaştığını sıkça görüyoruz. Bu yazıda IIS’te WebSocket desteğini baştan sona ele alacağız; kurulumdan sorun gidermeye kadar her adımı gerçek dünya senaryolarıyla açıklayacağız.

WebSocket Nedir ve IIS Neden Varsayılan Olarak Desteklemez?

WebSocket, HTTP üzerinden başlayan ama daha sonra kalıcı, çift yönlü bir bağlantıya dönüşen bir protokoldür. Klasik HTTP’de istemci sürekli yeni istekler açar; WebSocket’te ise bir kere el sıkışma (handshake) yapılır ve bağlantı açık kalır. Bu yapı; anlık mesajlaşma, canlı bildirimler, finansal veri akışları ve çok oyunculu oyunlar gibi senaryolarda kritik öneme sahiptir.

IIS, Windows Server 8 ve sonrasında WebSocket desteğini bünyesine almıştır. Ancak bu özellik varsayılan olarak kurulu gelmez. Windows Server kurulumunda rolü yüklerken ya da sonradan eklerken “WebSocket Protocol” bileşenini açıkça seçmeniz gerekir. Pek çok sysadmin standart bir IIS kurulumu yapıp uygulamayı devreye alırken bu adımı atlıyor.

Şunu da belirtmek gerekir: Windows Server 2008 R2 ve altında WebSocket desteği yerleşik olarak hiç gelmez. O ortamlarda üçüncü parti çözümlere ya da uygulama katmanında farklı yaklaşımlara gitmeniz gerekir.

Ön Koşullar

Başlamadan önce ortamınızın uygun olduğundan emin olun:

  • Windows Server 2012 veya üzeri (2016/2019/2022 tercih edilir)
  • IIS 8.0 veya üzeri
  • Sunucuda yönetici yetkisi
  • Uygulamanızın WebSocket protokolünü destekliyor olması (.NET 4.5+, ASP.NET Core, Node.js vb.)

Yöntem 1: Server Manager Üzerinden Kurulum (GUI)

En sık kullanılan yöntem Server Manager üzerinden yapmaktır. Özellikle sunucuyla ilk kez çalışıyorsanız veya görsel bir onay almak istiyorsanız bu yol daha güvenlidir.

Adım adım:

  • Server Manager’ı açın
  • “Manage” menüsünden “Add Roles and Features” seçeneğine tıklayın
  • “Role-based or feature-based installation” seçeneğini seçin
  • Hedef sunucuyu seçin
  • “Server Roles” ekranında “Web Server (IIS)” altında ilerleyin
  • “Web Server” > “Application Development” kategorisine gidin
  • “WebSocket Protocol” kutucuğunu işaretleyin
  • Kurulumu tamamlayın

Bu kadar. IIS’i yeniden başlatmanız gerekmez; özellik anında etkin hale gelir. Ancak uygulamanızı application pool’u recycle ederek ya da uygulama havuzunu yeniden başlatarak sıfırlamanızı öneririm.

Yöntem 2: PowerShell ile Kurulum

Birden fazla sunucuyu yönetiyorsanız ya da CI/CD pipeline’ınıza bu adımı eklemek istiyorsanız PowerShell çok daha verimlidir.

# WebSocket Protocol özelliğini yükle
Install-WindowsFeature Web-WebSockets

# Kurulumu doğrula
Get-WindowsFeature Web-WebSockets

Kurulum başarılıysa çıktıda InstallState: Installed görürsünüz. Eğer sunucu bir Windows Server Core kurulumuysa zaten GUI’niz yoktur ve bu komut tek seçeneğinizdir.

Birden fazla sunucuya aynı anda kurmak için:

# Hedef sunucu listesi
$servers = @("webserver01", "webserver02", "webserver03")

foreach ($server in $servers) {
    Invoke-Command -ComputerName $server -ScriptBlock {
        Install-WindowsFeature Web-WebSockets
        Write-Host "$env:COMPUTERNAME: WebSocket kurulumu tamamlandi"
    }
}

Yöntem 3: DISM ile Kurulum

Özellikle offline kurulum senaryolarında veya WIM imajı hazırlıyorsanız DISM tercih edilebilir:

# Çevrimiçi kurulum
dism /online /enable-feature /featurename:IIS-WebSockets /all

# Kurulum durumunu kontrol et
dism /online /get-featureinfo /featurename:IIS-WebSockets

/all parametresi bağımlılıkları otomatik olarak çözümler. Bağımlı bileşenlerden biri eksikse bu parametre olmadan kurulum başarısız olabilir.

web.config Yapılandırması

WebSocket özelliğini IIS’e kurdunuz, ama uygulamanız hâlâ çalışmıyor olabilir. Bunun nedeni genellikle web.config içinde gerekli ayarların yapılmamış olmasıdır.

ASP.NET uygulamaları için temel WebSocket yapılandırması:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <webSocket enabled="true" 
               pingInterval="00:00:30"
               receiveBufferLimit="4194304" />
    <handlers>
      <add name="WebSocketHandler" 
           verb="GET" 
           path="ws.ashx" 
           type="MyApp.WebSocketHandler, MyApp" />
    </handlers>
  </system.webServer>
</configuration>

enabled: WebSocket protokolünü bu uygulama için aktifleştirir pingInterval: Bağlantıyı canlı tutmak için ping aralığı (varsayılan 30 saniye) receiveBufferLimit: Maksimum alım tamponu boyutu (byte cinsinden, varsayılan 4MB)

Eğer WebSocket’i belirli bir uygulama için devre dışı bırakmak istiyorsanız:

<system.webServer>
  <webSocket enabled="false" />
</system.webServer>

Bu özellikle paylaşımlı ortamlarda bir uygulamayı izole etmek istediğinizde kullanışlıdır.

ASP.NET Core Uygulamalarında WebSocket Desteği

ASP.NET Core ile IIS’i bir arada kullandığınızda yapı biraz farklılaşır. ASP.NET Core, IIS’i arka planda bir reverse proxy olarak kullanır (in-process veya out-of-process hosting). WebSocket desteğinin çalışması için hem IIS bileşeni kurulu olmalı hem de uygulama içinde WebSocket middleware’i eklenmiş olmalıdır.

Program.cs veya Startup.cs içinde:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// WebSocket middleware'i ekle
var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

app.UseWebSockets(webSocketOptions);

app.Map("/ws", async context =>
{
    if (context.WebSockets.IsWebSocketRequest)
    {
        using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
        await HandleWebSocketConnection(webSocket);
    }
    else
    {
        context.Response.StatusCode = StatusCodes.Status400BadRequest;
    }
});

app.Run();

In-process hosting kullanıyorsanız web.config içinde şunun doğru ayarlı olduğundan emin olun:

<system.webServer>
  <aspNetCore processPath="dotnet"
              arguments=".MyApp.dll"
              stdoutLogEnabled="false"
              hostingModel="inprocess" />
  <webSocket enabled="true" />
</system.webServer>

Out-of-process modunda IIS, WebSocket trafiğini Kestrel’e iletir. Bu durumda da IIS WebSocket bileşeninin kurulu olması şarttır; aksi takdirde IIS upgrade isteğini Kestrel’e geçirmez.

SignalR ile WebSocket Yapılandırması

SignalR kullanan projelerde WebSocket, birden fazla transport seçeneğinden biridir. SignalR önce WebSocket’i dener; başarısız olursa Server-Sent Events veya Long Polling’e geçer. Eğer WebSocket desteğini aktif etmediyseniz SignalR fallback mekanizmasına geçer ve performans ciddi biçimde düşer.

SignalR’ı sadece WebSocket üzerinden çalışacak şekilde kısıtlamak için:

builder.Services.AddSignalR(options =>
{
    options.EnableDetailedErrors = true;
});

app.MapHub<ChatHub>("/chatHub", options =>
{
    options.Transports = HttpTransportType.WebSockets;
});

Bu yapılandırmayla SignalR, WebSocket dışındaki transport yöntemlerine hiç bakmaz. Eğer WebSocket çalışmıyorsa bağlantı tamamen başarısız olur; bu da sorunun hızla fark edilmesini sağlar.

Güvenlik Duvarı ve ARR (Application Request Routing) Ayarları

Birçok üretim ortamında IIS önünde bir load balancer veya ARR (Application Request Routing) bulunur. WebSocket bağlantıları HTTP Upgrade mekanizması kullandığından bu katmanlarda özel ayarlar gerekebilir.

ARR kullanıyorsanız applicationHost.config veya ARR rule tanımlamalarında proxy ayarlarını kontrol edin:

<rewrite>
  <rules>
    <rule name="WebSocket Proxy" stopProcessing="true">
      <match url="^ws(/.*)?$" />
      <conditions>
        <add input="{HTTP_CONNECTION}" pattern="Upgrade" />
        <add input="{HTTP_UPGRADE}" pattern="websocket" ignoreCase="true" />
      </conditions>
      <action type="Rewrite" url="http://backend-server/{R:0}" />
    </rule>
  </rules>
</rewrite>

ARR üzerinde WebSocket proxy’si için disableCache ayarının da aktif olduğundan emin olun; cache mekanizması WebSocket bağlantılarını bozabilir.

Windows Güvenlik Duvarı tarafında WebSocket için özel bir port açmanıza gerek yoktur; standart HTTP (80) ve HTTPS (443) portları üzerinden çalışır. Ancak özel port kullanıyorsanız ilgili port kurallarını kontrol edin.

SSL/TLS ile WebSocket (WSS)

Prodüksiyon ortamında WebSocket bağlantılarını her zaman WSS (WebSocket Secure) üzerinden kurmalısınız. IIS’te SSL sertifikanızı HTTPS binding’e doğru şekilde eklediyseniz WSS otomatik olarak çalışır; ayrıca bir şey yapmanız gerekmez.

Sertifika bağlama doğrulaması için:

# Mevcut SSL binding'leri listele
netsh http show sslcert

# Belirli bir IP:Port için sertifika bilgisi
netsh http show sslcert ipport=0.0.0.0:443

Eğer karma içerik uyarısı alıyorsanız (HTTPS sayfa üzerinden WS bağlantısı deneniyorsa) istemci tarafında bağlantı adresini wss:// olarak güncellemeniz gerekir.

Sorun Giderme

WebSocket Bağlantısı 101 Dönmüyor

En yaygın hata budur. Tarayıcı geliştirici araçlarında WebSocket isteğine 400 veya 500 yanıtı geliyorsa şunları kontrol edin:

# WebSocket özelliğinin kurulu olup olmadığını kontrol et
Get-WindowsFeature Web-WebSockets | Select-Object Name, InstallState

# IIS servis durumu
Get-Service W3SVC | Select-Object Status

# Application pool durumu
Import-Module WebAdministration
Get-WebConfiguration system.applicationHost/applicationPools/add | 
    Select-Object name, state

Event Log’dan Hata Okuma

# Son 50 IIS ile ilgili event log kaydı
Get-EventLog -LogName Application -Source "IIS*" -Newest 50 | 
    Select-Object TimeGenerated, EntryType, Message | 
    Format-List

Failed Request Tracing ile Detaylı Hata Ayıklama

IIS’in yerleşik Failed Request Tracing (FREB) özelliği WebSocket sorunlarını tespit etmek için çok değerlidir:

<tracing>
  <traceFailedRequests>
    <add path="*">
      <traceAreas>
        <add provider="WWW Server" 
             areas="WebSocket" 
             verbosity="Verbose" />
      </traceAreas>
      <failureDefinitions statusCodes="400-599" />
    </add>
  </traceFailedRequests>
</tracing>

Bu yapılandırma web.config içine eklenebilir ya da IIS Manager üzerinden Failed Request Tracing kuralı olarak tanımlanabilir. FREB logları %SystemDrive%inetpublogsFailedReqLogFiles altında XML formatında birikir.

Bağlantı Sayısı Limitleri

Yoğun WebSocket trafiği olan uygulamalarda application pool’un maximum worker process sayısını ve bağlantı limitlerini gözden geçirin:

# Application pool max worker process sayısını ayarla
Set-WebConfigurationProperty `
    -filter "/system.applicationHost/applicationPools/add[@name='MyAppPool']" `
    -name "processModel.maxProcesses" `
    -value 4

# Idle timeout'u devre dışı bırak (WebSocket için önemli!)
Set-WebConfigurationProperty `
    -filter "/system.applicationHost/applicationPools/add[@name='MyAppPool']" `
    -name "processModel.idleTimeout" `
    -value "00:00:00"

Bu son madde kritik: IIS’in varsayılan idle timeout değeri 20 dakikadır. Uzun süreli WebSocket bağlantıları olan uygulamalarda application pool bu sürede kapanabilir ve tüm aktif bağlantılar kesilir. Timeout’u sıfıra çekmek veya yeterince büyük bir değere ayarlamak şarttır.

Bağlantıyı Test Etme

Kurulum ve yapılandırma tamamlandıktan sonra WebSocket bağlantısını doğrulamak için wscat aracını kullanabilirsiniz:

# wscat kurulumu (Node.js gerektirir)
npm install -g wscat

# Bağlantı testi
wscat -c ws://sunucu-adiniz.com/ws

# SSL ile test
wscat -c wss://sunucu-adiniz.com/ws

PowerShell ile basit bir test:

# .NET WebSocket istemcisi ile bağlantı testi
$uri = [System.Uri]"ws://localhost/ws"
$client = [System.Net.WebSockets.ClientWebSocket]::new()

try {
    $cts = [System.Threading.CancellationTokenSource]::new(5000)
    $client.ConnectAsync($uri, $cts.Token).Wait()
    
    if ($client.State -eq "Open") {
        Write-Host "WebSocket baglantisi basarili!" -ForegroundColor Green
    }
} catch {
    Write-Host "Baglanti hatasi: $_" -ForegroundColor Red
} finally {
    $client.Dispose()
}

Gerçek Dünya Senaryosu: Üretim Ortamında Yaşanan Bir Sorun

Bir e-ticaret firmasında çalışırken anlık sipariş takibi için geliştirilen SignalR tabanlı dashboard’lar, staging ortamında mükemmel çalışmasına rağmen prodüksiyonda bağlantı sorunları yaşıyordu. Loglar incelendiğinde bağlantıların 101 Switching Protocols yerine 200 OK ile kapandığı görüldü; bu da WebSocket upgrade’inin gerçekleşmediğine işaret ediyordu.

Sorun birkaç katmandaydı: Önce prodüksiyon sunucularına WebSocket bileşeni hiç kurulmamıştı (staging’de kuruluydu ama prodüksiyon image’ı farklıydı). İkinci olarak, önde duran hardware load balancer WebSocket trafiğini tanımıyordu ve Connection: Upgrade header’larını modifiye ediyordu. Üçüncüsü, application pool idle timeout değeri 20 dakikaydı ve kullanıcıların uzun süre aktif olmadığı gece saatlerinde pool kapanıp tüm bağlantılar kesiliyor, sabah açılışında sistem yavaş toparlanıyordu.

Çözüm: Üç maddeyi de düzelttikten sonra sistem kararlı hale geldi. Bu deneyimden çıkan ders şu: WebSocket sorunlarını sadece uygulama katmanında aramayın; ağ ekipmanları ve IIS ayarları aynı derecede kritiktir.

Sonuç

IIS’te WebSocket desteği etkinleştirmek başlı başına karmaşık bir işlem değildir. Ancak bileşen kurulumunu atlamak, web.config’i doğru yapılandırmamak veya application pool idle timeout gibi detayları gözden kaçırmak prodüksiyon ortamında ciddi sorunlara yol açabilir.

Özetle dikkat edilmesi gereken temel noktalar:

  • Web-WebSockets bileşenini mutlaka kurun, varsayılan kurulumda gelmez
  • web.config içinde satırının varlığını doğrulayın
  • Application pool idle timeout’unu uzun süreli bağlantılar için sıfırlayın veya artırın
  • ARR veya load balancer kullanıyorsanız Upgrade header’larının korunduğunu kontrol edin
  • Prodüksiyon dağıtımlarında WebSocket bağlantısını wscat veya PowerShell ile test edin
  • ASP.NET Core out-of-process modunda IIS WebSocket bileşeni hâlâ gereklidir

Kurulumu otomatikleştirmek istiyorsanız PowerShell script’leri ve Desired State Configuration (DSC) ile tüm bu adımları tekrarlanabilir hale getirebilirsiniz. Özellikle birden fazla sunucu yöneten ortamlarda manuel konfigürasyona güvenmek hataya açık kapı bırakır.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir