---
title: 'Ters Vekil Yapılandırması'
source: 'https://academia.sh/tr/kurslar/sunucu-ve-sertlestirme/ters-vekil-yapilandirmasi'
course: 'Sunucu, Ağ ve Sertleştirme'
language: tr
updated: '2026-08-17T18:09:10+00:00'
license: 'CC BY-SA 4.0'
---

# Ters Vekil Yapılandırması

İki katlı bir vekil zincirinden gerçek istek geçirilerek kaybolan dört bilginin sayılması: istemci adresi, protokol, sunucu adı ve isteğin özgün yolu; her kaybın uygulamada ürettiği yanlış karar (üç üyenin tek kimlikle kaydedilmesi, iç adrese giden mutlak bağlantı, önek soyulunca 404 veren bağ), ikinci atlamanın ilk atlamanın aktarımını silmesi ve aktarılan başlığa güvenmenin açtığı iddia edilen kimlik yüzeyi.

Önceki ders yüzeyi sunucunun dışından saydı: kaç kapı dinliyor, kaç yol sunuluyor, kaç uç açık.
Sayımın tamamı isteğin **varmasıyla** ilgiliydi. Bu ders istek vardıktan sonrasını ölçer.

Ters vekil isteği alır ve arkaya iletir. "İletir" sözcüğü olup biteni gizler: vekil isteği taşımaz,
**yeniden kurar**. İstemcinin açtığı bağlantı vekilde biter; vekil arkaya kendi adına yeni bir
bağlantı açar. Yeni bağlantının öteki ucunda istemci yoktur, vekil vardır. Bağlantının kendisinde
taşınan ne varsa o noktada silinir. Ters vekilin ne olduğu ve uygulamayı üretime alırken nasıl
yapılandırıldığı daha önce ölçülmüştü; burada ölçülen **kaybolan bilgi kalemi** ve o kaybın açtığı
yüzeydir.

Kurgu bölgesel ölçüm ağının önünde iki vekil vardır: dışa bakan bir kenar vekil ve ortamı seçen
bir iç vekil. Saha el terminalleri `/api` önekiyle kenar vekile bağlanır, kenar vekil iç vekile,
iç vekil ölçüm uygulamasına. İki atlama, üç bağlantı.

- **WS7.** Uygulama aktarım başlığındaki **soldaki ilk girdiyi** okur; aktarım zinciri virgülle
  uzadığında okunan değer değişmez. Bu, aktarılan kimliğin yaygın okunma biçimidir.
- **WS8.** Tek makinede bütün istemciler aynı geri döngü adresini paylaşır. Kurgu üye adresi
  kenar vekilde kaynak bağlantı noktası bloğundan türetilir; gerçek bir dağıtımda bu değer
  doğrudan bağlantıdan gelir.
- **WS9.** Kenar vekil ile iç vekil **aynı dosyadır**; aralarındaki bütün fark ayar dizgesindedir.
- **WS10.** Uygulamanın iç özet ucu yalnız `10.9.` önekli adreslerden çağrılabilir; erişim kararı
  **çözülen adrese** dayanır.
- **WS11.** Ölçüm süre ölçmez; istek sayısı, kaynak bağlantı noktası blokları ve beklenen değerler
  koşumdan bağımsız sabitlerdir.

```js
// zincir/uygulama.mjs — olcum uygulamasi. Istegin dort bilgisini once "x-ileti-*" basligindan,
// yoksa baglantinin kendisinden cozer ve her cozumden bir karar uretir.
import { createServer } from "node:http";

const nokta = Number(process.argv[2]);
const IC_AG = "10.9.";                                  // ic ag oneki
const kayit = { adres: new Set(), giren: 0, reddedilen: 0 };

const coz = (i) => ({
  // Aktarim zinciri virgulle uzar; uygulama soldaki ilk girdiyi okur.
  adres: String(i.headers["x-ileti-adres"] ?? i.socket.remoteAddress).split(",")[0].trim(),
  sema: i.headers["x-ileti-sema"] ?? "sifresiz",
  ad: i.headers["x-ileti-ad"] ?? i.headers.host,
  onek: i.headers["x-ileti-onek"] ?? "",
});

if (Number.isInteger(nokta) === false) console.log("kullanim: node zincir/uygulama.mjs <nokta>");
else createServer((istek, yanit) => {
  yanit.sendDate = false;
  const yol = istek.url;
  const c = coz(istek);
  if (yol === "/dokum") {
    yanit.writeHead(200).end(JSON.stringify({ ...kayit, kimlik: kayit.adres.size, adres: [...kayit.adres] }));
    return;
  }
  if (yol === "/ic/ozet") {                             // yalniz ic agdan cagrilmasi gereken uc
    if (c.adres.startsWith(IC_AG)) { kayit.giren += 1; yanit.writeHead(200).end("ic ozet"); }
    else { kayit.reddedilen += 1; yanit.writeHead(403).end("disaridan"); }
    return;
  }
  const parca = yol.split("/");
  if (parca[1] !== "olcum" || parca.length > 4) { yanit.writeHead(404).end("yol yok"); return; }
  if (parca.length === 4 && parca[3] !== "ayrinti") { yanit.writeHead(404).end("yol yok"); return; }
  kayit.adres.add(c.adres);                             // denetim kaydina yazilan kimlik
  yanit.writeHead(200, {
    "x-adres": c.adres, "x-sema": c.sema, "x-ad": c.ad, "x-onek": c.onek || "yok",
    "x-karar": c.sema === "sifreli" ? "sun" : "yonlendir",
    "x-bag": `${c.sema}://${c.ad}${c.onek}${yol}/ayrinti`,
  }).end("olcum");
}).listen(nokta, "127.0.0.1");
```

Vekil altı ayarı bir dizgeden alır. Bir üründe bunların her biri bir yapılandırma satırıdır;
burada bir dizge alanıdır.

```js
// zincir/vekil.mjs — ters vekil. Ayni dosya hem kenar hem ic vekil olarak kosar; davranisi ayar
// dizgesi belirler. Ayar: adres,sema,ad,onekb = acik|kapali; onek=<yol>; temizle=acik;
// zincir=yaz|ekle|koru; harita=acik (yalniz kenar vekilde: baglanti -> kurgu istemci adresi).
import { createServer, request } from "node:http";

const [nokta, hedef, ayarMetni] = [Number(process.argv[2]), Number(process.argv[3]), process.argv[4] ?? ""];
const A = Object.fromEntries(ayarMetni.split(",").filter(Boolean).map((p) => p.split("=")));
// WS8: tek makinede butun istemciler ayni geri dongu adresini paylasir. Kurgu uye adresi kaynak
// baglanti noktasi blogundan turetilir; gercek dagitimda deger dogrudan baglantidan gelir.
const AG = { 512: "203.0.113.11", 513: "203.0.113.12", 514: "203.0.113.13" };
const kaynak = (s) => (A.harita === "acik" ? AG[Math.floor(s.remotePort / 100)] : undefined) ?? s.remoteAddress;

if (Number.isInteger(nokta) === false || Number.isInteger(hedef) === false) {
  console.log("kullanim: node zincir/vekil.mjs <nokta> <hedef> <ayar>");
} else createServer((disIstek, disYanit) => {
  disYanit.sendDate = false;
  const b = { ...disIstek.headers };
  if (A.temizle === "acik") for (const k of Object.keys(b)) if (k.startsWith("x-ileti-")) delete b[k];
  const gelen = b["x-ileti-adres"];
  if (A.adres === "acik") {
    const kendi = kaynak(disIstek.socket);
    if (A.zincir === "koru" && gelen) b["x-ileti-adres"] = gelen;
    else if (A.zincir === "ekle" && gelen) b["x-ileti-adres"] = `${gelen}, ${kendi}`;
    else b["x-ileti-adres"] = kendi;
  }
  if (A.sema === "acik") b["x-ileti-sema"] = "sifreli";
  if (A.ad === "acik") b["x-ileti-ad"] = b["x-ileti-ad"] ?? disIstek.headers.host;
  let yol = disIstek.url;
  if (A.onek) {
    if (yol.startsWith(A.onek) === false) { disYanit.writeHead(404).end("yol yok"); return; }
    yol = yol.slice(A.onek.length) || "/";              // onek soyulur; arka uc onu bilmez
    if (A.onekb === "acik") b["x-ileti-onek"] = A.onek;
  }
  b.host = `127.0.0.1:${hedef}`;                        // istenen ad yukari akisin adiyla degistirilir
  const icIstek = request({ port: hedef, path: yol, method: disIstek.method, headers: b }, (icYanit) => {
    disYanit.writeHead(icYanit.statusCode, icYanit.headers);
    icYanit.pipe(disYanit);
  });
  icIstek.on("error", () => { if (disYanit.headersSent === false) disYanit.writeHead(502).end("kesildi"); });
  disIstek.pipe(icIstek);
}).listen(nokta, "127.0.0.1");
```

İstemci üç üyeyi ayrı kaynak bağlantı noktası bloklarından bağlar, çözülen dört değeri beklenenle
karşılaştırır, uygulamanın ürettiği bağlantıyı izler ve denetim kaydındaki kimlik sayısını okur.

```js
// zincir/istemci.mjs — uc uye ayri kaynak baglanti noktasi bloklarindan zincire baglanir.
// Kullanim: node zincir/istemci.mjs <kenar> <uygulama> <senaryo> <etiket> <kayma>
import { request } from "node:http";

const [kenar, uyg, senaryo, etiket, kayma] =
  [Number(process.argv[2]), Number(process.argv[3]), process.argv[4], process.argv[5] ?? "-", Number(process.argv[6] ?? 0)];
const AD = "olcum.ornek.gecersiz";                      // kurgu ad
const BEKLENEN = { adres: "203.0.113.11", sema: "sifreli", ad: AD, onek: "/api" };

const cagir = ({ yol, kaynak, port = kenar, basliklar = {} }) => new Promise((coz) => {
  const r = request({ port, path: yol, agent: false, localPort: kaynak, headers: { host: AD, ...basliklar } },
    (y) => { let g = ""; y.on("data", (d) => { g += d; }); y.on("end", () => coz({ kod: y.statusCode, b: y.headers, govde: g })); });
  r.on("error", (e) => coz({ kod: 0, b: {}, govde: e.code }));
  r.end();
});

if (senaryo === "kayip") {
  let ilk = null;
  for (let i = 0; i < 3; i += 1) {
    const y = await cagir({ yol: "/api/olcum/7", kaynak: 51200 + i * 100 + kayma * 5 });
    ilk = ilk ?? y;
  }
  const dokum = JSON.parse((await cagir({ yol: "/dokum", port: uyg, kaynak: 51700 + kayma })).govde);
  const bag = ilk.b["x-bag"] ?? "-";
  const yolu = bag.slice(bag.indexOf("://") + 3).replace(/^[^/]*/, "");
  const izlenen = await cagir({ yol: yolu, kaynak: 51800 + kayma });
  const dogru = ["adres", "sema", "ad", "onek"].filter((k) => ilk.b[`x-${k}`] === BEKLENEN[k]).length;
  console.log(`${etiket.padEnd(18)}cozulen ${dogru}/4  kayitta ${dokum.kimlik} kimlik  ` +
    `karar ${String(ilk.b["x-karar"]).padEnd(10)}bag izlendi ${izlenen.kod}`);
  console.log(`${" ".repeat(18)}adres ${String(ilk.b["x-adres"]).padEnd(15)} ad ${String(ilk.b["x-ad"]).padEnd(22)} onek ${ilk.b["x-onek"]}`);
} else if (senaryo === "sahte") {
  let giren = 0;
  for (let i = 0; i < 4; i += 1) {
    const y = await cagir({ yol: "/api/ic/ozet", kaynak: 51500 + i + kayma * 10, basliklar: { "x-ileti-adres": "10.9.0.5" } });
    if (y.kod === 200) giren += 1;
  }
  const dokum = JSON.parse((await cagir({ yol: "/dokum", port: uyg, kaynak: 51900 + kayma })).govde);
  console.log(`${etiket.padEnd(18)}ic uca giren ${giren}/4  uygulamanin reddettigi ${dokum.reddedilen}`);
} else console.log("kullanim: node zincir/istemci.mjs <kenar> <uygulama> <senaryo> <etiket> <kayma>");
```

```bash
# olc.sh — ayni istek zinciri farkli aktarim ayarlariyla. Her kosumda ucu de yeniden baslatilir.
K0="onek=/api,harita=acik"                # her kosumda ayni: onek soyulur, kaynak haritasi kenarda
kos() {                                   # kos <kenar-ek> <ic-ayar> <senaryo> <etiket> <kayma>
  node zincir/uygulama.mjs 8942 & U=$!
  node zincir/vekil.mjs 8941 8942 "$2" & I=$!
  node zincir/vekil.mjs 8940 8941 "$K0$1" & K=$!
  sleep 0.5
  node zincir/istemci.mjs 8940 8942 "$3" "$4" "$5"
  kill $K $I $U 2>/dev/null; wait $K $I $U 2>/dev/null; sleep 0.2
}
D=",temizle=acik,adres=acik,sema=acik,ad=acik,onekb=acik"   # dort basligin hepsi aktarilir

kos ",temizle=acik"                     "" kayip "aktarim yok"    0
kos ",temizle=acik,adres=acik,sema=acik" "" kayip "adres+sema"     1
kos "$D"                                "" kayip "dort baslik"    2
kos "$D"       "adres=acik,zincir=yaz"     kayip "ikinci atlama"  3
kos ",adres=acik,sema=acik,ad=acik,onekb=acik,zincir=ekle" "" sahte "temizleme yok" 4
kos "$D"                                "" sahte "temizleme var"  5
```

```
aktarim yok       cozulen 0/4  kayitta 1 kimlik  karar yonlendir bag izlendi 404
                  adres 127.0.0.1       ad 127.0.0.1:8942         onek yok
adres+sema        cozulen 2/4  kayitta 3 kimlik  karar sun       bag izlendi 404
                  adres 203.0.113.11    ad 127.0.0.1:8942         onek yok
dort baslik       cozulen 4/4  kayitta 3 kimlik  karar sun       bag izlendi 200
                  adres 203.0.113.11    ad olcum.ornek.gecersiz   onek /api
ikinci atlama     cozulen 3/4  kayitta 1 kimlik  karar sun       bag izlendi 200
                  adres 127.0.0.1       ad olcum.ornek.gecersiz   onek /api
temizleme yok     ic uca giren 4/4  uygulamanin reddettigi 0
temizleme var     ic uca giren 0/4  uygulamanin reddettigi 4
```

## Sıfırdan Dörde

İlk satır varsayılan durumdur: iki vekil de isteği iletiyor, hiçbiri hiçbir şey aktarmıyor.
Uygulama dört bilginin **dördünü de** kaybediyor ve dört ayrı yanlış karar üretiyor.

**İstemci adresi.** Üç ayrı üye üç ayrı istek gönderdi; denetim kaydında **bir** kimlik var.
Kayıt eksik değil, dolu — yalnız yazdığı adres iç vekilin adresi. Bir olayın hangi el
terminalinden geldiği sorulduğunda kayıt yanıt verir ve yanıtı yanlıştır.

**Protokol.** Uygulamaya gelen bağlantı şifresizdir, çünkü şifreleme kenar vekilde bitmiştir.
Uygulama şifresiz bir istek gördüğüne karar verip `yonlendir` diyor. Kararın kendisi doğru
yazılmış bir kuraldır; girdisi yanlıştır.

**Sunucu adı.** İstemci `olcum.ornek.gecersiz` adını istedi. Vekil arkaya bağlanırken istenen adı
yukarı akışın adıyla değiştirdi — bu bir hata değil, bağlantının kurulma biçimidir. Uygulama
kendi ürettiği mutlak bağlantıya `127.0.0.1:8942` yazıyor. Bu bağlantı bir sayfada gösterilse ya
da bir bildirim e-postasına konsa, iç adres dışarı çıkmış olur.

**Özgün yol.** Kenar vekil `/api` önekini soydu. Uygulama önekten habersiz olduğu için ürettiği
bağlantıya öneki koymuyor. Bağlantı izlendiğinde kenar vekil onu kendi yönlendirme kuralına
uydurmuyor ve **404** dönüyor. Saha ekibine giden bildirim e-postasındaki bağlantı, açıldığı gün
çalışmayan bir bağlantıdır.

İkinci satır iki başlığı açıyor. Denetim kaydındaki kimlik sayısı bire değil **üçe** çıkıyor ve
karar `sun` oluyor. İki kalem kapandı; ad ile önek hâlâ kayıp ve bağ hâlâ 404. Bu satır kısmi
aktarımın en yanıltıcı yanını gösteriyor: kayıt düzeldiği için yapılandırmanın tamam olduğu
düşünülür, oysa kapanan iki kalemin ikisi de kaydın içinde görünen kalemlerdi. Kayıtta
görünmeyen iki kalem, kayda bakarak bulunamaz.

Üçüncü satır dört başlığı da açıyor: dört bilginin dördü çözülüyor, kayıtta üç kimlik var,
üretilen bağ izlendiğinde 200 dönüyor.

## İkinci Atlamanın Sildiği

Dördüncü satırda kenar vekilin ayarı üçüncü satırla **birebir aynı**. Değişen tek şey iç vekilin
de adres aktarımını açması.

Sonuç: çözülen bilgi dörtten üçe düşüyor ve denetim kaydındaki kimlik sayısı üçten bire iniyor.
İç vekil, kenar vekilin yazdığı başlığın üstüne kendi gördüğü adresi yazdı; onun gördüğü adres
kenar vekilin adresidir. Aktarım iki atlamada da açık olmasına karşın uygulamaya varan değer
istemcinin adresi değil.

Bu, ilk satırdan daha zor bulunan bir arızadır. İlk satırda hiçbir aktarım yoktu ve durum bir
yapılandırma incelemesinde görülür. Dördüncü satırda **her iki vekilde de aktarım açıktır**;
inceleme "aktarım açık" der ve geçer. Aradaki fark tek bir kelimede — ikinci atlama gelen değeri
korumak yerine üzerine yazıyor.

Zincir uzunluğu burada bir çarpan olur: aktarımın doğru çalışması için zincirdeki **her**
atlamanın gelen değeri koruması ya da ona eklemesi gerekir. İki atlamada iki karar, dört
atlamada dört karar vardır ve hepsinin doğru olması gerekir; birinin yanlış olması yeter.

## Aktarılan Başlığa Güvenmek

Son iki satır ölçünün öteki yüzüdür. Uygulama artık aktarılan adrese **karar bağlıyor**: iç özet
ucu yalnız iç ağ adreslerinden çağrılabiliyor. Kaybı kapatan başlık, kapattığı anda bir yetki
girdisine dönüştü.

Beşinci satırda kenar vekil gelen `x-ileti-*` başlıklarını temizlemiyor ve zincire ekleme
yapıyor. İstemci kendi isteğine `10.9.0.5` yazıyor. Kenar vekil bunun üstüne kendi gördüğü
adresi ekliyor, başlık iki girdili oluyor ve uygulama soldaki ilk girdiyi okuyor: istemcinin
yazdığını. Dört isteğin **dördü de** iç uca giriyor, uygulama hiçbirini reddetmiyor ve dört
istek kayıtlarda başarılı iç çağrı olarak duruyor.

Altıncı satırda kenar vekil temizliyor. Dört isteğin sıfırı giriyor, uygulama dördünü de
reddediyor.

Açılan yüzeyin adı **iddia edilen kimlik yüzeyi**dir: uygulamanın güvendiği her aktarım başlığı,
önündeki her atlama onu silmediği sürece istemcinin denetimindeki bir girdidir. Bu yüzey iki
biçimde açılır. Birincisi temizlemenin unutulmasıdır — beşinci satır. İkincisi, önceki dersin
saydığı **yukarı akış kapısı**dır: iç vekil ile uygulamanın kapısı makinenin bütün arayüzlerinde
dinliyorsa, kenar vekile hiç uğramayan bir istek başlığını kendisi yazar ve temizleme hiç
çalışmaz. Kenar vekildeki tek satırlık temizleme kuralı, ancak zincirin tek girişi olduğu sürece
bir kural sayılır.

## Dört Kalem, İki Yön

Dört bilginin her biri iki ayrı kalem üretir: kapalıyken bir yanlış karar, açıkken bir güven
noktası.

| Bilgi | Kapalıyken üretilen yanlış karar | Açıkken doğan yüzey |
|---|---|---|
| İstemci adresi | üç üye kayıtta tek kimliğe düşer | adrese bağlı erişim kararı istemcinin yazdığı değere düşer |
| Protokol | şifreli istek şifresiz sayılır, karar `yonlendir` olur | uygulama şifrelemeyi kendisi doğrulamaz, başlığa güvenir |
| Sunucu adı | üretilen bağlantı iç adrese işaret eder | ad başına ayrım yapan kural sahte adla atlatılabilir |
| Özgün yol | önek düşer, üretilen bağ 404 alır | önek başına yetkilendirme kuralı sahte önekle atlatılabilir |

Tablonun sağ sütunu dersin asıl sonucudur. Kaybı kapatan tek yol bilgiyi bir başlıkta taşımaktır
ve başlık bağlantının kendisi gibi kanıtlanabilir değildir. Aktarım kapalıyken uygulama yanlış
bilgiyle doğru davranır; açıkken doğru bilgiyle davranır ve bilginin doğruluğu artık zincirdeki
her atlamanın disiplinine bağlıdır. Kaybolan dört kalem kapatıldı, yerine denetlenmesi gereken
dört güven noktası geldi.

## Özet

- Vekil zincirinden geçerken dört bilgi kaybolur: istemci adresi, protokol, istenen sunucu adı
  ve isteğin özgün yolu; aktarım kapalıyken uygulama dördünü de yanlış çözdü.
- Dört kaybın dördü de görünür bir karar üretti: üç üye kayıtta tek kimliğe düştü, karar
  `yonlendir` oldu, üretilen bağlantı iç adrese işaret etti ve önek eksikliği yüzünden izlendiğinde
  404 döndü.
- İki başlığın aktarılması kaydı düzeltti ama bağı düzeltmedi: kayıtta üç kimlik göründü, bağ
  yine 404 aldı; kayda bakarak kalan iki kalem bulunamaz.
- Her iki vekilde de aktarım açıkken bile ikinci atlama gelen değeri koruyacak yerde üzerine
  yazdığında çözülen bilgi dörtten üçe, kayıttaki kimlik üçten bire indi.
- Aktarılan başlığa karar bağlandığında iddia edilen kimlik yüzeyi açıldı: temizleme kapalıyken
  sahte başlıklı dört isteğin dördü de iç uca girdi, temizleme açıkken sıfırı girdi.

## Sonraki Adım

Bu dersin bütün ölçümleri şifrelemenin **bir yerde bittiğini** varsaydı: kenar vekil şifreyi
çözüyor, arkası şifresiz taşıyor. Sonlandırmanın kenar vekilde olduğu hiç sorgulanmadı, oysa bu
bir karardır ve üç yerde verilebilir.

Sonlandırma noktası değiştiğinde üç sayı birden değişir: zincirde kaç bacak şifresiz kalır,
sertifika kaç ayrı yerde durur ve yenileme sırasında kaç noktaya dokunulur. Üçü aynı yöne
gitmez; şifresiz bacağı sıfıra indiren seçenek sertifikanın bulunduğu yer sayısını ve yenileme
maliyetini artırır. Sonraki ders üç sonlandırma seçeneğini bu üç sayıyla karşılaştırır ve kabul
edilen protokol sürümleriyle şifre takımlarını bir kalem kümesi olarak modelleyip varsayılanın
kaç eski seçeneği açık bıraktığını, kısıtlamanın kaç istemciyi düşürdüğünü ölçer.
