Browser’ı açıp serhanbahar.com yazıp enter’a bastığımızda neler olur?

serhanbahar.com’a gitmeden önce klavyemizde “s” tuşuna bastığımızda tarayıcımız otomatik tamamlama işlevini devreye sokar. Tarayıcının algoritmasına ve gizli modda olup olmamamıza bağlı olarak açılır menü ile “S” harfi geçen seçenekler bize sunulacaktır. Otomatik tamamlamadan gelen serhanbahar.com seçildiğinde (daha önce girdiğim için otomatik tamamlamada öneri olarak çıkmaktadır) ve enter tuşuna basıldığında aşağıdaki işlemler gerçekleşmektedir.

USB Klavyede:

  • Klavyenin USB devresi, bilgisayarın USB denetleyicisininin 1 numaralı pin’i üzerinden sağlanan 5V’luk besleme ile beslenmektedir.
  • Bir “keycode” üretilir ve dahili klavye devre belleği tarafından “endpoint” adı verilen bir kayıt defterinde saklanır.
  • Bilgisayarın USB deneyleyicisi her 10 ms’de bir “endpoint”i çağırır ve orada depolanan keycode değerini alır.
  • Bu alınan değer low-level USB protokolünü izleyen bir veya daha fazla USB paketine dönüştürülmek üzere USB SIE’ye gitmektedir.
  • Paketler seri sinyal olarak gönderilir ve bu sinyal daha sonra bilgisayarın USB kontrol cihazında kodu çözümlenerek HID sürücüsü tarafından yorumlanır. Ve son olarak anahtarın değeri işletim sisteminin donanım soyutlama katmanına aktarılır.

Dokunmatik (Sanal) Klavyelerde:

  • Kullanıcı parmağını ekrandaki sanal klavyedeki bir harfe dokundurduğunda parmak ile ekran arasında çok küçük miktarda bir akım aktarımı yaşanır. Bu sayede dokunan noktada voltaj düşüşü yaratılarak ekran denetleyicisine ekranın neresine basıldığına dair bir koordinat belirtilebilecek proses başlatılır.
  • Yukarıdaki işlemden sonra mobil işletim sistemi bu olayı arayüze aktadır. Bu aşamadan sonra sanal klavye artık “tuşa basıldı” mesajını OS’a iletebilir.

Peki Windows’ta arka planda neler gerçekleşiyor bir de ona bakalım.

Uygulamaya bir VM_KEYDOWN mesajı gönderilir.

HID aktarımı, key down olayını HID ​​kullanımını bir tarama koduna dönüştüren KBDHID.sys sürücüsüne iletir. Bu durumda, tarama kodu VK_RETURN (0x0D)’dir. KBDHID.sys sürücüsü, KBDCLASS.sys (klavye sınıfı sürücüsü) ile arabirim oluşturur. Bu sürücü, tüm klavye ve tuş takımı girişini güvenli bir şekilde tutmaktan sorumludur. Daha sonra Win32K.sys’ye çağrı yapar ve bunların hepsi Kernel üzerinden gerçekleşir.

Win32K.sys, GetForegroundWindow() API aracılığıyla hangi pencerenin etkin pencere olduğunu belirler. Windows “message pump” sonra SendMessage’ı (hWnd, WM_KEYDOWN, VK_RETURN, lParam) çağırır. lParam, tuşa basma hakkında daha fazla bilgi gösteren bir bitmask’dır.

Windows SendMessage API, iletiyi hWnd için bir kuyruğa ekleyen basit bir işlevdir. Daha sonra sıradaki her iletiyi işlemek için hWnd’ye atanan ana ileti işleme işlevi çağrılır.

Etkin olan pencere (hWnd) aslında bir düzenleme kontrolüdür ve bu durumda WindowProc, WM_KEYDOWN iletileri için bir ileti işleyicisine sahiptir. Bu kod SendMessage’a (wParam) iletilen 3. parametrenin içine bakar ve VK_RETURN olduğundan, kullanıcının ENTER tuşuna bastığını bilir.

OS X’te durumlar neler bir de ona bakalım.

Sürücü, sinyali OS X WindowServer işlemine geçirilen bir anahtar koda çevirir. Sonuç olarak, WindowServer bir olay kuyruğuna yerleştirildiği Mach portları üzerinden uygun (örneğin aktif veya dinleyen) uygulamalara bir olay gönderir.

Olaylar daha sonra mach_ipc_dispatch işlevini çağıran yeterli ayrıcalıklara sahip iş parçacıkları tarafından bu sırada okunabilir.

GNU/Linux’ta ise:

Bir grafik X sunucusu kullanıldığında, X, tuşa basılması için genel olay sürücüsü evdev’i kullanacaktır. X sunucuya özgü tuş haritaları ve kurallarla, anahtar kodların tarama kodlarıyla yeniden eşlenmesi yapılır. Basılan tuşun tarama kodu eşlemesi tamamlandığında, X sunucusu karakteri pencere yöneticisine (DWM, metacity, i3, vb.) gönderir, böylece pencere yöneticisi karakteri odaklanan pencereye gönderir. Karakteri alan pencerenin grafik API’si, uygun odaklanmış alanda uygun font sembolünü basar.

Bu aşamada tarayıcının yazılan linki parse etmesi gerekmektedir.

Tarayıcıya gitmek istediğimiz yeri girerken herhangi bir protokol veya var olan bir domain vermez isek genellikle tarayıcılar adres çubuğuna yazdığımız metni varsayılan arama motorunda arayarak sonuç vermeye çalışır. Şu anki senaryoda biz geçerli bir domain vermiş olduk. Ve gerçekten serhanbahar.com diye bir web sitesi var. (Bu yazıyı nerede yayınlardım yoksa)

Günümüz tarayıcılarından hardcoded olarak bir liste bulunmaktadır. Bu listenin içerisinde “ne olursa olsun HTTPS olarak bağlan” denen web siteleri yer almaktadır. Buna HSTS denmektedir. Tarayıcı önceden hazırlanmış olan bu HSTS listesini kontrol eder. Eğer gideceğimiz domain bu listede var ise tarayıcı tüm istekleri HTTP yerine HTTPS olarak yapar. Gideceğimiz domain HSTS listesinde yoksa tarayıcı domaine isteği HTTP olarak gönderir. Bunun karşılığında web sitesinin SSL’i var ise web sitesin’den “bana isteklerini HTTPS olarak gönder” karşılığını alarak trafik yine HTTPS’e dönmektedir.

Bu aşamadan sonra DNS Lookup başlamaktadır. Tarayıcı öncelikle alan adının ön belleğinde olup olmadığını kontrol eder. Eğer domain ön belleğinde yoksa arama yapmak için bir kütüphane fonksiyonunu çağırır. Bu kütüphane fonksiyonu işletim sistemine göre değişir. Bu fonksiyona örnek vermemiz gerekirse gethostbyname’i verebiliriz.

Domain ön belleğe alınmamışsa network stack’te yapılandırılmış olan DNS sunucusuna bir istek yapılır. DNS sunucusu aynı subnet’te ise ARP adımları başlar. Eğer değilse Default Gateway IP’si için ARP işlemi başlatılır.

Broadcast ARP yayını yapılabilmesi için hem hedef IP adresine hem de kullanılacak interface’in MAC adresine ihtiyaç vardır. ARP önbelleği kontrol eder ve hedef IP için daha önce işlem yapılıp yapılmadığına bakar. Eğer yapıldıysa Hedef IP = MAC sonucuna varır.

Eğer ARP tablosunda bununla ilgili bir veri yoksa, Route tablosuna bakılarak hedef ip adresinin subnet’te olup olmadığına karar verilir. Eğer Route tablosunda istenen veri bulunursa direkt olarak bu subnet ile devam edilir. Aksi durumda Default Gateway’in subnetinin interface’i kullanılır.

Bundan sonraki aşamada önemli olan şey hedefe giderken orayla nasıl bağlantılı olduğumuzdur.

Eğer Router’a direkt olarak bağlıysak, Router isteğimize ARP yanıtı verir.

Eğer bir Hub’a bağlıysak, Hub ARP isteğini diğer tüm portlardan yayınlar. Router ise ARP yanıtı döner.

Eğer bir switch üzerinden gidiyorsak, switch MAC tablosunu kontrol eder. Eğer tabloda istenen MAC yoksa ARP talebi diğer tüm portlara gönderilir. Tabloda aranan MAC adresi varsa ona gidilir.

Tarayıcı hedef sunucunun IP adresini aldıktan sonra verilen port numarasını da URL’den alır. (Örneğin http bağlantısı kuruluyorsa port 80’e https bağlantısı kuruluyorsa port 443’e gidilir)

Port numarası url’den alındıktan sonra socket adlı sistem kitaplığı fonksiyonuna bir çağrı yapılarak TCP socket akışı istenir.

Bu istek önce bir TCP segmentinin craft edildiği Taşıma katmanına iletilir. Hedef port header’a eklenir ve kaynak portu kernel’in dinamik port aralığından seçilerek işleme devam edilir.

Bu aşamadan sonra segment ek bir IP başlığının ekleneceği Ağ katmanına gönderilir. Hedef sunucumuzun yanı sıra geçerli makinenin de IP adresi yeni bir paket oluşturulmak üzere eklenir.

Paketin bir sonraki durağı bağlantı katmanıdır. Makinenin MAC adresini içeren bir frame header’a eklenir. Bu aşamadan sonra paket transfer edilmeye hazır hale gelmiştir.

53 numaralı port açılarak UDP isteği gönderilir, eğer yanıt boyutu çok yüksekse TCP kullanılır.

Artık bağlantı aşamasına geçilmektedir. İstemci bir ISN seçer ve ISN’i ayarladığını sunucuya belirtmek için SYN biti ayarlanmış bir paket gönderir. Sunucu SYN paketini alır ve kabul edilebilir modda ise sunucu kendi ISN numarasını seçerek SYN paketini yarlar. Sunucu, istemciden gelen ISN+1’i ACK alanına kopyalayarak ilk paketin alındığını bildirmek için ACK bayrağına ekler.

İstemci bir paket göndererek bağlantıyı kabul eder. Kendi sıra numarasını arttırır ve alıcı onay numarasını da arttırarak ACK alanını ayarlar. Biraz daha açmamız gerekirse bir taraf N bayt veri gönderdiğinde, SEQ değeri bu sayı kadar arttırılır. Diğer taraf bu paket veya paketleri kabul ettiğinde diğerinden almış olduğu son diziye eşit ACK değerine sahip bir ACK paketi gönderilir. Daha sonra bağlantının kapatılması için bir FIN paketi gönderilir. Diğer taraf FIN paketini ACK paketine çevirir ve kendi FIN paketini gönderir.

Gitmek istediğimiz sayfa SSL kullandığı için TLS handshake işlemi gerçekleşecektir.

İstemci, TLS sürümü, şifreleme algoritmalarının bir listesi ve mevcut sıkıştırma yöntemlerini içeren bir ClientHello mesajı gönderir. Bunun karşılığında sunucu, istemciye ServerHello mesajı ile cevap verir. Bu ServerHello mesajının içinde TLS sürümü, seçilen şifre, seçilen sıkıştırma yöntemleri ve sunucunun sertifka yetkilisi tarafından imzalanan genel sertifikası bulunmaktadır. (CA)

Sertifika içinde kalan sürecin şifrelenebilmesi için client tarafından kullanılabilecek ortak anahtarı içerir. Taa ki simetrik anahtar üzerinde anlaşılana kadar.

İstemci, sunucudan gelen dijital sertifikayı güvenilir CA listesine göre doğrular. CA’ya dayalı bir güven oluşturulursa istemci, sunucuya bir dizi rastgele bayt oluşturur ve bunu sunucunun ortak anahtarını kullanarak şifreler. Bu rastgele bayt dizisi simetrik anahtarı da belirlenmek için kullanılabilir. (Bu bende acaba burada bir açık bulunabilir mi hissiyatı da oluşturmuyor değil.)

Sunucu, özel anahtarını kullanarak gelen random baytların şifresini çözer ve bu baytları simetrik ana anahtarının kendi kopyasını oluşturmak için kullanır.

İstemci, sunucuya bitmiş bir mesaj gönderir ve bu noktaya kadar olan hash değerini simetrik anahtar ile şifreler.

Daha sonra sunucu kendi hash’ini oluşturur ve eşleşmenin doğrulanması için istemci tarafından gelen hash’in şifresini çözer. Bu noktada sunucu (eğer var ise) istemciye kendi Finished mesajını gönderir ve simetrik anahtar ile şifreler.

Artık bu andan itibaren TLS oturumu, kabul edilen simetrik anahtarlarla şifrelenmiş uygulama verilerini iletebilir.

Kullanılan web tarayıcısı Google tarafından yazılmışsa, tarayıcı sayfayı almak için bir HTTP isteği göndermek yerine, sunucudan HTTP ile SPDY protokolüne bir “upgrade” denemek ve negotiate etmek için bir istek gönderir.

Ayrıca istemci http protokolünü kullanıyor ve SPDY’yi desteklemiyorsa aşağıdaki gibi bir istek gönderilir.

GET / HTTP/1.1
Host: serhanbahar.com
Connection: close
[other headers]
Other headers kısmı, HTTP’ye göre formatlanmış key-value çiftini ifade eder.

HTTP/1.1 connection close ile istemcinin yanıtının tamamlandıktan sonra bağlantının kapanacağını belirtir. Kalıcı bağlantıları destelemeyen HTTP/1.1 her mesajda close seçeneğini içermek zorundadır.

İstek ve header gönderildikten sonra, tarayıcı sunucunun isteğinin içeriğinin yapıldığını belirten boş bir tek satır gösterir.

Sonuç olarak sunucu isteğin durumunu belirten bir yanıt kodu verir. Örneğin 200 başarılı gibi.

Daha sonra HTTPD isteği alır. Sunucu aşağıdaki parametrelere göre isteği ayırır.

(GET, HEAD, POST, PUT, PATCH, DELETE, CONNECT, OPTIONS, TRACE)

Eğer doğrudan adres çubuğuna URL girerek siteye gittiysek bu istek GET olacaktır.

Arka planda tarayıcı HTML, CSS ve Js kodlarını parse eder. Tarayıcının görevi sizin gitmek istediğiniz sayfanın teknolojisini yorumlamaktır.(ilk cümlemizi hatırlayın) Daha sonra bu yorumları tarayıcı penceresinde göstermektir.

Tarayıcının HTML dosyalarını yorumlama ve görüntüleme biçimi W3C tarafından belirlenmiştir. Browser’larda birçok kullanıcı arayüzü bulunmaktadır. Örneğin URI eklenmesi için adres çubuğu, ileri geri tuşları, sık kullanılan sayfalar, yer imi seçenekleri, yenileme ve durdur tuşları, ana sayfa tuşu vs gibi.

Bu kısa ek bilgiden sonra devam edelim. Bu aşamada HTML parse işlemi başlar. HTML standart şekilde yukarıdan aşağıya ve aşağıdan yukarıya parser’lar kullanılarak parse edilemez. Bu nedenle browserlar HTML parse edebilmek için özel bir parser kullanır.

HTML parse işlemi bittikten sonra tarayıcı sayfaya bağlı olan external resource’ları çekmeye başlar, örneğin CSS, images, JS dosyaları gibi.

HTML sayfalarında hiçbir zaman Invalid Syntax hatası görmeyiz çünkü tarayıcılar geçersiz olan içerikleri düzeltir ve sürece devam eder.

Daha sonra CSS yorumlaması gerçekleştirilir. Her bir CSS dosyası StyleSheet nesnesine ayrıştırılır. CSS parser’ları HTML parser’ının aksine yukardan aşağıya ve aşağıdan yukarı doğru olabilir.

Artık bu aşamadan sonra da sayfanın render edilmesi işlemi başlar. Render işlemi başarılı olarak tamamlandıktan sonra eğer varsa zamanlama mekanizmaları veya kullanıcı etkileşimleri sonucu ortaya çıkan etkileşimleri için Js kodları çalıştırılabilmektedir.

Bu yazı bir çeviri/yorumlama niteliğindedir. Daha detaylı bilgi için kaynaktaki linki inceleyebilirsiniz.

Kaynak:
  • https://github.com/alex/what-happens-when