İçeriğe geç
academia.sh

Ders 15 / 16

E-posta Protokolleri

Gönderim ile erişimin ayrımı ve postanın iki adı: teslimi yönlendiren posta zarfı ile kullanıcıya gösterilen başlık ayrı alanlardır, birbirini doğrulamaz, ve aracı zarfa bakar.

İçindekiler

Önceki ders bir işi iki kanala bölen bir protokolü ölçtü: komutlar birinde, baytlar öbüründe, ve aracı ikisini eşleştiremediğinde bir kararı yanlış aldı. Kayıp gizlemekten değil bölünmeden geliyordu.

Posta bir adım ileri gider. Burada bölünen şey kanal değil addır. Bir postanın nereye teslim edileceğini söyleyen alanlar ile kullanıcıya kimden geldiği gösterilen alanlar aynı iletinin içinde, ayrı iki katmanda durur. Teslimi yönlendiren katman posta zarfıdır ve aracı ona bakar. Kullanıcının ekranda gördüğü ad ise başlıktan gelir ve teslime hiç karışmaz. İkisi birbirini doğrulamaz. Bu dersin sorusu, bu ayrımın neden var olduğu ve hangi denetimin onu kapattığıdır.

  • DG46. Kurgu M04/K03’ün ortak kurgusudur: istasyon.ornek ölçüm istasyonu uyarı postaları üretir, ornek.test ve liste.ornek alan adları alıcı ve liste tarafını temsil eder, arada uygulamayı bilmeyen bir aracı durur.
  • DG47. Posta zarfı ile taşıma zarfı ayrı iki kavramdır. Taşıma zarfı, güvenli taşıma konusunda kurulan ve aracıyı kör eden katmandır. Posta zarfı ise protokolün kendi alanlarıdır; hiçbir şeyi gizlemez, yalnız teslimi yönlendirir. Bu derste ölçülen posta zarfıdır.
  • DG48. Ölçülen küme 40 ileti ve ileti başına 5 karardır: teslim_yolu_var, gonderen_yetkili, adlar_hizali, gizli_alici_var, gosterilen_ad_dogrulanmis. Toplam 200 karar; ölçülebilen en küçük fark 1/200=0,00501/200 = 0{,}0050.
  • DG49. İletiler dört türdendir: doğrudan, vekil (istasyon adına başka bir alanın gönderdiği), liste, ve iletilen. Dördü de meşrudur; kurguda hiçbir sahte ileti yoktur. Ölçünün amacı sahteciliği saymak değil, meşru çeşitliliğin denetimlere ne yaptığını saymaktır.
  • DG50. Alan adı politikası yayınlamak alanın seçimidir: istasyon.ornek ve liste.ornek yayınlar, ornek.test yayınlamaz. Kâhin — gerçeğin kendisi — kurguyu biz ürettiğimiz için bilinir ve rejimden rejime değişmez.

Gönderim ve Erişim

Posta iki ayrı protokol ailesiyle taşınır ve ikisi zıt yönlere bakar.

Gönderim (submission) iletiyi istemciden alıp alıcının posta deposuna kadar iten yoldur. SMTP bu yolun belirtimidir; aynı belirtim hem istemciden ilk konağa gönderimde hem konaklar arasında aktarımda kullanılır. Erişim (retrieval) ise depoya ulaşmış iletiyi kullanıcının çektiği yoldur; IMAP ile POP3 bu yönün belirtimleridir. IMAP iletiyi sunucuda tutar ve kullanıcı klasör yapısıyla birlikte çok yerden aynı görünümü okur; POP3 iletiyi indirip depodan düşürme üzerine kuruludur.

Ayrımın bu ders için sonucu şudur: aracı yalnız gönderim yolunda durur. Erişim yolunda kullanıcının kendi deposuyla arasında bir karar verme yeri yoktur. Gönderim sırasında alınmayan bir karar, erişim sırasında geri alınamaz — ileti çoktan teslim edilmiştir. Turun borcu burada bir posta kutusuna yazılmış olur.

İki erişim belirtiminin tur davranışı da ayrışır. POP3’te durum istemcidedir: oturum içindeki ileti numaraları o oturuma özgüdür ve iletiler indirilip depodan düşürüldüğünde ikinci bir istemci aynı kutuyu göremez. IMAP’te durum sunucudadır; her iletinin oturumdan oturuma değişmeyen bir kalıcı numarası ve okundu, yanıtlandı, silindi gibi imleri vardır, bu yüzden birden çok istemci aynı görünümü paylaşır. Bedeli şudur: paylaşılan durumun her sorgusu bir gidiş–dönüştür. Önceki üç dersin yoklama sorusu erişim tarafında da aynen çıkar ve IMAP’in yanıtı aynı ailedendir — IDLE komutu bağlantıyı açık tutar, sunucu değişikliği kendisi bildirir ve istemci boşuna tur atmaz. Kısa yoklamanın karar başına tur maliyeti burada da geçerlidir.

Posta Zarfı ile Başlık

Gönderim konuşmasının iki katmanı aşağıda yan yana duruyor.

gönderim konuşması — istemci ile teslim eden konak arasında

  ->  EHLO istasyon.ornek
  <-  250 merhaba
  ->  MAIL FROM:<[email protected]>      posta zarfı: dönüş yolu
  <-  250 gönderen kabul edildi
  ->  RCPT TO:<[email protected]>            posta zarfı: teslim adresi
  <-  250 alıcı kabul edildi
  ->  RCPT TO:<[email protected]>            posta zarfı: ikinci alıcı
  <-  250 alıcı kabul edildi
  ->  DATA
  <-  354 iletiyi gönderin, sonunda tek nokta

      From: Kuzey Yamac Istasyonu <[email protected]>   başlık
      To: Nobet <[email protected]>                         başlık
      Subject: eşik aşıldı                                 başlık
      Date: ...

      Ölçüm eşiği aştı.
      .
  <-  250 ileti kuyruğa alındı

Bu döküm çalıştırılmadı; öğretilen biçimdir. Üç nokta okunmalıdır.

Birincisi, teslim yalnız RCPT TO satırlarına bakılarak yapılır. To: başlığı teslime hiç karışmaz; onu okumayan bir teslim yine de doğru çalışır. İkincisi, yukarıdaki iletide iki zarf alıcısı var ama başlıkta bir tane yazıyor — [email protected] başlığa hiç girmemiştir. Gizli kopya bir başlık alanı değildir, bir zarf alıcısıdır; başlıkta ona karşılık gelen bir satır yoktur ve olmaması gerekir. Üçüncüsü, MAIL FROM ile From: ayrı iki adrestir. Birincisi teslim edilemeyen iletinin geri döneceği yerdir, ikincisi kullanıcıya gösterilecek addır. Bir liste iletisinde dönüş yolu listeye, gösterilen ad özgün yazara aittir; ikisinin farklı olması protokolün kusuru değil, tasarımıdır.

Bir dördüncü nokta bu kursta ilk kez ortaya çıkıyor: aracı burada yalnız okumaz, yazar da. İletiyi devralan her konak başlığın en üstüne bir Received: satırı ekler ve satırlar birikerek iletinin geçtiği yolu ters sırada kaydeder. Bu, kurs boyunca aracının iletiye kendi bildirimini koyduğu tek yerdir. Kaydın bir sınırı var ve ders için önemli: Received: satırları iletiyi taşıyan konakların kendi beyanıdır ve alt sıradaki satırları hiçbir şey doğrulamaz. Bir izin var olması, izin doğru olmasını gerektirmez — kursun dördüncü okuması burada da aynen geçerlidir.

Ölçüm

Aracı üç görünürlük düzeyinde ölçülüyor: yalnız posta zarfını görürken, başlıkları da okurken, ve başlığı imzalayan anahtarı da almışken.

TOHUM = 20260809
TURLER = ["dogrudan", "dogrudan", "dogrudan", "vekil",
          "liste", "iletilen", "dogrudan"]
ZARF_ALANI = {"dogrudan": "istasyon.ornek", "vekil": "ornek.test",
              "liste": "liste.ornek", "iletilen": "ornek.test"}
POLITIKA = {"istasyon.ornek": True, "liste.ornek": True, "ornek.test": False}
KARARLAR = ("teslim_yolu_var", "gonderen_yetkili", "adlar_hizali",
            "gizli_alici_var", "gosterilen_ad_dogrulanmis")


def uretec(tohum):
    d = tohum % 2147483646 + 1

    def r(n):
        nonlocal d
        d = (d * 48271) % 2147483647
        return d % n
    return r


def iletiler(sayi=40, tohum=TOHUM):
    r, liste = uretec(tohum), []
    for i in range(sayi):
        tur = TURLER[r(7)]
        zarf_alici = 1 + r(5)
        liste.append({
            "no": i + 1, "tur": tur,
            "zarf_alani": ZARF_ALANI[tur],
            "baslik_alani": "istasyon.ornek",
            "zarf_alici": zarf_alici,
            "baslik_alici": zarf_alici - 1 if r(5) == 0 else zarf_alici,
            "iletildi": tur in ("liste", "iletilen"),
            "kaynak_izinli": r(9) != 0,     # kâhin: çıkış konağı gerçekten yetkili
            "imza_var": r(7) != 0,
            "degistirildi": r(9) == 0,      # kâhin: ileti yolda değiştirildi
            "yol_var": r(11) != 0,
        })
    return liste


def kahin(m):
    return {
        "teslim_yolu_var": m["yol_var"],
        "gonderen_yetkili": m["kaynak_izinli"],
        "adlar_hizali": m["zarf_alani"] == m["baslik_alani"],
        "gizli_alici_var": m["zarf_alici"] > m["baslik_alici"],
        "gosterilen_ad_dogrulanmis": m["imza_var"] and not m["degistirildi"],
    }


def ileti(m, gorunur):
    tam = {
        "zarf_alani": m["zarf_alani"], "zarf_alici": m["zarf_alici"],
        "yol_var": m["yol_var"],
        "teslim_eden_izinli": m["kaynak_izinli"] and not m["iletildi"],
        "baslik_alani": m["baslik_alani"], "baslik_alici": m["baslik_alici"],
        "imza_var": m["imza_var"],
        "imza_saglam": m["imza_var"] and not m["degistirildi"],
    }
    return {k: v for k, v in tam.items() if k in gorunur}


def araci(i):
    k = {}
    if "yol_var" in i:
        k["teslim_yolu_var"] = i["yol_var"]
    if "zarf_alani" in i and POLITIKA[i["zarf_alani"]]:
        k["gonderen_yetkili"] = i["teslim_eden_izinli"]
    if "zarf_alani" in i and "baslik_alani" in i:
        k["adlar_hizali"] = i["zarf_alani"] == i["baslik_alani"]
    if "zarf_alici" in i and "baslik_alici" in i:
        k["gizli_alici_var"] = i["zarf_alici"] > i["baslik_alici"]
    if "imza_saglam" in i:
        k["gosterilen_ad_dogrulanmis"] = i["imza_saglam"]
    return k


ZARF = ("zarf_alani", "zarf_alici", "yol_var", "teslim_eden_izinli")
BASLIK = ("baslik_alani", "baslik_alici", "imza_var")
GORUNUR = {
    "zarf": ZARF,
    "zarf+başlık": ZARF + BASLIK,
    "zarf+başlık+anahtar": ZARF + BASLIK + ("imza_saglam",),
}


def olc(ad):
    dogru = yanlis = alinamayan = tur = 0
    dokum = {}
    for m in iletiler():
        gercek, verilen = kahin(m), araci(ileti(m, GORUNUR[ad]))
        eksik = False
        for karar in KARARLAR:
            if karar not in verilen:
                alinamayan += 1
                eksik = True
            elif verilen[karar] == gercek[karar]:
                dogru += 1
            else:
                yanlis += 1
                dokum[karar] = dokum.get(karar, 0) + 1
        tur += 1 if eksik else 0
    return dogru, yanlis, alinamayan, tur, dokum


print(f"{'görünürlük':<20s} {'doğru':>6s} {'yanlış':>7s} {'alınamayan':>11s} "
      f"{'tur':>4s}  yanlış dökümü")
for ad in GORUNUR:
    d, y, e, t, dk = olc(ad)
    print(f"{ad:<20s} {d:6d} {y:7d} {e:11d} {t:4d}  {dk}")

m = iletiler()
hizasiz = [x for x in m if x["zarf_alani"] != x["baslik_alani"]]
print()
print(f"ileti {len(m)}, karar {len(m) * len(KARARLAR)}, hizasız {len(hizasiz)}, "
      f"hizasızların hepsi meşru "
      f"{all(x['tur'] in ('vekil', 'liste', 'iletilen') for x in hizasiz)}")
print(f"iletilen {sum(x['iletildi'] for x in m)}, "
      f"politikası yayınlı alandan gelen {sum(POLITIKA[x['zarf_alani']] for x in m)}, "
      f"gizli alıcı taşıyan {sum(x['zarf_alici'] > x['baslik_alici'] for x in m)}")
saglam = sum(x["imza_var"] and not x["degistirildi"] for x in hizasiz)
print(f"hizasız olup imzası sağlam {saglam}, "
      f"imzasız {sum(not x['imza_var'] for x in hizasiz)}, "
      f"yolda değişmiş {sum(x['imza_var'] and x['degistirildi'] for x in hizasiz)}")
görünürlük            doğru  yanlış  alınamayan  tur  yanlış dökümü
zarf                     60       7         133   40  {'gonderen_yetkili': 7}
zarf+başlık             140       7          53   40  {'gonderen_yetkili': 7}
zarf+başlık+anahtar     180       7          13   13  {'gonderen_yetkili': 7}

ileti 40, karar 200, hizasız 20, hizasızların hepsi meşru True
iletilen 14, politikası yayınlı alandan gelen 27, gizli alıcı taşıyan 8
hizasız olup imzası sağlam 17, imzasız 2, yolda değişmiş 1

Sayıların Okunması

Zarf teslimi yönetir, başlık hakkında hiçbir şey söylemez. Yalnız posta zarfını gören aracı 200 kararın 60’ını alıyor; kalan 133’ünü hiç alamıyor ve 40 iletinin kırkında da bir tur borçlanıyor. Aldığı kararlar teslimle ilgili olanlardır — yol var mı, gönderen yetkili mi. Kullanıcının ekranda ne göreceği bu görünürlükten hiç çıkarılamaz. Ayrımın en temiz kanıtı budur: teslim için gereken bilgi ile gösterim için gereken bilgi ayrı kümelerdir.

Başlığı okumak 80 karar kazandırır ve tek bir tur eklemez. Başlıklar aynı bağlantıda, DATA‘dan sonra zaten akıyor; aracı onları okuduğunda doğru karar 60’tan 140’a çıkıyor. Bu, kursun ikinci iddiasının tersine bakan yüzüdür: alan eklemek karar kazandırmaz, ama zaten taşınan bir alanı okumak kazandırabilir. Kazandıran şey baytın kendisi değil, adı ve anlamı sabitlenmiş bir alan olmasıdır.

Hizasızlık tek başına hiçbir şey söylemez. 40 iletinin 20’sinde zarf alanı ile başlık alanı farklıdır ve kurguda yirmisi de meşrudur: vekil gönderim, liste ve iletilen posta. Yalnız hizasızlığa bakarak eleyen bir kural bu kümenin yarısını eler. Aracı adlar_hizali kararını her seferinde doğru veriyor — ama doğru cevabını verdiği soru, cevabı aranan soru değildir.

Yol denetimi iletmeyle bozulur. Yedi karar yanlış çıkıyor ve yedisi de aynı kaynaktan: yol tabanlı denetim, iletiyi teslim eden konağa bakar. Liste iletilerinde teslim eden konak listenin konağıdır, oysa ileti gerçekten yetkili bir kaynaktan çıkmıştır. Aracı “yetkili değil” der ve yanılır. Politikasını yayınlamayan alandan gelen 13 iletide ise karar hiç alınamaz — eksik bildirimin bu derste ödettiği bedel yanlış değil, boşluktur.

İmza turu bir kez ödenir. Başlığı kapsayan imzanın doğrulanması bir anahtar alma turu ister; bu turdan sonra aracı 180 doğru karara çıkıyor ve tur borçlusu ileti sayısı 40’tan 13’e düşüyor. Anahtar ileti başına değil alan adı başına alınır: bu kümede tek bir başlık alanı olduğu için tur bir kez ödenir ve kırk iletinin tamamına yeter. Kalan 13, politikası yayınlanmamış alandan gelenlerdir; onların borcu imzayla değil, yayınla kapanır.

Ayrım Neden Var, Hangi Denetim Onu Kapatır

Zarf ile başlığın ayrı olması sonradan eklenmiş bir gevşeklik değil, teslimin çalışması için gereken bir ayrımdır. Teslim edilemeyen bir iletinin nereye döneceği, gösterilecek addan bağımsız olmalıdır; yoksa bir liste iletisinin geri dönüşü özgün yazarın kutusuna düşer. Bir liste ya da iletme, alıcı kümesini değiştirmeden iletiyi başka bir yola sokabilmelidir. Gizli kopya, başlığa yazılmadan teslim edilebilmelidir. Üçü de zarfın başlıktan ayrı olmasını gerektirir.

Ayrımın bedeli, başlıkta yazan adı hiçbir şeyin doğrulamamasıdır. Ölçümdeki 20 hizasız ileti bunun meşru yüzüdür; aynı yapı, gösterilen adın taşıdığı güveni protokolün kendisinden almaz. Kapatan denetim üç parçadır ve üçü ayrı sorulara yanıt verir:

  • Yayınlanmış gönderen politikası (SPF) zarf alanının hangi konaklardan posta çıkacağını bildirir. Yol tabanlıdır, bu yüzden iletmeyle bozulur — ölçümdeki 7 yanlışın tamamı buradan gelir. Yayınlanmamışsa karar alınamaz: 13 ileti.
  • Başlığı kapsayan imza (DKIM) gösterilen adı imzalayan alanla bağlar. İletmeye dayanır, çünkü yola değil içeriğe bakar; ölçümde 20 hizasız iletinin 17’si sağlam imza taşıyor. İçerik yolda değiştirilirse bozulur: 1 ileti. Bedeli bir anahtar alma turudur.
  • Hizalama ve raporlama politikası (DMARC) ilk ikisinin sonucunu başlık alanıyla hizalar ve alan sahibinin ne yapılmasını istediğini bildirir. Kendi başına bir kanıt üretmez; iki denetimin çıktısını tek bir karara bağlar.

Daraltma. Sayılan yüzeylerin her birinin kapanma yönü aynıdır: kararı yoldan içeriğe taşımak ve sonucu başlık alanıyla hizalamak. Yol tabanlı denetim tek başına iletmeyi yanlışlar; içerik tabanlı imza tek başına gösterilen adla hizalanmayabilir; hizalama politikası tek başına doğrulayacak bir şey üretmez. Üçü birlikte, aracının gidiş–dönüşsüz aldığı kararların sayısını değil doğruluğunu artırır ve bunun karşılığında alan adı başına bir tur ister. Bu dersin ölçüsü de zaten budur: aracı hizasızlığı zaten görüyordu, eksik olan görmek değil, gördüğünü bağlayacak bir bildirimdi.

Özet

  • Posta iki yönlü iki aileyle taşınır: gönderim iletiyi depoya iter (SMTP), erişim depodan çeker (IMAP, POP3); aracı yalnız gönderim yolunda durur ve orada alınmayan karar sonradan alınamaz.
  • Teslimi posta zarfı yönetir (MAIL FROM, RCPT TO), kullanıcıya gösterilen adı başlık taşır (From:, To:); ikisi ayrı alanlardır, birbirini doğrulamaz ve gizli kopya yalnız zarfta bulunur.
  • Yalnız zarfı gören aracı 200 kararın 60’ını alıyor ve 40 tur borçlanıyor; başlıkları da okumak hiçbir tur eklemeden doğru karar sayısını 140’a çıkarıyor.
  • 40 iletinin 20’sinde adlar hizasızdır ve yirmisi de meşrudur; yalnız hizasızlığa bakan bir kural kümenin yarısını eler — aracı doğru cevabı, sorulmayan soruya vermektedir.
  • Yol tabanlı gönderen politikası iletmeyle bozulur ve 7 kararı yanlışlar, yayınlanmadığı 13 iletide hiç karar üretmez; başlığı kapsayan imza hizasız 20 iletinin 17’sini bağlar ve bedeli alan adı başına tek bir turdur.

Sonraki Adım

Bu iki derste ölçülen şey, aracının bir iletiden ne okuyabildiğiydi. Okumanın da bir önkoşulu var: iletideki zaman damgalarının aynı saati göstermesi. Sonraki ders saati eşitleyen protokolü ölçer ve bir tur boyunca peşinden gitmediğimiz bir varsayımı açar — gidiş ile dönüş gecikmesinin eşit olduğu varsayımını. Eşit değilse saat sapması doğrudan bu farktan doğar ve protokolün elinde farkı görecek hiçbir alan yoktur. Aynı ders, aygıtları yoklayan ile aygıtların bildirdiği iki yönetim modelini tur ve karar dengesiyle karşılaştırarak kursu kapatır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat