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 6455 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ış
HTTPden 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 APIsi yerine TCPConnection olarak anılmıştır. Haziran 2008de, 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 2009da, varsayılan olarak WebSocket protokolü standartlarını tamamen uygulayan ilk tarayıcı Google Chrome 4 olmuştur. Sonrasında, Şubat 2010da WebSocket protokolünün geliştirilmesi, W3C ve whatwg IRC grubundan IETye 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 2011de Ian Fette gözetiminde RFC tamamlanmıştır.
Browser implementation
WebSocket protokolünün güvenli bir versiyonu, Firefox 6, Safari 6, Google Chrome 14, Opera 12.10 ve Internet Explorer 10 tarafından uygulanmaktadır. Detaylı bir protokol test raporu bu tarayıcıların spesifik protokol özelliklerine uyumluluğunu listelemektedir.
Protokolün daha eski ve daha az güvenli bir versiyonu, Opera 11, Safari 5 ve iOS 4.2'de bulunan Safari mobil versiyonunda uygulanmıştır. iOS7'deki BlackBerry tarayıcısı WebSocket protokolünü uygulamaktadır. Açıklıklar yüzünden, Firefox 4 ve 5 ile Opera 11 üzerinde devre dışı bırakılmıştır.
Ayrıca, SPDY üzerinde WebSocket protokolünün deneysel bir uygulamasına imkan tanıyan Google Chrome için --enable-websocket-over-spdy komut satırı anahtarı bulunmaktadı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 (HTTPde 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.1
Host: server. example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
Sunucunun cevabı:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-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 HTTPye 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, HTTPye 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ı WebSocketa 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 bytedan 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.