Ders 11 / 16
Güvenlik Duvarı Yapılandırması
Makine düzeyinde açık yüzey kalem kalem sayılır: kurulum sonrası kaç kapı dinliyor, kaç bölgeden ulaşılabiliyor, varsayılan reddede geçilince kaç deneme duruyor, kaç meşru iş yanlışlıkla kapanıyor ve giden yön kısıtlanmadığında ne açık kalıyor.
İçindekiler
Önceki konu adın ve gönderenin doğrulanmasıyla kapandı: sorgu doğru ad sunucusuna gidiyor, e-postanın kaynağı kanıtlanabiliyor. Doğrulanan şey adın kendisiydi; adın işaret ettiği makine kurulduğu günkü ayarlarıyla duruyor ve o ayarlar onu her yerden erişilebilir bıraktı. Arkadaki makineye adı hiç kullanmadan da ulaşılır — adres yeter.
Ağ politikası daha önce küme içi ölçekte ölçüldü: hangi kapsül hangi kapsüle ulaşabiliyor. Buranın ölçeği kümenin altındaki makinedir. Sorulan üç şey var: hiçbir şey yapılmadığında kaç kalem açık kalır, kapatmak kaç satır ister, kapatınca kaç meşru iş durur.
- ST1. Altı makine ve yirmi beş dinleyen kapıdan oluşan düzen, kurgusal bölgesel ölçüm ağına
aittir. Gerçek bir makine koşturulmuyor; ölçülen şey
nodeile kurulan modeldir. - ST2. Kaynak bölge dörde indirgendi. Gerçekte bölge ayrımı adres aralıklarıyla yazılır; kalem sayısını büyütür, sonucun yönünü değiştirmez.
- ST3. Deneme sayıları elle yazıldı; rastgelelik yok, her koşum aynı sayıları üretir.
- ST4. Bir kapı ya açıktır ya kapalı; hız sınırı ve durum takibi modellenmiyor.
- ST5. İzin listesi izden türetilmedi, elle yazıldı;
ATLANANile işaretlenen iki seyrek akışın gözden kaçması modele elle konuldu. Gerçekte atlanan akış sayısı gözlem süresine bağlıdır. - ST6. Giden yön hedef sınıfı düzeyinde modellendi. Gerçekte giden kural adres ve kapı üzerinden yazılır; kalem sayısı büyür, kısıtlanmamış giden yönün anlamı değişmez.
Kural Kümesi Modeli
Model üç şey tutuyor: hangi makinede hangi kapı dinliyor, dönemde hangi bölgeden hangi kapıya kaç
deneme geldi ve operatörün yazdığı izin listesi. Kurallar kendi küçük şemamızla yazılıyor: bir satır
bir kaynak bölge, bir makine ve bir kapı adı belirtir, * o eksende ayrım yapılmadığı demektir.
// duvar.mjs — makine, dinlenen kapi, deneme ve kural kumesi modeli; gercek ag degil export const BOLGE = ['ic-ag', 'ofis-ag', 'saha-ag', 'dis']; const ORTAK = [['yonetim-kabugu', 'yonetim'], ['olcut-uc', 'yardimci'], ['gunluk-aktarim', 'yardimci']]; const OZGU = { // kurulumun makine basina acik biraktigi kapilar 'toplayici-1': [['okuma-alim', 'is']], 'toplayici-2': [['okuma-alim', 'is']], 'dogrulayici': [['dogrulama-api', 'is']], 'faturalama': [['fatura-api', 'is']], 'veri-deposu': [['veri-uc', 'is'], ['yedek-uc', 'is']], 'yonetim': [['yonetim-arayuz', 'yonetim']], }; export const MAKINE = Object.keys(OZGU); export const KAPI = MAKINE.flatMap((m) => [...ORTAK, ...OZGU[m]].map(([ad, tur]) => ({ makine: m, ad, tur }))); export const anahtar = (b, m, k) => `${b}|${m}|${k}`; // Otuz gunluk deneme: [bolge, makine, kapi, sayi, mesru mu] const her = (b, k, f, ms) => MAKINE.map((m, i) => [b, m, k, f(i), ms]); export const DENEME = [ ['saha-ag', 'toplayici-1', 'okuma-alim', 41200, true], ['saha-ag', 'toplayici-2', 'okuma-alim', 38900, true], ['ic-ag', 'dogrulayici', 'dogrulama-api', 26400, true], ['ic-ag', 'veri-deposu', 'veri-uc', 91500, true], ['ic-ag', 'faturalama', 'fatura-api', 8600, true], ['ofis-ag', 'faturalama', 'fatura-api', 1240, true], ['ofis-ag', 'yonetim', 'yonetim-arayuz', 860, true], ['ofis-ag', 'yonetim', 'yonetim-kabugu', 310, true], ['ofis-ag', 'veri-deposu', 'yedek-uc', 4, true], // aylik yedek dogrulamasi ['ofis-ag', 'dogrulayici', 'dogrulama-api', 12, true], // ceyrek sonu elle dogrulama ...her('ic-ag', 'olcut-uc', () => 8640, true), ...her('ic-ag', 'gunluk-aktarim', () => 30, true), ...her('ic-ag', 'yonetim-kabugu', () => 62, true), // yapilandirma dagitimi ...her('dis', 'yonetim-kabugu', (i) => 12000 + i * 1730, false), ...her('dis', 'olcut-uc', (i) => 90 + i * 7, false), ['dis', 'veri-deposu', 'veri-uc', 2400, false], ['dis', 'veri-deposu', 'yedek-uc', 180, false], ['dis', 'toplayici-1', 'okuma-alim', 640, false], ['dis', 'yonetim', 'yonetim-arayuz', 5100, false], ['saha-ag', 'veri-deposu', 'veri-uc', 26, false], ['saha-ag', 'yonetim', 'yonetim-kabugu', 14, false], ['ofis-ag', 'veri-deposu', 'veri-uc', 310, false], ]; export const MESRU = DENEME.filter((d) => d[4]).map((d) => anahtar(d[0], d[1], d[2])); // Izin listesini operator elle yazdi; iki seyrek akis gozden kacti. const ATLANAN = ['ofis-ag|veri-deposu|yedek-uc', 'ofis-ag|dogrulayici|dogrulama-api']; export const IZIN = MESRU.filter((a) => !ATLANAN.includes(a)).map((a) => a.split('|')); // Ayni liste uc genislikte yazilabilir; '*' o eksende ayrim yok demektir. export const bicimler = () => ({ 'kapi-adi': [...new Set(IZIN.map((r) => r[2]))].map((k) => ['*', '*', k]), 'bolge+kapi': [...new Set(IZIN.map((r) => `${r[0]}|${r[2]}`))].map((s) => [s.split('|')[0], '*', s.split('|')[1]]), 'bolge+makine+kapi': IZIN, }); export function acilan(kural) { // kural kumesi -> acik kalem kumesi const acik = new Set(); for (const [b, m, k] of kural) for (const bb of (b === '*' ? BOLGE : [b])) for (const p of KAPI) if ((m === '*' || p.makine === m) && (k === '*' || p.ad === k)) acik.add(anahtar(bb, p.makine, p.ad)); return acik; } export const HEPSI = acilan([['*', '*', '*']]); // varsayilan izinli duzen tek satira esit export function say(acik) { const kapali = (d) => !acik.has(anahtar(d[0], d[1], d[2])); const top = (f) => DENEME.filter(f).reduce((a, d) => a + d[3], 0); return { kalem: acik.size, karsiliksiz: [...acik].filter((a) => !MESRU.includes(a)).length, duran: top((d) => !d[4] && kapali(d)), gecen: top((d) => !d[4] && !kapali(d)), yanlisKapali: DENEME.filter((d) => d[4] && kapali(d)).length }; } export const GIDEN_MESRU = [ ['toplayici-1', 'ic:kuyruk'], ['toplayici-2', 'ic:kuyruk'], ['dogrulayici', 'ic:veri-deposu'], ['faturalama', 'ic:veri-deposu'], ['faturalama', 'dis:posta-gecidi'], ['yonetim', 'dis:paket-deposu'], ['veri-deposu', 'ic:yedek-alan'], ...MAKINE.map((m) => [m, 'dis:zaman-kaynagi']), ]; export const GIDEN_IZIN = GIDEN_MESRU.filter(([m, h]) => h !== 'dis:zaman-kaynagi' || m === 'yonetim');
HEPSI satırı modelin sessiz iddiasıdır: varsayılan izinli düzen tek bir * -> * -> * kuralına
eşittir; kimse o kuralı yazmadı ama etkisi yazılmış gibidir. say bir açık kalem kümesi alıp beş
sayı döndürüyor: kaç kalem açık, kaçının karşılığı yok, meşru olmayan denemelerden kaçı durdu, kaçı
geçti ve kaç meşru akış yanlışlıkla kapandı.
Varsayılanın Bıraktığı Yüzey
// kosum1.mjs — kurulum sonrasi hicbir sey yapilmadiginda acik kalan kalemler sayilir import { BOLGE, MAKINE, KAPI, DENEME, MESRU, GIDEN_MESRU, HEPSI, say } from './duvar.mjs'; const s = say(HEPSI); const tur = (t) => KAPI.filter((k) => k.tur === t).length; const top = (f) => DENEME.filter(f).reduce((a, d) => a + d[3], 0); const kapiTuru = (m, k) => KAPI.find((x) => x.makine === m && x.ad === k).tur; for (const [ad, deger, not = ''] of [ ['dinlenen kapi', KAPI.length, `${MAKINE.length} makine: is ${tur('is')}, yardimci ${tur('yardimci')}, yonetim ${tur('yonetim')}`], ['gelen yon acik kalem', s.kalem, `${KAPI.length} kapi x ${BOLGE.length} bolge`], [' mesru akisa karsilik gelen', MESRU.length], [' karsiliksiz acik', s.karsiliksiz], ['dis bolgeden erisilen yonetim kapisi', tur('yonetim')], ['giden yon kisitlamasi', '-', `${MAKINE.length} makinenin hedefi sinirsiz, ${GIDEN_MESRU.length} mesru akis`], ['otuz gunluk mesru olmayan deneme', top((d) => !d[4]), `${new Set(DENEME.filter((d) => !d[4]).map((d) => d[0])).size} kaynak bolgeden`], [' yonetim kapisina gelen', top((d) => !d[4] && kapiTuru(d[1], d[2]) === 'yonetim')], [' durdurulan', s.duran], [' hedefe ulasan', s.gecen], ]) console.log(`${ad.padEnd(38)}${String(deger).padStart(7)} ${not}`.trimEnd());
dinlenen kapi 25 6 makine: is 6, yardimci 12, yonetim 7 gelen yon acik kalem 100 25 kapi x 4 bolge mesru akisa karsilik gelen 28 karsiliksiz acik 72 dis bolgeden erisilen yonetim kapisi 7 giden yon kisitlamasi - 6 makinenin hedefi sinirsiz, 13 mesru akis otuz gunluk mesru olmayan deneme 107265 3 kaynak bolgeden yonetim kapisina gelen 103064 durdurulan 0 hedefe ulasan 107265
Yirmi beş dinleyen kapının yalnız altısı işin kendisi için açık. Kalan on dokuzu ölçüt toplama, günlük aktarımı ve yönetim kabuğu içindir; hiçbiri kasten açılmadı, kurulum açtı. Yüz kalem bu kapıların dört bölgeden birden erişilebilir olmasından geliyor — yirmi sekizinin karşılığında meşru bir akış var, yetmiş ikisinin yok.
Yönetim kapılarının yedisi dış bölgeden de erişilebilir ve dönemin meşru olmayan yüz yedi bin denemesinin yüz üç bini tam olarak oraya geliyor. Son iki satır çıkış noktasıdır: bu denemelerin sıfır tanesi durdu. Varsayılan kararı “izin ver” olan bir güvenlik duvarı katmanıyla hiç olmayan katman aynı sayıyı üretiyor. Giden yönde ise kısıtlama diye bir kalem bile yok.
Varsayılan Reddet ve Kuralın Genişliği
// kosum2.mjs — varsayilan reddede gecilir; ayni izin listesi uc kural genisliginde yazilir import { BOLGE, IZIN, bicimler, acilan, HEPSI, say } from './duvar.mjs'; const satir = (ad, n, acik) => { const s = say(acik); console.log(`${ad.padEnd(35)} ${String(n).padEnd(6)} ${String(s.kalem).padEnd(6)} ` + `${String(s.karsiliksiz).padEnd(12)} ${String(s.duran).padEnd(13)} ${String(s.gecen).padEnd(13)} ${s.yanlisKapali}`); }; console.log(`ayni izin listesi (${IZIN.length} akis) uc genislikte:\n` +`${'kural genisligi'.padEnd(35)} satir kalem karsiliksiz duran deneme gecen deneme yanlis kapali`); satir('varsayilan izin', 0, HEPSI); for (const [ad, k] of Object.entries(bicimler())) satir(ad, k.length, acilan(k)); const dar = bicimler()['bolge+makine+kapi']; const A = ['ofis-ag', '*', '*'], B = ['dis', 'yonetim', 'yonetim-kabugu'], C = ['*', '*', 'olcut-uc']; console.log('\nen dar bicime gecici satir eklenirse:'); for (const [ad, ek] of [['ofis-ag -> * -> *', [A]], ['dis -> yonetim -> yonetim-kabugu', [B]], ['ucu birden (+ * -> * -> olcut-uc)', [A, B, C]]]) satir(` ${ad}`, dar.length + ek.length, acilan([...dar, ...ek])); const genis = bicimler()['kapi-adi'].map(([b, m, k]) => [k, acilan([[b, m, k]]).size]).filter(([, n]) => n > 4); console.log(`\nkapi adina yazilan tek kuralin actigi kalem (${BOLGE.length} bolge x kapiyi dinleyen makine):`); console.log(' ' + genis.map(([k, n]) => `${k} ${n}`).join(', '));
ayni izin listesi (26 akis) uc genislikte: kural genisligi satir kalem karsiliksiz duran deneme gecen deneme yanlis kapali varsayilan izin 0 100 72 0 107265 0 kapi-adi 8 96 69 180 107085 1 bolge+kapi 10 31 5 107265 0 2 bolge+makine+kapi 26 26 0 107265 0 2 en dar bicime gecici satir eklenirse: ofis-ag -> * -> * 27 48 20 106955 310 0 dis -> yonetim -> yonetim-kabugu 27 27 1 86615 20650 2 ucu birden (+ * -> * -> olcut-uc) 29 61 33 85660 21605 0 kapi adina yazilan tek kuralin actigi kalem (4 bolge x kapiyi dinleyen makine): okuma-alim 8, yonetim-kabugu 24, olcut-uc 24, gunluk-aktarim 24
Varsayılanı reddet yapmak tek başına bir sayı üretmiyor. kapi-adi satırı bunu gösteriyor: sekiz
kural yazıldı, varsayılan reddedir, izin listesi uygulanıyor — ve açık kalem yüzden doksan altıya
indi, meşru olmayan denemelerin yalnız yüz sekseni durdu. Son satır nedenini veriyor: yonetim-kabugu
tek kural olarak yazıldığında yirmi dört kalem açıyor, çünkü altı makinenin ve dört bölgenin hepsini
birden kapsıyor. İzin listesinde bu kapı için altı satır vardı ve altısı da iç ağdandı; bölge
eksenini düşürmek dış bölgeyi de açıyor. Üç geniş kural, doksan altı kalemin yetmiş ikisini üretiyor.
Bölge eksenini eklemek satırı sekizden ona çıkarıyor: açık kalem otuz bire iniyor ve meşru olmayan denemelerin tamamı duruyor. İki satır, yüz yedi bin denemeyi kapatıyor. Makine eksenini de eklemek yirmi altı satır istiyor; karşılıksız kalem beşten sıfıra iniyor ama durdurulan deneme değişmiyor. Bölge ekseni kapatan eksendir, makine ekseni yalnız artığı temizler: on altı satırlık emek beş kaleme karşılık geliyor.
Yanlış kapatma sütunu her iki dar biçimde de iki — modelde ATLANAN ile işaretlenen aylık yedek
doğrulaması ve çeyrek sonu elle doğrulaması, dönemde dört ve on iki deneme. Yüz binlerce satırlık bir
izde bu on altı satır görünmez. Kural yazıldığı gün hiçbir şey bozulmaz; ay ve çeyrek sonunda bozulur
ve görünen şey bir bağlantı hatasıdır, bir izin listesi satırı değil.
Ortadaki blok kapatmanın kendi getirdiği yüzeyi ölçüyor; kural kümesi de yazılan, gerekçeli olarak
genişletilen ve çoğu zaman geri alınmayan bir kalemdir. ofis-ag için açılan joker satır yirmi iki
kalem ekliyor ama yalnız üç yüz on deneme geçiriyor; dış bölgeye açılan tek yönetim kapısı bir kalem
ekleyip yirmi bin altı yüz elli deneme geçiriyor — kalemin hangi bölgeye baktığı sayıdan önemlidir.
Joker satırın son sütunu asıl sorunu gösteriyor: yanlış kapatma ikiden sıfıra iniyor, çünkü satır
atlanmış iki meşru akışı kazara açıyor. Eksiklik fark edilmiyor, satırın kaldırılması için bir neden
de doğmuyor. Üçü birlikte kaldığında yirmi dokuz satır altmış bir kalem açıyor; kural kümesi tek
yönde büyür, çünkü satır eklemenin gerekçesi olur, satır silmenin olmaz.
Giden Yön
Buraya kadar sayılan her kalem gelen yöne aitti. Giden yön çoğu düzende hiç kısıtlanmaz ve kalem sayısında görünmediği için yüzey olduğu fark edilmez.
// kosum3.mjs — giden yon ayri sayilir; gelen kural bu sayilarin hicbirine dokunmuyor import { MAKINE, IZIN, GIDEN_MESRU, GIDEN_IZIN, bicimler, acilan, say } from './duvar.mjs'; const dis = (l) => new Set(l.filter(([, h]) => h.startsWith('dis:')).map(([, h]) => h)).size; const kalem = say(acilan(bicimler()['bolge+makine+kapi'])).kalem; const duran = GIDEN_MESRU.filter(([k, h]) => !GIDEN_IZIN.some(([a, b]) => a === k && b === h)); console.log('makine varsayilan izinli hedef duran mesru akis'); for (const m of MAKINE) console.log((`${m.padEnd(13)} ${'sinirsiz'.padEnd(11)} ` + `${String(GIDEN_IZIN.filter(([k]) => k === m).length).padEnd(13)} ` + duran.filter(([k]) => k === m).map(([, h]) => h).join(', ')).trimEnd()); console.log(`\nmesru giden akis ${GIDEN_MESRU.length} (${dis(GIDEN_MESRU)} dis hedef sinifina)`); console.log(`giden kural satiri ${GIDEN_IZIN.length} (varsayilanda 0, hedef sinirsiz)`); console.log(`izin verilen dis hedef sinifi ${dis(GIDEN_IZIN)} (varsayilanda herhangi)`); console.log(`yanlis kapatilan mesru akis ${duran.length}`); console.log(`gelen yon acik kalemi ${kalem} -> ${kalem} (degismedi)`); console.log(`toplam kural satiri ${IZIN.length} -> ${IZIN.length + GIDEN_IZIN.length}`);
makine varsayilan izinli hedef duran mesru akis toplayici-1 sinirsiz 1 dis:zaman-kaynagi toplayici-2 sinirsiz 1 dis:zaman-kaynagi dogrulayici sinirsiz 1 dis:zaman-kaynagi faturalama sinirsiz 2 dis:zaman-kaynagi veri-deposu sinirsiz 1 dis:zaman-kaynagi yonetim sinirsiz 2 mesru giden akis 13 (3 dis hedef sinifina) giden kural satiri 8 (varsayilanda 0, hedef sinirsiz) izin verilen dis hedef sinifi 3 (varsayilanda herhangi) yanlis kapatilan mesru akis 5 gelen yon acik kalemi 26 -> 26 (degismedi) toplam kural satiri 26 -> 34
Sekiz satır giden kural, makine başına açık hedefi bire ya da ikiye indiriyor; varsayılanda bu sütunda “sınırsız” yazıyordu. Aradaki fark ele geçirilen bir makinenin ne yapabileceğidir: gelen kural kümesi eksiksiz olsa bile içeride çalışan bir süreç dışarıya bağlanabiliyorsa veriyi taşıyabilir, komut alabilir ve kendi kalıcılığını kurabilir. Bu yolun kapanması gelen yönün hiçbir kalemini değiştirmiyor; açık kalem yirmi altıda kalıyor, kural sayısı otuz dörde çıkıyor.
Yanlış kapatma sütunu beş. İzin listesini yazan kişi zaman kaynağı bağımlılığını yönetim düğümünde gördü ve orada yazdı, ötekilerde aklına gelmedi. Özelliği hemen görünmemesidir: saat bir anda durmaz, kayar. Kayma birkaç gün sonra imza doğrulamasında, günlük sıralamasında ve ölçüt pencerelerinde ortaya çıkar; hepsi başka bir şeyin belirtisi gibi görünür. Gelen yöndeki iki yanlış kapatma bir bağlantı hatası verip düzeltilir, giden yöndeki beş tanesi haftalarca yanlış teşhis edilebilir.
Kapatmanın getirdiği yeni yüzey de burada. İzin verilen üç dış hedef sınıfından biri paket deposudur ve yönetim düğümü için açıktır; yama alabilmenin bedeli, dışarıya çıkan bir yolun kalıcı olarak açık kalmasıdır. Otuz dört satırlık kural kümesi kapatılamayan bir kalem bırakıyor: iki yönde birden ayrıcalıklı olan yönetim düğümü.
Özet
- Kurulum sonrası altı makinede 25 kapı dinliyor; yalnız 6’sı işin kendisi için. Dört bölgeden erişilebilirlik bunu 100 açık kaleme çeviriyor, 72’sinin karşılığında meşru akış yok ve dönemin meşru olmayan 107.265 denemesinin tamamı hedefe ulaşıyor — 103.064’ü yönetim kapılarına.
- Varsayılanı reddet yapmak tek başına yetmiyor: kapı adına yazılan 8 satır yalnız 180 denemeyi durduruyor. Bölge ekseni 10 satırla denemelerin tamamını kapatıyor; makine ekseni 26 satır isteyip karşılıksız kalemi 5’ten 0’a indiriyor, durdurulan denemeye bir şey eklemiyor.
- Her iki dar biçim de 2 meşru akışı yanlışlıkla kapatıyor; ikisi dönemde toplam 16 deneme ürettiği için izde görünmüyor ve ay ile çeyrek sonunda bozuluyor.
- Kural kümesinin kendisi bir yüzeydir: dış bölgeye açılan tek satır 1 kalem ekleyip 20.650 deneme geçiriyor, ofis ağına açılan joker satır 22 kalem ekleyip yanlış kapatmayı 2’den 0’a indirerek eksik izin listesini gizliyor.
- Giden yön 8 satırla kısıtlandığında makine başına açık hedef 1–2’ye iniyor ve gelen yönün 26 kalemi değişmiyor; bedeli, günler sonra saat kayması olarak görünen 5 yanlış kapatmadır. Kapatılamayan kalem, yama alabilmek için dışarıya bakan tek makinedir.
Sonraki Adım
En dar kural kümesi yönetim kabuğunu altı makinede iç ağa açık bıraktı. Kapı daraldı, arkasındaki şey değişmedi: bağlanan taraf hâlâ bir parolayla giriyor ve parola denemesi güvenlik duvarının izin verdiği bölgelerden serbestçe yapılabiliyor. Sonraki dersin sorusu kapının hangi bölgeye açık olduğu değil, kapıdan geçmenin neye bağlı olduğudur: parola tabanlı erişimde bir dönemde kaç deneme kaç kaynaktan geliyor, anahtar tabanlıya geçince bu yüzeyin ne kadarı kapanıyor, anahtar kaç kopya hâlinde nerede duruyor ve kaç makinede yetkili, iptal etmek kaç dokunuş istiyor — ve erişimi bir sıçrama sunucusuna indirmek doğrudan erişilebilir makine sayısını düşürürken karşılığında hangi tek hedefi doğuruyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.