WebSocket

WebSocket, tek bir TCP bağlantısı üzerinden tam çift yönlü iletişim kanalı sağlayan bir bilgisayar iletişim protokolüdür. WebSocket protokolü IETF tarafından 2011 yılında RFC 6355 ile standart hale getirilmiş ve WebIDL içerisindeki WebSocket API W3C tarafından standart hale getirilmektedir.
WebSocket, web tarayıcılarında ve web sunucularında uygulanmak üzere tasarlanmıştır, fakat herhangi bir istemci veya sunucu uygulaması tarafından uygulanabilmektedir. WebSocket protokolü, TCP tabanlı bağımsız bir protokoldür. HTTP ile tek ilişkisi, HTTP sunucuları tarafından bir Upgrade isteği olarak yorumlanmasıdır. WebSocket protokolü, sunucuya ve sunucudan gerçek zamanlı veri aktarımını sağlayarak, tarayıcı ile web sunucusu arasında etkileşimi sağlamaktadır. Bu, sunucunun istemci istemeden tarayıcıya içerik gönderebileceği ve bağlantıyı açık tutarak istediği zaman mesaj alabilmesini veya gönderebilmesini sağlayan standart bir yöntem ile sağlanmaktadır. Bu şekilde, tarayıcı ile sunucu arasında iki yönlü devam eden bir iletişim gerçekleşebilmektedir. İletişim TCP 80 portu (veya TLS ile şifrelenmiş bağlantılarda 443 portu) üzerinden gerçekleşmektedir ve bu, güvenlik duvarı kullanarak Internet web trafiğini engelleyen ortamlar için bir avantaj olmaktadır. Benzer iki yönlü sunucu-tarayıcı iletişimi Comet gibi standart olmayan stopgap teknolojileri tarafından sağlanmaktaydı.
WebSocket protokolü, Google Chrome, Microsoft Edge, Internet Explorer, Firefox, Safari ve Opera dahil pek çok tarayıcı tarafından desteklenmektedir. WebSocket ayrıca sunucu üzerindeki web uygulamalarının da desteğini gerektirmektedir.

Genel bakış

HTTP’den farklı olarak, WebSocket protokolü tam çift yönlü iletişim sağlamaktadır. İlave olarak, WebSocket TCP protokolünün üzerinde mesaj akışına imkan tanımaktadır. TCP tek başına, mesaj kavramı kullanmadan byte akışı ile ilgilenmektedir. WebSocket protokolünden önce, 80 protokolü üzerinden tam çift yönlü iletişim Comet kanalları üzerinden yapılabilmekteydi; fakat, Comet uygulaması çok yaygın değildir ve TCP el sıkışması ve HTTP başlıkları yüzünden küçük mesajlar için verimsiz olmaktadır. WebSocket protokolü, webin güvenlik ilkelerini etkilemeksizin bu problemleri çözmeyi amaçlamaktadır.
WebSocket protokolü tanımı, şifreli ve şifresiz trafik için kullanılan iki yeni uniform resource identifier (URI)  formatı olan  ws ve wss ifadelerini tanımlamaktadır. Şema adı ve fragment dışında (# desteklenmemektedir), diğer URI bileşenleri için genel URI biçimini kullanacak şekilde tanımlanmıştır.
Tarayıcının Geliştirici Araçlarını kullanarak, geliştiriciler WebSocket paketleri ile WebSocket el sıkışmasını inceleyebilmektedir.

Tarih

WebSocket, HTML5 tanımında ilk olarak, TCP tabanlı soket API’si yerine  TCPConnection olarak anılmıştır. Haziran 2008’de, Michael Carter tarafından, WebSocket olarak bilinen protokolün ilk versiyonu olan bir takım çalışma gerçekleştirilmiştir.
Bunun üzerine kısa bir süre sonra Ian Hickson ve Michael Carter tarafından #whatwg IRC chat odasındaki işbirliği ile WebSocket ismi verilmiştir ve sonrasında Ian Hickson tarafından HTML5 tanımında yer alacak şekilde yazılmıştır ve Michael Carter tarafından bir blog üzerinde duyurulmuştur. Aralık 2009’da, varsayılan olarak WebSocket protokolü standartlarını tamamen uygulayan ilk tarayıcı Google Chrome 4 olmuştur. Sonrasında, Şubat 2010’da WebSocket protokolünün geliştirilmesi, W3C ve whatwg IRC grubundan IET’ye geçmiştir ve Ian Hickson gözetiminde iki değişime uğramıştır.
Protokol tamamlandıktan ve birden çok tarayıcı tarafından varsayılan olarak desteklendikten sonra, Aralık 2011’de Ian Fette gözetiminde RFC tamamlanmıştır.

Protokol El Sıkışması

Bir WebSocket bağlantısı kurmak için istemci, aşağıdaki örnekte gösterildiği gibi sucununun WebSocket el sıkışma cevabı gönderdiği bir WebSocket el sıkışma isteği göndermektedir.

İstemci isteği (HTTP’de olduğu gibi, her bir satır  \r\n ile bitmektedir ve sonda ilave bir boş satır bulunmak zorundadır):
GET /chat HTTP/1.1Host: server.example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13Origin: http://example.com
Sunucunun cevabı:
HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=Sec-WebSocket-Protocol: chat
El sıkışma, sunucuların aynı port üzerinden hem HTTP bağlantılarını hem de WebSocket bağlantılarını işleyebilmesi açısından HTTP’ye benzemektedir. Bağlantı kurulduğunda, iletişim, HTTP protokolüne uymayan iki taraflı bir ikili protokole dönüşmektedir.
Upgrade başlığına ek olarak, istemci base64 ile kodlanmış rastgele bytelardan oluşan bir Sec-WebSocket-Key başlığını da göndermektedir. Sunucu ise Sec-WebSocket-Accept başlığı ile anahtar değerinin özeti ile cevap vermektedir. Bu yöntem, önceki bir WebSocket trafiğinin tekrar oynatılmasını engellemeye çalışmaktadır ve herhangi bir kimlik doğrulama, gizlilik veya bütünlük kontrolü sağlamamaktadır.  Özet fonksiyonu 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 sabit değerini Sec-WebSocket-Key başlığındaki (base64 kodlaması çözülmemiş) değere eklemekte, SHA-1 özet fonksiyonunu uygulamakta ve sonucu base64 kullanarak kodlamaktadır.
Bağlantı kurulduktan sonra, istemci ve sunucu WebSocket verisini tam çift yönlü modda gönderebilmektedir. Veri, payload tarafından takip edilen küçük bir başlık ile minimal bir şekilde çerçevelenmektedir. WebSocket iletişimi, tek bir mesajın birkaç veri çerçevesi içerisine dağılabileceği mesajlarla tanımlanmaktadır. Bu, verinin ilk kısmının bilindiği fakat mesajın toplam büyüklüğünün bilinmediği durumlarda, mesajların gönderilebilmesine izin vermektedir (FIN biti ile işaretlenip sona erişilene kadar veri çerçevelerini arka arkaya göndermektedir). Protokol üzerinde yapılan eklentilerle, farklı veri akışlarının eş zamanlı olarak çoklanması için de kullanılabilmektedir (örneğin bir soketin kullanımını tek bir büyük payload için tekelleştirilmesini önlemek için).
(Güvenlik açısından) Sunucu tarafında bağlantı kurulurken Origin başlığının doğrulanması, Siteler Arası WebSocket Çalma (Cross-Site WebSocket Hijacking) saldırılarına karşı koruma açısından önem taşımaktadır. Bu saldırı bağlantı çerezler veya HTTP kimlik doğrulaması ile doğrulandığında mümkün olabilmektedir.  WebSocket üzerinden hassas veriler iletilirken, WebSocket bağlantısını doğrulamak için token veya benzer koruma mekanizmalarının kullanılması faydalı olacaktır.

Proxy geçişi

WebSocket protokolü istemci uygulamaları, web tarayıcısının hedef makine ve porta bağlanırken bir vekil sunucu kullanıp kullanmadığını tespit etmeye çalışmaktadır ve eğer kullanıyorsa, kalıcı bir tünel oluşturmak için HTTP CONNECT metodunu kullanmaktadır.
WebSocket protokolünün kendisi vekil sunucuların ve güvenlik duvarlarının farkında olmasa da, HTTP’ye uygun bir el sıkışmayı desteklemektedir ve böylece HTTP sunucularının varsayılan HTTP ve HTTPS portlarını (80 ve 443) bir WebSocket ağ geçidiyle veya sunucusuyla paylaşmasına izin vermektedir. WebSocket protokolü, WebSocket ve Güvenli WebSocket bağlantılarını belirtmek için ws:// ve wss:// öneklerini tanımlamaktadır. Her iki yöntemde, bağlantıyı WebSocket’a yükseltmek için bir HTTP yükseltme mekanizması kullanmaktadır. Bazı vekil sunucular şeffaftır ve WebSocket ile çalışabilmektedir; diğerleri ise WebSocket protokolünün çalışmasını engelleyecektir ve bağlantının sonlanmasına yol açacaktır. Bazı durumlarda, ilave vekil sunucu yapılandırması gerekebilmektedir ve bazı vekil sunucuların WebSocket protokolünü desteklemesi için yükseltilmesi gerekebilmektedir.
Eğer şifrelenmemiş WebSocket trafiği, WebSocket desteği olmayan bir şeffaf vekil sunucu üzerinden akıyorsa, bağlantı muhtemelen başarısız olacaktır.
Eğer şifreli WebSocket bağlantısı kullanılıyorsa, Güvenli WebSocket bağlantısında Transport Layer Security (TLS) kullanılması, tarayıcı bir vekil sunucu kullanacak şekilde yapılandırıldığında, HTTP CONNECT komutunun çalıştırılmasını sağlamaktadır. Bu, Güvenli WebSocket istemcisi ile WebSocket sunucusu arasında HTTP vekil sunucusu aracılığıyla düşük seviye birebir TCP iletişimini sağlayan bir tünel kurmaktadır. Şeffaf vekil sunucularda, tarayıcı vekil sunucunun varlığından habersizdir ve hiçbir HTTP CONNECT paketi yollanmamaktadır. Ancak, kablodaki trafik şifreli olduğu için, aradaki şeffaf vekil sunucular şifreli trafiğin geçmesine izin verebilmektedir. Bu yüzden, Güvenli WebSocket kullanıldığında, WebSocket bağlantısının başarılı olma ihtimali artmaktadır. Şifrelemenin olması kaynak kullanımı açısından bir miktar yük oluşturacaktır, fakat güvenli bir tünel üzerinden geçebileceği için daha yüksek bir başarı oranı sağlamaktadır.
2010 ortalarında verilen bir taslak (hixie-76 versiyonu)ters vekil sunucularla ve ağ geçitleriyle uyumluluğu, başlıklardan sonra 8 byte’dan oluşan bir anahtar eklediği ve bu anahtarı   Content-Length: 8 başlığında belirtmediği için bozmuştur. Bu veri tüm aradaki cihazlar tarafından iletilmeyeceği için protokol başarısızlığına yol açabilmektedir. Bu yüzden, daha yeni taslaklar (örneğin hybi-09) bu problemi çözerek anahtar veriyiSec-WebSocket-Key başlığına koymaktadır.