WebSocket bağlantılarını proxy'lemek, HTTP Upgrade el sıkışmasını doğru şekilde işleyen ve WebSocket iletişimi için gereken kalıcı, çift yönlü TCP bağlantısını sürdüren bir ara sunucu yapılandırmak anlamına gelir. Bu kurulum, gerçek zamanlı uygulamalar için yük dengeleme, SSL sonlandırma, önbellekleme ve erişim denetimi gibi özellikleri mümkün kılar.
WebSocket proxy'lemeyi anlamak
WebSocket'ler, istemci ile sunucu arasında tek bir TCP bağlantısı üzerinden kalıcı bir bağlantı kurar. Bu, genellikle kısa ömürlü istek/yanıt döngüleri kullanan geleneksel HTTP'den farklıdır. HTTP'den WebSocket'e geçiş, HTTP/1.1 protokolündeki "Upgrade" mekanizmasıyla başlatılır.
İstemci, belirli başlıklar içeren bir ilk HTTP GET isteği gönderir:
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Key: [base64 kodlu nonce]
* Sec-WebSocket-Version: 13
Sunucu WebSocket'i destekliyorsa, yükseltmeyi onaylayan HTTP 101 Switching Protocols durumuyla yanıt verir:
* HTTP/1.1 101 Switching Protocols
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Accept: [istemcinin anahtarından türetilen yanıt anahtarı]
Bu el sıkışmanın ardından bağlantı artık HTTP değil, üzerinden WebSocket çerçevelerinin taşındığı ham bir TCP soketidir. Proxy sunucusu, bu Upgrade ve Connection başlıklarını doğru şekilde iletecek ve ardından uzun ömürlü TCP bağlantısını tamponlamadan veya erken kapatmadan sürdürecek biçimde yapılandırılmalıdır.
Yaygın proxy sunucuları için kurulum
Nginx
Nginx, HTTP Upgrade el sıkışmasını işleyerek WebSocket bağlantılarını etkin biçimde proxy'leyebilir. Anahtar nokta, istemciden gelen Upgrade ve Connection başlıklarını arka uç sunucusuna iletmek ve HTTP/1.1 kullanıldığından emin olmaktır.
http {
upstream websocket_backend {
server backend_server_1:8080;
server backend_server_2:8080;
}
server {
listen 80;
server_name yourdomain.com;
location /ws/ {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host; # Arka uç host başlığına dayanıyorsa önemlidir
proxy_read_timeout 86400s; # Uzun ömürlü bağlantılar için gerektiği gibi ayarlayın
proxy_send_timeout 86400s;
proxy_buffering off; # Gerçek zamanlı veri için tamponlamayı kapatın
}
# Diğer HTTP location'ları
location / {
proxy_pass http://other_http_backend;
# ... diğer HTTP proxy ayarları
}
}
}
proxy_http_version 1.1;:Upgradebaşlığı mekanizması için şarttır.proxy_set_header Upgrade $http_upgrade;: istemcininUpgradebaşlığını iletir.proxy_set_header Connection "upgrade";: istemcininConnectionbaşlığını iletir. Açıkça "upgrade" olarak ayarlanmazsa Nginx, HTTP/1.1 bağlantılarındaConnection: upgradedeğerini otomatik olarakConnection: keep-alivebiçimine dönüştürür. Açıkça ayarlamak, WebSocket'ler için doğru davranışı garantiler.proxy_read_timeout/proxy_send_timeout: Nginx'in uzun ömürlü WebSocket bağlantılarını hareketsizlik nedeniyle kapatmasını önlemek için bu değerleri varsayılanın üzerine çıkarın.proxy_buffering off;: Nginx'in yanıtları tamponlamasını engeller; gerçek zamanlı WebSocket iletişiminde minimum gecikme için kritiktir.
Apache HTTP Server
Apache, mod_proxy'nin parçası olan mod_proxy_wstunnel ile WebSocket bağlantılarını proxy'leyebilir. mod_proxy, mod_proxy_http ve mod_proxy_wstunnel modüllerinin etkin olduğundan emin olun.
<VirtualHost *:80>
ServerName yourdomain.com
# Proxy modüllerini etkinleştir
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
# WebSocket bağlantılarını proxy'le
<Location /ws/>
ProxyPass ws://backend_server:8080/ws/
ProxyPassReverse ws://backend_server:8080/ws/
</Location>
# Güvenli WebSocket bağlantılarını (WSS) proxy'le
<Location /wss/>
ProxyPass wss://backend_server:8443/wss/
ProxyPassReverse wss://backend_server:8443/wss/
</Location>
# Diğer HTTP location'ları
<Location />
ProxyPass http://other_http_backend/
ProxyPassReverse http://other_http_backend/
</Location>
</VirtualHost>
ProxyPass ws://...:ws://şeması,mod_proxy_wstunnelmodülüne WebSocket yükseltmesini işlemesini söyler. Güvenli WebSocket'ler içinwss://kullanın.ProxyPassReverse: yanıt başlıklarında URL'lerin doğru şekilde yeniden yazılmasını sağlar.ws://veyawss://belirtildiğinde Apache'ninmod_proxymodülüUpgradeveConnectionbaşlıklarını otomatik olarak işler.
HAProxy
HAProxy, 1.5 sürümünden beri WebSocket proxy'lemeyi destekler. Başlıkları incelemek için http modunda, ham iletim için tcp modunda çalışabilir. WebSocket'lerde genellikle yükseltme isteğini tespit eden özel kurallarla birlikte http modu kullanılır.
global
log /dev/log local0 info
maxconn 4000
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms # İstemci tarafı WebSocket bağlantıları için artırıldı
timeout server 50000ms # Arka uç tarafı WebSocket bağlantıları için artırıldı
frontend http_frontend
bind *:80
acl is_websocket hdr(Upgrade) -i websocket
use_backend ws_backend if is_websocket
default_backend http_backend
backend ws_backend
mode http
# Bu seçenek HTTP modunda WebSocket'ler için kritiktir; HAProxy'ye HTTP
# yükseltmesinden sonra TCP tünellemeye geçmesini söyler.
option http-tunnel
server backend_ws_1 backend_server_1:8080 check
server backend_ws_2 backend_server_2:8080 check
backend http_backend
mode http
server backend_http_1 backend_server_3:80 check
acl is_websocket hdr(Upgrade) -i websocket:Upgrade: websocketbaşlığı içeren istekleri (büyük/küçük harf duyarsız) eşleştiren bir Access Control List (ACL) tanımlar.use_backend ws_backend if is_websocket: WebSocket yükseltme istekleriniws_backendarka ucuna yönlendirir.option http-tunnel: bu kritiktir. HAProxy birUpgradebaşlığı algıladığında ve bu seçenek ayarlıysa, ilk HTTP el sıkışmasının ardından HTTP ayrıştırma modundan ham TCP tüneline geçer. Böylece WebSocket protokolü engellenmeden çalışır.timeout client/timeout server: HAProxy'nin uzun ömürlü bağlantıları kapatmasını önlemek için WebSocket arka uçlarında bu zaman aşımları belirgin şekilde artırılmalıdır.
Yaygın sorunların giderilmesi
Bağlantının kopması veya zaman aşımı
- Proxy zaman aşımları: en yaygın nedendir.
proxy_read_timeout,proxy_send_timeout(Nginx),timeout client,timeout server(HAProxy) veya diğer proxy'lerdeki eşdeğer ayarların WebSocket bağlantıları için yeterince yüksek olduğundan emin olun (örneğin 24 saat veya daha fazla). - Boşta kalan bağlantılar: bazı proxy'ler veya ağ cihazları boştaki TCP bağlantılarını agresif biçimde kapatabilir. WebSocket protokolünde bir keep-alive mekanizması varsa (örneğin ping/pong çerçeveleri), periyodik ping göndermek üzere hem istemcide hem sunucuda yapılandırıldığından emin olun.
- Yük dengeleyici hareketsizliği: proxy'nin önünde bir yük dengeleyici varsa onun da kendi hareketsizlik zaman aşımları olabilir. Bu ayarları kontrol edin.
HTTP 400 Bad Request (Upgrade başlığı eksik veya hatalı)
- İstemci isteği: istemcinin
Upgrade: websocketveConnection: Upgradebaşlıklarını doğru gönderdiğini doğrulayın. - Proxy yapılandırması: proxy'nin bu başlıkları arka uca ilettiğinden emin olun.
- Nginx:
proxy_set_header Upgrade $http_upgrade;veproxy_set_header Connection "upgrade";satırlarını kontrol edin. - Apache:
mod_proxy_wstunnelmodülünün etkin olduğundan veProxyPassyönergesininws://ya dawss://kullandığından emin olun. - HAProxy:
acl is_websocketkuralınınUpgradebaşlığını doğru tespit ettiğini veuse_backendileoption http-tunnelayarlı bir arka uca yönlendirdiğini doğrulayın.
- Nginx:
HTTP 502 Bad Gateway
- Arka uç sunucu sorunları: proxy, arka uçtan geçersiz bir yanıt aldı.
- Arka uç WebSocket sunucusu çalışıyor ve beklenen portu dinliyor mu?
- Arka uç, WebSocket yükseltmelerini işleyecek şekilde doğru yapılandırılmış mı?
- Arka uç sunucu günlüklerinde hata olup olmadığına bakın.
- Ağ bağlantısı: proxy'nin belirtilen port üzerinden arka uç sunucusuna erişebildiğini doğrulayın.
- Proxy tamponlaması:
proxy_buffering offgenelde WebSocket'ler için iyi olsa da, aşırı veri veya hatalı yapılandırma, proxy akışı işlemekte zorlandığında bazen 502 hatalarına yol açabilir.
Güvenlik değerlendirmeleri (SSL/TLS sonlandırma)
- WSS (güvenli WebSocket'ler): güvenli WebSocket bağlantıları (wss://) için SSL/TLS sonlandırmayı proxy üstlenmelidir.
- Proxy 443 portunu (veya başka bir güvenli portu) dinler, TLS el sıkışmasını yapar ve şifresi çözülmüş WebSocket trafiğini arka uca iletir (dahili olarak genellikle düz
ws://veyahttp://üzerinden). - WSS için örnek Nginx yapılandırması:
```nginx
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/nginx/ssl/yourdomain.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.key;location /ws/ { proxy_pass http://websocket_backend; # Arka uç düz HTTP olabilir proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 86400s; proxy_send_timeout 86400s; proxy_buffering off; }}
`` * **Origin başlıkları:** WebSocket istemcileri birOrigin` başlığı gönderir. Arka uç sunucuları güvenlik nedeniyle bu başlığı sıklıkla doğrular. Arka uç bu başlığa dayanıyorsa proxy'nizin onu kaldırmadığından veya değiştirmediğinden emin olun.
- Proxy 443 portunu (veya başka bir güvenli portu) dinler, TLS el sıkışmasını yapar ve şifresi çözülmüş WebSocket trafiğini arka uca iletir (dahili olarak genellikle düz
Proxy tampon sınırları
- Nginx:
proxy_buffering off;kritiktir. Ayarlanmazsa Nginx büyük WebSocket mesajlarını tamponlayabilir; bu da gecikmeye veya zaman aşımlarına yol açar. - HAProxy:
option http-tunnel, ham TCP'ye geçerek bu sorunu çözer.
WebSocket'ler için proxy sunucularının karşılaştırması
| Özellik | Nginx | Apache HTTP Server (mod_proxy_wstunnel) | HAProxy |
|---|---|---|---|
| Yapılandırma | Manuel başlık iletimi | Özel ws:// / wss:// yönergeleri |
ACL'ler ve option http-tunnel |
| Karmaşıklık | Orta | Orta | Orta-yüksek (gelişmiş özellikler için) |
| Performans | Yüksek (olay tabanlı) | Orta (süreç/iş parçacığı tabanlı) | Yüksek (olay tabanlı) |
| SSL/TLS sonlandırma | Mükemmel | İyi | Mükemmel |
| Yük dengeleme | Round-robin, IP hash, least_conn | Round-robin | Kapsamlı (birçok algoritma, sağlık kontrolü) |
| Sticky session | IP hash (temel), üçüncü parti modüller | Sınırlı | Çerez tabanlı, kaynak IP |
| Tamponlama denetimi | proxy_buffering off |
mod_proxy_wstunnel tarafından yönetilir |
option http-tunnel HTTP tamponlamasını kapatır |
Dikkat edilmesi gerekenler
- Sticky session'lar: bazı WebSocket uygulamalarında istemcinin oturum boyunca aynı arka uç sunucusuna bağlı kalması gerekebilir (örneğin sunucu tarafında durum tutuluyorsa).
- Nginx:
upstreambloğundaip_hashkullanın. - HAProxy:
balance sourceveyacookieyönergelerini kullanın. - Mümkünse arka uç uygulamanızı sticky session gerektirmeden yatay ölçeklenecek şekilde tasarlayın; bu yük dengelemeyi basitleştirir.
- Nginx:
- Sağlık kontrolleri: proxy içinde arka uç WebSocket sunucularınız için sağlam sağlık kontrolleri yapılandırın. Böylece yalnızca sağlıklı sunucular WebSocket yükseltme isteği alır.
- Günlükleme: proxy'de ve arka uçta kapsamlı günlükleme yapılandırın. WebSocket bağlantı sorunları geçici olabilir ve teşhis için ayrıntılı günlükler şarttır.
- HTTP/2 ve WebSocket'ler: WebSocket'ler yükseltme el sıkışması için genellikle HTTP/1.1 kullansa da HTTP/2 ile bir arada bulunabilirler. Ancak WebSocket protokolünün kendisi doğrudan HTTP/2 çerçeveleri üzerinde çalışmaz. İstemcilerden HTTP/2 alan proxy'ler, arka uca yapılan WebSocket yükseltmesi için genellikle HTTP/1.1'e düşer.
