Kurumsal Network Kurulumu

LDAP ve LDAPS Nedir? Dizin Sorgulama ve 636 Portu

LDAP nedir, nasıl çalışır? Dizin yapısı, DN ve base DN mantığı, bind türleri ve 389 ile 636 farkı; gerçek paket yakalamalarıyla anlatıyoruz.

İlker Pehlivan

LDAP (Lightweight Directory Access Protocol), bir dizindeki kullanıcı, grup ve cihaz kayıtlarını sorgulamak ve güncellemek için kullanılan ağ protokolüdür. Bir kurumda “bu kullanıcı kim, hangi gruplarda, hangi birimde çalışıyor” sorusunun cevabı merkezi bir yerde tutulur ve uygulamalar o merkeze bu protokolle sorar. Düz bağlantı için 389, şifreli bağlantı için 636 numaralı portu kullanır.

Bir kütüphane düşünün. Raflarda yüz binlerce kitap var ve hiçbiri gelişigüzel durmuyor: önce kat, sonra bölüm, sonra raf, sonra o rafta sıra.

Katalogdaki fiş size kitabın adını vermez. Tam olarak nerede durduğunu tarif eder. Adını bilmek o kitabı bulmaya yetmez; yerini bilmek yeter.

LDAP tam olarak böyle çalışır ve bu makale boyunca o kütüphanede kalacağız.

Aşağıda önce LDAP’ın ne olduğunu ve adındaki “hafif” kelimesinin neyin hafifi olduğunu göreceğiz. Sonra dizinin raf düzenini, yani DIT ve DN kavramlarını kuracağız; ardından çoğu kişinin karıştırdığı Active Directory ile LDAP ayrımını netleştireceğiz. Sonrasında bir sorgunun nasıl kurulduğunu ve dizine kimliğin nasıl kanıtlandığını ele alacağız. Son olarak 389 ile 636 arasındaki farkın neden bir tercih meselesi olmadığını lafla değil, kendi lab ortamımızda yakaladığımız paketlerle göstereceğiz: aynı bind işleminin birinde parola ağda okunabilir halde duruyor, diğerinde hiçbir iz bırakmıyor. Elinizde şu an cevap vermeyen bir dizin sorgusu varsa doğrudan teşhis bölümüne atlayabilirsiniz.

Bu makale kurumsal network kurulumu hizmetimizin kimlik ve dizin katmanına odaklanır; LDAP’ın içinde yer aldığı protokol zincirinin tamamını kurumsal ağ protokolleri rehberimizde ele alıyoruz.

LDAP dizin sorgulamanın hiyerarşik yapısı: kütüphane salonundan bölümlere, oradan raflara ve tek bir kitaba inen bakır iplik, yanında katalog dolabından fiş çeken kütüphaneci
Katalog fişi kitabın adını değil, tam yerini söyler. Bir nesnenin DN'i de tam olarak budur.

LDAP Nedir? Dizin Protokolü ve Adındaki “Lightweight”

LDAP, bir dizin servisine (directory service) erişmek için kullanılan, istemci ile sunucu arasında çalışan açık bir protokoldür. Güncel sürümü LDAPv3’tür ve tarifi RFC 4511 numaralı belgede yazılıdır.

RFC’ler internetin kural kitabıdır. Numaralandırılmış, herkese açık teknik belgelerdir; bir protokolün hangi mesajı nasıl göndereceği, hangi alanın ne anlama geldiği orada tanımlanır. Bu makalenin ilerleyen bölümlerinde paketlerin içinde göreceğiniz name ve authentication gibi alan adları uydurma değil, doğrudan o belgeden geliyor.

Önemi şurada: Windows da, OpenLDAP da, bir ağ yazıcısının içindeki yazılım da aynı belgeye bakarak yazılmıştır. Birbirlerini anlamalarının sebebi ortak bir üretici değil, ortak bir metindir. Yani LDAP bir üründen değil, bir anlaşmadan ibarettir.

Buradaki kilit kelime dizin. Bir dizin, veritabanı değildir ve bu ayrım protokolün bütün tasarımını açıklar:

  • Dizin çok okunur, az yazılır. Bir kullanıcı kaydı yılda birkaç kez değişir ama günde binlerce kez sorgulanır. LDAP bu oran için optimize edilmiştir.
  • Dizin hiyerarşiktir. Satır ve sütunlardan değil, iç içe geçmiş dallardan oluşur.
  • Dizin dağıtıktır. Bir dalın sorumluluğu başka bir sunucuya devredilebilir, istemci bunu fark etmez.

Kütüphanede de aynı düzen var. Katalog kartları nadiren değişir, sürekli okunur; raf düzeni hiyerarşiktir; ve bir bölümün sorumluluğu başka bir kata devredilmiş olabilir.

”Hafif” Olan Neydi, Neye Göre Hafif?

Addaki “lightweight” kelimesi LDAP’ın basit olduğunu değil, kendinden öncekine göre hafif olduğunu söyler. Öncesinde X.500 adlı bir dizin standardı vardı ve erişim protokolü DAP (Directory Access Protocol) idi. DAP teknik olarak yetkindi ama çalışabilmesi için OSI protokol yığınının tamamını istiyordu; bu da onu üniversite ve kurum ağlarının çoğunda pratikte kullanılamaz hale getiriyordu.

1993’te Michigan Üniversitesi’nde geliştirilen LDAP, aynı dizin modelini korudu ama doğrudan TCP/IP üzerinde çalıştı. Sonuç, kavramsal olarak DAP kadar güçlü ama internetin konuştuğu dili konuşan bir protokol oldu. Bugün X.500’ü sahada neredeyse hiç görmezsiniz; ondan miras kalan kavramlar ise LDAP’ın içinde aynen yaşıyor.

Bunun pratik sonucu şu: LDAP’ta karşınıza çıkan tuhaf kısaltmaların çoğu 1980’lerin X.500 mirasıdır. dc, ou, cn gibi ifadeler ilk bakışta keyfi görünür; keyfi değiller, bir kütüphane sınıflandırma sisteminin kalıntılarıdır.

LDAP Dizin Yapısı: DIT, DN ve RDN

LDAP dizini bir ağaçtır ve bu ağacın adı DIT’tir (Directory Information Tree). Tepede kurumun kökü, altında birimler, en altta tek tek kullanıcılar, gruplar ve bilgisayarlar durur. Her nesnenin ağaçta tam olarak bir yeri vardır ve o yeri tarif eden ifadeye DN (Distinguished Name) denir.

Addaki “distinguished” kelimesi boşuna değil: DN, bir nesneyi dizindeki diğer her şeyden ayıran şeydir. Aynı DN’e sahip iki nesne olamaz, tıpkı aynı rafta aynı sırada iki kitabın duramayacağı gibi.

Kütüphane karşılığı birebir oturuyor:

LDAPKütüphaneÖrnek
DITRafların tamamıBinadaki bütün koleksiyon
dc (domain component)Bina / koleksiyon adıdc=ad,dc=sercebilisim,dc=com
ou (organizational unit)Kat ve bölümou=Bilgisayarlar
cn (common name)Rafta duran tek kitapcn=PCTEST01
DNKitabın tam yeri: kitap, raf, bölüm, binacn=PCTEST01,ou=...,dc=com
RDNKitabın kendi etiketi, rafı olmadanYalnızca cn=PCTEST01 kısmı

Lab ortamımızdaki bir bilgisayar kaydının gerçek DN’i şöyle görünüyor:

LDAP
CN=PCTEST01,OU=Bilgisayarlar,OU=Genel_Mudurluk,OU=Lokasyonlar,DC=ad,DC=sercebilisim,DC=com

Bu satır bir isim değil, bir adres. Okunuşu da adres gibi, ama ters yönde:

  1. CN=PCTEST01 en spesifik parça: aradığımız nesnenin kendisi. Buna RDN (Relative Distinguished Name) denir, yani “bulunduğu dala göre adı”.
  2. OU=Bilgisayarlar o nesnenin durduğu raf.
  3. OU=Genel_Mudurluk o rafın bulunduğu bölüm.
  4. OU=Lokasyonlar o bölümün bulunduğu kat.
  5. DC=ad,DC=sercebilisim,DC=com binanın kendisi, yani domain.

Dikkat edilecek üç kural var ve üçü de sahada hataya yol açar:

  • Sıralama soldan sağa, spesifikten genele gider. Dosya yollarının tam tersi. C:\Lokasyonlar\Genel_Mudurluk\Bilgisayarlar\PCTEST01 yazma alışkanlığıyla DN kuran herkes ilk denemede ters yazar.
  • DN’in tamamı benzersizdir, RDN yalnızca kendi dalında benzersizdir. İki farklı birimde aynı adda kullanıcı olabilir; DN’leri farklı olduğu için çakışmazlar.
  • Boşluk ve Türkçe karakter baş ağrıtır. Yukarıdaki Genel_Mudurluk adının alt çizgiyle yazılmasının sebebi budur. Bir OU adında boşluk varsa DN’i tırnaklamanız ya da kaçış karakteri kullanmanız gerekir, Türkçe karakter ise istemciden istemciye farklı davranır.

Nesneyi Nesne Yapan Şey: objectClass ve Öznitelikler

Dizindeki her kayıt bir nesnedir ve her nesnenin bir tipi vardır. Tipi belirleyen öznitelik objectClass’tır: bir kayıt user mı, group mu, computer mı, bunu o alan söyler. Tip, o nesnenin hangi öznitelikleri taşıyabileceğini de belirler; buna şema (schema) denir.

Kullanıcı nesnelerinde sık karşılaşacağınız öznitelikler şunlar:

  • sAMAccountName: Kullanıcının oturum açarken yazdığı kısa ad. Active Directory’ye özgüdür.
  • userPrincipalName: kullanici@ad.sercebilisim.com biçimindeki modern oturum açma adı.
  • mail: E-posta adresi. Uygulamaların kullanıcıyı eşleştirmek için en sık kullandığı alan.
  • memberOf: Kullanıcının üye olduğu grupların DN listesi. Yetkilendirme kararlarının çoğu bu alandan çıkar.
  • distinguishedName: Nesnenin kendi DN’i.

Kütüphane karşılığı şu: katalog fişinde kitabın yeri dışında yazar, yayın yılı ve tür de yazar. Aradığınız kitabı yerini bilmeden de bulabilmenizin sebebi bu alanların doldurulmuş olmasıdır.

Active Directory LDAP Değildir: Active Directory LDAP Konuşur

Bu, konuyla ilgili en yaygın kavram hatası ve düzeltilmesi teşhis sırasında doğrudan işe yarar. Active Directory bir dizin servisidir; LDAP ise o dizine erişmek için kullanılan protokollerden yalnızca biridir. İkisi aynı şey değildir, biri diğerinin yerine kullanılamaz.

Farkı en net şu şekilde görürsünüz: bir Domain Controller aynı anda birkaç protokol birden konuşur ve her biri farklı bir soruya cevap verir.

ProtokolPortCevapladığı soru
LDAP389 / 636Bu kullanıcı hangi gruplarda, hangi birimde?
Kerberos88Bu kişi gerçekten iddia ettiği kişi mi?
DNS53Domain Controller’ı nerede bulacağım?
SMB445Grup ilkesi dosyalarını nereden okuyacağım?

Yani LDAP yetkiyi söyler, kimliği kanıtlamaz. “Bu kişi o” cevabını veren Kerberos’tur; LDAP’ın işi “bu kişi neye yetkili” sorusudur. Kimlik doğrulamanın nasıl işlediğini ve bilet mantığını Kerberos nedir rehberimizde, grup ilkesi dosyalarının taşındığı paylaşım katmanını ise SMB nedir rehberimizde ele alıyoruz.

Neden Hepsi Bir Arada Geliyor?

Bir kütüphane yalnızca kataloğundan ibaret değildir. Katalog hangi kitabın nerede olduğunu söyler, ama kapıda kimliğinizi kimse sormuyorsa herkes içeri girer; binanın adresi bilinmiyorsa kimse ulaşamaz; kitapları raflara taşıyan bir sistem yoksa katalog boş bir vaattir. Dizin de böyle: tek başına eksik bir cevaptır.

Bir kurumun kimlik altyapısının cevaplaması gereken dört soru var ve LDAP bunlardan yalnızca birine bakar:

  1. “Bu kişi kim, neye yetkili?” Dizinin işi. LDAP burada.
  2. “Gerçekten o mu?” Kimlik doğrulama. Ayrı bir protokol gerekir.
  3. “Dizin nerede?” İstemcinin sunucuyu bulması. İsim çözümleme gerekir.
  4. “Kurallar makinelere nasıl ulaşacak?” Politika dosyalarının dağıtımı. Bir paylaşım protokolü gerekir.

Microsoft, Active Directory’yi 1990’ların sonunda tasarlarken bu dördünü ayrı ayrı kurulan ürünler olarak bırakmadı; tek bir pakette birleştirdi ve o pakete “domain” adını verdi. Bugün bir Domain Controller kurduğunuzda Kerberos’u ve DNS’i ayrıca kurmazsınız, kendiliğinden gelirler. Bu bir kolaylık değil, zorunluluktur: AD onlar olmadan çalışamaz, çünkü kendi istemcilerini bulunur kılmak için DNS’e, kullanıcıyı doğrulamak için Kerberos’a muhtaçtır.

Buradan çıkan sonuç, bu bölümün başlığını da açıklıyor. “Active Directory LDAP değildir” cümlesi bir kelime oyunu değil: AD dört soruya birden cevap veren bir sistemdir, LDAP ise o sistemin yalnızca birinci soruyu cevaplarken konuştuğu dildir.

Aynı Karar Linux Tarafında da Verildi

Bu tasarımın Microsoft’a özgü olmadığını görmek, kavramı yerine oturtan en iyi yol. Linux dünyasında FreeIPA tam olarak aynı ihtiyaçtan doğdu ve aynı yolu izledi: içinde dizin için 389 Directory Server, kimlik doğrulama için MIT Kerberos, isim çözümleme için BIND ve sertifika için Dogtag bulunur. Hepsi tek kurulumla gelir, tek yerden yönetilir.

Karşılaştırma şu tabloya oturuyor:

Ne verirNe vermez
OpenLDAPYalnızca dizinKimlik doğrulama, isim çözümleme, politika dağıtımı
FreeIPADizin + Kerberos + DNS + sertifikaWindows istemci yönetimi, grup ilkesi
Active DirectoryDizin + Kerberos + DNS + paylaşım + grup ilkesiLinux istemcilerde yerel yönetim derinliği

Tablonun bir satırı daha var ve Windows istemcisi olan ortamlar için belirleyici olan o: Samba AD DC, FreeIPA’nın veremediği iki şeyi (Windows istemcinin domaine katılması ve grup ilkesi dağıtımı) verir, çünkü Active Directory’nin konuştuğu protokol dizisinin tamamını uygular. Linux üzerinde bunun nasıl kurulduğunu ve kurulduktan sonra hangi portların açıldığını Samba AD DC kurulum rehberimizde ölçümleriyle ele alıyoruz.

Bu tablo, “hangisini kurmalıyım” sorusunun cevabını da veriyor. Yalnızca bir kullanıcı dizinine ihtiyacınız varsa OpenLDAP yeter ve hafiftir. Ama makineleri yönetmeniz, tek oturum açma kurmanız ve merkezi politika dağıtmanız gerekiyorsa, dizin tek başına işi görmez; eksik kalan üç soruyu kendiniz çözmek zorunda kalırsınız. Kurumların hazır paketleri tercih etmesinin sebebi budur.

Bu Ayrımı Bilmek Teşhiste Ne Kazandırır?

Yukarıdaki dört soru akademik bir sınıflandırma değil. Sahada işe yarama biçimi çok somut: bir arıza karşınıza çıktığında, belirtiye değil hangi sorunun cevapsız kaldığına bakarsınız. Kullanıcı “GPO uygulanmıyor” diyorsa bu dördüncü sorudur, dizin sorusu değil; dizini kurcalamak zaman kaybıdır. “Oturum açamıyorum” ikinci ya da üçüncü sorudur. “Kullanıcı görünüyor ama yetkisi yok” birinci sorudur.

Danışmanlık verdiğim bir firmada bunun bedelini somut olarak gördüm. Yapı şöyleydi: merkezde bir Domain Controller, iki şubede birer RODC (Read-Only Domain Controller). RODC, şubeye konan salt okunur bir dizin kopyasıdır; kendisi değişiklik üretmez, merkezden replikasyon alır ve şubedeki kullanıcıların oturum açmasını yerelden karşılar. Amaç, her oturum açma isteğini merkeze taşıyıp şube hattını meşgul etmemektir.

Ortam yıllar içinde çok fazla dikkatsiz müdahale görmüştü ve tuhaf olan şuydu: iki RODC’den biri sorunsuz çalışıyordu, diğeri sürekli arıza veriyordu. Aynı domain, aynı merkez, aynı yapılandırma, farklı davranış.

Sorunlu RODC’de belirti grup ilkelerindeydi: politikalar ya hiç uygulanmıyor ya da yarım uygulanıyordu. Burada dört soruyu bilmek doğrudan işe yaradı, çünkü grup ilkesi bir dizin sorusu değildir. Dizinde politikanın tanımı durur, ama politikanın dosyaları SYSVOL paylaşımında durur ve oraya SMB ile ulaşılır. Yani bakılacak yer dizin değil, paylaşım katmanıydı.

SYSVOL içeriğine baktığımda tablo netleşti: grup ilkelerinin yarısı fiziksel olarak orada yoktu. Her GPO, SYSVOL altında kendi GUID’iyle adlandırılmış bir klasörde durur; o klasörlerin bir kısmı sorunlu RODC’ye hiç ulaşmamıştı. Dizin tarafı politikaların var olduğunu söylüyordu, paylaşım tarafında ise dosyaları yoktu. İstemci de haliyle uygulayamıyordu ve ürettiği hata mesajının içinde ne “SYSVOL” ne “SMB” geçiyordu.

Buradan sonrası bir onarım kararıydı ve onarmamayı seçtik. Yıllarca birikmiş müdahalelerin üstünde replikasyon durumunu tek tek elle düzeltmek, günler sürecek ve sonunda güvenilirliği yine tartışmalı kalacak bir işti. Kararı kolaylaştıran şey, sorunlu sunucunun bir RODC olmasıydı: salt okunur bir kopyada kaybedilecek özgün veri yoktur, çünkü üzerindeki her şeyin aslı zaten merkezdedir. Sunucu sıfırdan kuruldu, güncel sunucu sürümüne çekildi ve domain’e RODC olarak yeniden dahil edildi. Bozulmuş dosyalar, yarım kalmış replikasyon ve ne zaman girdiği bilinmeyen artıklar tek hamlede ortadan kalktı; eksik GPO’lar merkezden temiz bir kopya olarak yeniden geldi.

Bu vakanın asıl dersi kurulum yöntemi değil. Protokollerin hangi soruyu cevapladığını bilmek, arıza anında sizi tahminden ölçüme geçiren şeydir. O bilgi olmadan aynı arıza günlerce dizin ayarlarında aranabilirdi, çünkü belirti oradan geliyormuş gibi görünüyordu. Bu makalede LDAP’ı bu kadar ayrıntılı ele almamızın sebebi de bu: bir protokolü tanımak, onu kurmak için değil, bozulduğunda nereye bakmayacağınızı bilmek için gereklidir.

Bunun pratik sonucu şu: bir uygulamanın “LDAP entegrasyonu” var demek, o uygulamanın Active Directory’ye bağlanabildiği anlamına gelir ama nasıl bağlandığını söylemez. Uygulama dizini yalnızca okuyor da olabilir, kullanıcı parolasını dizine doğrulatıyor da olabilir. İkisi bambaşka güvenlik sonuçları doğurur ve aradaki farkı bu makalenin bind bölümünde göreceksiniz.

Ters yönü de doğru: LDAP konuşan tek şey Active Directory değildir. OpenLDAP, 389 Directory Server, Apple Open Directory ve pek çok ağ cihazının yerleşik dizini aynı protokolü konuşur. Bir istemci açısından hepsi aynı sorguyu kabul eder; aradaki fark şemada ve öznitelik adlarındadır. Active Directory mimarisinin tamamını Active Directory rehberimizde ele alıyoruz.

LDAP Sorgusu Nasıl Kurulur? Base DN, Scope ve Filtre

Bir LDAP sorgusu üç sorunun cevabından oluşur ve üçünü birlikte vermeden dizinden anlamlı bir sonuç alamazsınız:

  1. Nereden başlayacağım? Bu base DN’dir.
  2. Ne kadar derine ineceğim? Bu scope’tur.
  3. Neye uyanları istiyorum? Bu filtredir.

Kütüphanede de aynı üç soru: hangi bölümden başlayacaksınız, sadece o rafa mı yoksa alt raflara da mı bakacaksınız, ve hangi ölçüte uyan kitapları istiyorsunuz.

Base DN: Aramanın Başladığı Dal

Base DN, aramanın kök alacağı noktadır ve LDAP bu noktanın altında olmayan hiçbir şeyi göstermez. Bu cümle teşhis bölümünün yarısını açıklar, o yüzden altını çiziyorum: yanlış base DN bir hata üretmez, sadece boş sonuç üretir.

Domain’in tamamında arama yapmak istiyorsanız base DN domain kökü olur:

LDAP
DC=ad,DC=sercebilisim,DC=com

Yalnızca belirli bir birimde arayacaksanız o birimin DN’i olur:

LDAP
OU=Genel_Mudurluk,OU=Lokasyonlar,DC=ad,DC=sercebilisim,DC=com

Base DN’i dar tutmak iki işe yarar: sorgu hızlanır ve uygulamanın göreceği kullanıcı kümesi sınırlanır. Bir uygulamayı dizine bağlarken base DN’i domain köküne kurmak en kolay yoldur, ama o uygulamaya dizindeki her nesneyi görme imkânı verir.

Burada çoğu zaman geç fark edilen bir bağımlılık var: bu daraltmayı yapabilmenin ön koşulu, OU ağacının o daralmaya izin verecek şekilde tasarlanmış olmasıdır. Kullanıcılar, bilgisayarlar ve gruplar aynı dalın içinde karışık duruyorsa gösterilecek dar bir base DN de yoktur; uygulamaya mecburen domain kökünü verirsiniz. Yani dizin sorgusunun ne kadar isabetli olacağı, sorguyu yazdığınız gün değil, OU yapısını kurduğunuz gün belirlenir. O yapının nasıl tasarlanacağını Active Directory OU yönetimi rehberimizde ele alıyoruz.

Scope: Ne Kadar Derine İnilecek?

Arama kapsamı üç değerden biridir ve aralarındaki fark, “sorgu neden boş döndü” sorusunun en sık ikinci cevabıdır:

ScopeNe yaparKütüphane karşılığı
baseYalnızca base DN’in kendisine bakarSadece o tek fişi oku
oneYalnızca bir alt seviyeye bakarSadece o raftakiler, diğer raflara bakılmaz
subBase DN’in altındaki her şeye bakarO bölüm ve altındaki tüm raflar
Aynı dizin ağacında üç arama kapsamının kapsadığı düğümler. Base kapsamı yalnız base DN'in kendisine bakar ve altındaki hiçbir kullanıcıyı görmez, sonuç sıfırdır. One kapsamı yalnız bir alt seviyeye bakar; oradaki üç kullanıcıyı bulur ama alt OU'nun içine girmez, sonuç üçtür. Sub kapsamı base DN'in altındaki her şeye bakar, alt OU'nun içindeki kullanıcıyı da görür, sonuç dörttür. base one sub ou=Kullanicilar ou=Kullanicilar ou=Kullanicilar 0 kullanıcı 3 kullanıcı 4 kullanıcı yalnız base DN'in kendisi alt OU'nun içine girmez altındaki her şey kullanıcı alt OU Aynı base DN, aynı dizin. Değişen tek şey ne kadar derine inildiği. Aynı dizin ağacında üç arama kapsamının kapsadığı düğümler. Base kapsamı yalnız base DN'in kendisine bakar ve altındaki hiçbir kullanıcıyı görmez, sonuç sıfırdır. One kapsamı yalnız bir alt seviyeye bakar; oradaki üç kullanıcıyı bulur ama alt OU'nun içine girmez, sonuç üçtür. Sub kapsamı base DN'in altındaki her şeye bakar, alt OU'nun içindeki kullanıcıyı da görür, sonuç dörttür. base one sub ou=Kullanicilar ou=Kullanicilar ou=Kullanicilar 0 kullanıcı · yalnız base DN'in kendisi 3 kullanıcı · alt OU'nun içine girmez 4 kullanıcı · altındaki her şey Aynı dizin. Değişen tek şey ne kadar derine inildiği.
Lab ölçümünün görsel karşılığı: one alt OU'ya taşınan kullanıcıyı görmez ve üç sonuç döner, sub dört. Sorgunun kendisi ve base DN her üçünde de aynı.

Pratikte çoğu zaman istediğiniz sub’dur ve yaygın istemcilerin varsayılanı da odur. one ise genellikle kazara değil, kasten seçilir ve iyi bir sebebi vardır: bir uygulamaya dizinin yalnızca belirli bir katmanını göstermek. Örneğin ou=Kullanicilar altında bir de ou=Ayrilanlar ya da ou=Servis_Hesaplari dalı varsa, one seçmek o dalları sorgunun dışında bırakır. Aynı mantıkla bir güvenlik duvarına VPN yetkilendirmesi için yalnızca ana kullanıcı katmanını gösterip alt dalları gizleyebilirsiniz.

Tehlike de tam buradan doğuyor: ayar doğru sebeple konur, sonra dizin değişir ve kimse ayarı hatırlamaz. Bunu lab ortamında ürettim. ou=Kullanicilar altında üç kullanıcı varken bir şube açıldığını ve o şubenin kullanıcılarının alt bir OU’ya taşındığını varsaydım. Aynı base DN, aynı filtre, tek fark arama kapsamı:

Çıktı
--- scope = one ---
cn: Ilker Pehlivan
cn: Aysegul Demir
cn: Mehmet Kaya
sonuc sayisi: 3

--- scope = sub ---
cn: Ilker Pehlivan
cn: Aysegul Demir
cn: Mehmet Kaya
cn: Zeynep Arslan
sonuc sayisi: 4

Şube çalışanı Zeynep Arslan, one sorgusunda hiç görünmüyor. Kritik olan ise iki sorgunun da başarıyla tamamlanmış olması:

Çıktı
one  -> exit code 0
sub  -> exit code 0

Yani sunucu bir şeyin eksik olduğunu bilmiyor bile. Sorulan soruya doğru cevap verdi: “bu dalın bir seviye altında kim var?” Zeynep iki seviye altındaydı, o kadar.

Sahadaki karşılığı şu senaryodur ve teşhisi zorlaştıran şey de budur: uygulama aylarca sorunsuz çalışır, sonra yeni bir şube açılır ya da kullanıcılar lokasyona göre yeniden düzenlenir, ve yalnızca yeni gelenler sisteme giremez. Hiçbir ayar değiştirilmemiştir, hiçbir hata kaydı düşmez; değişen tek şey dizinin şeklidir. “Eski çalışanlar giriyor, yeni işe girenler giremiyor” şikâyetinin en sık sebeplerinden biri budur.

Filtre: Hangi Ölçüte Uyanlar

LDAP filtreleri parantezli bir sözdizimi kullanır ve ilk bakışta yabancı görünür. Kuralı basit: her koşul kendi parantezine girer, operatör en başa yazılır.

En sık kullanacağınız kalıplar:

LDAP
(objectClass=user)
(sAMAccountName=ilker)
(&(objectClass=user)(memberOf=CN=VPN_Kullanicilari,OU=Gruplar,DC=ad,DC=sercebilisim,DC=com))
(|(sAMAccountName=ilker)(mail=ilker@sercebilisim.com))
(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))

Sırayla ne yaptıklarına bakalım:

  1. Birinci satır tüm kullanıcı nesnelerini getirir. Tek koşul, tek parantez.
  2. İkinci satır oturum açma adı ilker olan kaydı bulur.
  3. Üçüncü satır iki koşulu birleştirir: & işareti “ve” demektir, yani hem kullanıcı olacak hem de belirtilen gruba üye olacak. Grup üyeliği DN ile yazılır, grup adıyla değil.
  4. Dördüncü satır | işaretiyle “veya” kurar: adı ilker olan ya da e-postası eşleşen kayıt.
  5. Beşinci satır devre dışı hesapları eler. ! işareti “değil” demektir; içindeki uzun sayı dizisi ise userAccountControl alanındaki tek bir biti sınayan özel bir eşleştirme kuralıdır.

Beşinci satır ilk bakışta korkutucu görünür ama sahada en çok işinize yarayacak olan odur. Bir uygulamayı dizine bağladığınızda varsayılan filtre genellikle tüm kullanıcıları çeker ve işten ayrılmış, hesabı devre dışı bırakılmış kişiler de o listeye girer. Uygulama tarafında hâlâ görünen ayrılmış çalışan kayıtlarının klasik sebebi budur.

LDAP Bind: Dizine Kimliğinizi Nasıl Kanıtlarsınız?

Bind, bir LDAP oturumunun açılış adımıdır: istemci sunucuya bağlanır ve “ben kimim” der. Sorgu ancak bundan sonra başlar. Kütüphane karşılığı, katalog terminaline oturmadan önce danışmadan geçmek.

Üç tür bind vardır ve aralarındaki fark, bu makalenin güvenlik bölümünün tamamının temelidir.

Anonim Bind

İstemci hiçbir kimlik sunmaz. Dizinin herkese açık bıraktığı kadarını görür, gerisini göremez. Kütüphanedeki halka açık katalog terminali gibidir: rafların düzenini görürsünüz, ödünç alma kayıtlarını göremezsiniz.

Modern Active Directory kurulumlarında anonim bind büyük ölçüde kapalıdır. Yalnızca RootDSE denilen, sunucunun kendini tanıttığı en üst kayıt anonim okunabilir; dizinin geri kalanı için kimlik gerekir.

Simple Bind

İstemci bir DN ve bir parola gönderir. Adı gibi basittir ve bu makalenin en kritik cümlesi buraya ait: simple bind’de parola, protokolün içinde şifrelenmez.

Şifreleme varsa taşıma katmanından gelir, yani LDAPS veya StartTLS kullanılıyor olmalıdır. Düz 389 üzerinde yapılan bir simple bind işleminde parola ağda okunabilir halde gider. Bunu bir sonraki bölümde iddia olarak değil, yakalanmış paket olarak göstereceğiz.

Kütüphane karşılığı şu: üye kartınızı gösterirken şifrenizi bankonun önünde yüksek sesle söylemek. İşlem yürür, kimse itiraz etmez, ama sırada bekleyen herkes duymuştur.

SASL Bind

SASL (Simple Authentication and Security Layer), kimlik doğrulamayı protokolün dışına çıkaran bir çerçevedir. LDAP “kimliği şu mekanizma doğrulasın” der ve işi ona devreder. Active Directory ortamında bu mekanizma genellikle Kerberos’tur ve aradaki bağlantıyı GSSAPI adlı standart arayüz kurar; Wireshark yakalamalarında Windows istemcilerin bind satırlarında bu ismi görürsünüz.

Avantajı net: parola hiçbir aşamada ağa çıkmaz. Windows makinelerin dizine bağlanırken kullandığı yöntem varsayılan olarak budur ve siz hiçbir şey yapmadan çalışır. Sorun, üçüncü taraf uygulamalarda başlar: pek çok uygulama SASL desteklemez ve size yalnızca “sunucu, kullanıcı adı, parola” alanları sunar. O andan itibaren simple bind’e mahkûmsunuz ve tek koruma taşıma katmanındadır.

LDAP, LDAPS ve StartTLS: 389, 636 ve 3268 Portları

Üç port ve iki şifreleme yöntemi var; ikisini karıştırmak sahada yanlış firewall kuralı yazmanın bir numaralı sebebi.

PortNeŞifreleme
389LDAPYok (StartTLS ile sonradan kurulabilir)
636LDAPSBağlantı en baştan TLS içinde
3268Global CatalogYok
3269Global Catalog over SSLVar

LDAPS ile StartTLS aynı işi iki farklı sırayla yapar:

  • LDAPS (636), bağlantıyı en baştan TLS içinde kurar. Önce şifreli tünel açılır, LDAP konuşması o tünelin içinde başlar. İsimlendirmesi HTTPS ile aynı mantıktadır.
  • StartTLS (389), önce düz bağlantı kurar, sonra “şimdi şifrelemeye geçelim” komutu gönderir ve aynı bağlantı şifreliye yükseltilir. Ayrı port istemez.

İkisi de aynı güvenlik seviyesini sağlar ve ikisi de sunucuda bir sertifika ister. O sertifikanın nereden geleceği ayrı bir karardır: kendi iç sertifika otoritenizden mi, dışarıdan mı, yoksa self-signed mı; üçünün hangisinin ne zaman doğru olduğunu sertifika otoritesi rehberimizde ele alıyoruz. Aradaki fark pratiktir: LDAPS ayrı bir port olduğu için firewall’da ayrı kural gerektirir, StartTLS ise mevcut 389 kuralını kullanır ama uygulamanın StartTLS desteklemesi şarttır.

StartTLS’in isteğe bağlı olduğunu lab’da ölçtük ve sonuç, bu bölümdeki uyarının neden önemli olduğunu tek başına açıklıyor. Aynı sunucuya, aynı 389 portundan, aynı sorguyu iki kez gönderdik:

Çıktı
ldapsearch -x -ZZ -H ldap://127.0.0.1:389 ...   -> sonuc geldi (sifreli)
ldapsearch -x     -H ldap://127.0.0.1:389 ...   -> sonuc geldi (duz metin)

-ZZ parametresi “önce StartTLS’e geç, geçemezsen bağlanma” demektir. İki komut da aynı kaydı döndürdü; tek fark, birinde trafiğin şifrelenmiş olması. Yani sunucu şifrelemeyi destekliyor olsa bile düz bağlantıyı reddetmiyor: şifrelemeyi isteyip istememe kararı tamamen istemcide. Sunucuda sertifika kurulu olması, o sunucuya yapılan bağlantıların şifreli olduğu anlamına gelmez.

Ölçtük: Açık Port, Çalışmayan Servis

Kendi lab Domain Controller’ımıza iki soru sorduk ve aldığımız iki cevap birbiriyle çelişti:

SoruCevap
Portlar açık mı?389, 636, 3268 üçü de açık
636 gerçekten şifreli bağlantı kuruyor mu?Hayır. Denenen dört TLS sürümünde de reddetti

Birinci satıra bakıp “LDAPS çalışıyor” demek en kolay yanılgı. Port testi yalnızca kapının açık olduğunu söyler, arkasında birinin oturup oturmadığını değil.

Asıl cevap ikinci satırda. Sunucu bağlantıyı şifreleme anlaşması sırasında kapatıyor ve dört sürümün dördünde de tam aynı noktada kopuyor. Bu ayrıntı sebebi de ele veriyor: sorun sürüm uyuşmazlığı olsaydı en az biri farklı davranırdı. Eksik olan şey sertifika. Lab’daki DC’de henüz iç sertifika otoritesi kurulmadı ve LDAPS sertifikasız çalışmaz.

Sahadaki karşılığı bir teşhis tuzağı, üstelik kimse yanlış bir şey yapmadan:

  • Firewall’u yazan kişi portu açar, testi geçer, işini bitmiş sayar.
  • Uygulamayı kuran kişi ldaps:// yazar, bağlanamaz, hatayı uygulamada arar.
  • Aradaki katman, yani sertifika, ikisinin de kontrol listesinde yoktur.

Sonu hep aynı yere çıkar: ldaps:// çalışmayınca ldap:// denenir, o çalışır, yapılandırma öylece kalır. Şifreleme çalışmadığı için değil, kimse neden çalışmadığını araştırmadığı için terk edilir.

Global Catalog: 3268 Neden Var?

Global Catalog, bir ormandaki (forest) tüm domain’lerin nesnelerinin kısmi bir kopyasını tutan özel bir dizindir. Her nesnenin her özniteliğini değil, en sık aranan özniteliklerini içerir.

Kütüphane karşılığı şu: her şubenin kendi tam kataloğu vardır, ama bir de bütün şubelerin ortak özet kataloğu vardır. Hangi kitabın hangi şubede olduğunu tek bakışta oradan öğrenirsiniz; kitabın tüm ayrıntısı için asıl şubeye gitmeniz gerekir.

Pratik sonucu şu: tek domain’li ortamlarda 3268 ile 389 arasında fark hissetmezsiniz. Çok domain’li bir ormanda ise 389 yalnızca kendi domain’ini görür ve diğer domain’lerdeki kullanıcılar sorguda çıkmaz. Bir uygulamanın “bazı kullanıcıları göremiyorum” şikâyeti çok domain’li ortamlarda çoğu zaman buradan gelir.

Buradaki tuzak, 3268’in de şifresiz olmasıdır. Çok domain’li bir ortamda uygulamayı Global Catalog’a çevirdiğinizde kullanıcı görünürlüğü sorununu çözersiniz, ama bunu yaparken bağlantıyı yine düz metne kurmuş olursunuz. Şifreli karşılığı 3269’dur ve 389 ile 636 arasındaki ilişkinin aynısı burada da geçerlidir: port numarasını değiştirmek tek başına şifreleme getirmez, şifreli olanı seçmek gerekir.

Sahadan: LDAPS’e Direnç Neden Vahim Bir Karar?

Yıllarca firewall üzerinde AD kimlikleriyle otomatik VPN yetkilendirmesi kurdum. Kurgu şuydu: firewall’daki LDAP Servers tanımı Domain Controller’ı gösterir, kullanıcı VPN’e bağlanmak istediğinde firewall dizine sorar, kişi VPN_Kullanicilari grubundaysa erişim açılır. Kullanıcı yönetimi tek yerden yürür, ayrı bir VPN kullanıcı listesi tutulmaz. Temiz bir tasarım.

Bu kurgunun taşıdığı yük fark edilenden büyüktür. Firewall dizine bir servis hesabıyla bağlanır ve o hesabın parolası cihazın yapılandırmasında durur. Bağlantı 389 üzerinden kuruluyorsa, firewall her sorguda o parolayı ağa açık halde yazar.

Buna rağmen bazı BT yöneticilerinin LDAPS’e geçmemek için direndiğini gördüm. Gerekçe her seferinde aynıydı: “çalışıyor, dokunmayalım.” Sertifika üretmek fazladan bir işti, geçiş sırasında VPN’in kesilmesi riski vardı ve düz bağlantı yıllardır sorunsuz görünüyordu.

Buradaki yanılgı, riskin görünmemesini riskin yokluğu sanmak. Ortadaki adam (man-in-the-middle) saldırısında saldırganın önündeki iş şaşırtıcı derecede kolaydır:

  • Dizinde yetkisi olması gerekmez. Hiçbir hesabı olmayan biri de o trafiği okuyabilir.
  • Parola kırması gerekmez. Parola şifrelenmiş değil ki kırılsın; olduğu gibi geçiyor.
  • Tek koşul aynı ağ segmentinde bulunmaktır. Yanlış VLAN’a bağlanmış bir switch portu ya da yönetimden çıkmış bir erişim noktası bu koşulu sağlar.

Ele geçen şey de sıradan bir kullanıcı parolası değil, dizini geniş yetkiyle okuyan bir servis hesabıdır.

Tavsiyem nettir ve tartışmaya açmıyorum: dizine bağlanan her uygulama LDAPS ya da StartTLS kullanmalıdır. Geçişin maliyeti bir sunucu sertifikasıdır ve iç sertifika otoritesi kurulmuşsa o maliyet sıfıra yakındır. Karşılığında ağda dolaşan bir servis hesabı parolasından kurtulursunuz. Bu takas, kurumsal ağda düşünmeye değer bir takas bile değildir.

Şifreleme burada tek başına yeterli de değil, çünkü asıl mesele o hesabın ne kadar yetkili olduğu. Dizine bağlanan bir uygulamanın servis hesabı çoğu ortamda ihtiyacından fazla yetkiyle tanımlanır ve yıllarca öyle kalır; parolası ele geçmese bile o hesap başlı başına bir risktir. Servis ve ayrıcalıklı hesapların yetkisinin nasıl daraltılacağını, izleneceğini ve hangi katmanda tutulacağını Active Directory güvenlik sıkılaştırması rehberimizde ele alıyoruz.

LDAP Trafiğini Paket Düzeyinde İzlemek

Bu bölüm protokolü anlatmıyor, gösteriyor. Yukarıda “simple bind’de parola şifrelenmez” dedik; şimdi o cümlenin ağdaki karşılığını paket paket açacağız. Bir kez gördükten sonra ldap:// ile ldaps:// arasındaki farkı bir daha tercih meselesi olarak görmezsiniz.

Ölçümlerin tamamı kendi lab ortamımızda üretildi ve kurgu bilinçli olarak iki işletim sistemine yayıldı:

  • Dizin sunucusu: openldap, Ubuntu 24.04 üzerinde OpenLDAP, 192.168.1.25. Base DN dc=lab,dc=sercebilisim,dc=com.
  • İstemci: Windows iş istasyonu, 192.168.1.115. Sorguları .NET’in System.DirectoryServices.Protocols kütüphanesiyle attı.
  • Yakalama: Sunucu tarafında tcpdump, çözümleme tshark 4.2.2.

Bu ayrıntı önemli: istemci Windows, sunucu Linux ve arada hiçbir uyarlama katmanı yok. Aynı sorgu, aynı sözdizimiyle, aynı port üzerinden çalışıyor. LDAP’ın protokol olmasının pratik anlamı budur; bir ürünün özelliği olsaydı iki taraf birbirini anlamazdı.

Düz Bağlantı: 389 Üzerinde Ne Görünüyor?

Önce klasik kurulum: istemci 389 portuna bağlanıyor, simple bind ile kimlik sunuyor, sonra bir kullanıcı arıyor. Yakalanan akış şu. Okumadan önce üç şeyi bilmek yeterli:

  • Her satır bir LDAP mesajıdır. Baştaki sayı çerçeve numarası, yani paketin yakalamadaki sırası.
  • 192.168.1.115 istemci, 192.168.1.25 dizin sunucusu. Ok yönü kimin konuştuğunu gösterir.
  • Sondaki isim mesajın tipidir. bindRequest, searchRequest gibi. Bunlar protokolün sabit isimleri.
Çıktı
 4  192.168.1.115 → 192.168.1.25  bindRequest(1) "uid=ilker,ou=Kullanicilar,dc=lab,dc=sercebilisim,dc=com" simple
 6  192.168.1.25  → 192.168.1.115 bindResponse(1) success
 7  192.168.1.115 → 192.168.1.25  searchRequest(2) "dc=lab,dc=sercebilisim,dc=com" wholeSubtree
 8  192.168.1.25  → 192.168.1.115 searchResEntry(2) "uid=aysegul,ou=Kullanicilar,dc=lab,dc=sercebilisim,dc=com"
 9  192.168.1.25  → 192.168.1.115 searchResDone(2) success  [1 result]
11  192.168.1.115 → 192.168.1.25  unbindRequest(3)

Altı satırın hikâyesi sırayla şu:

  1. Çerçeve 4: İstemci kimliğini sunuyor. Sondaki simple kelimesi bind türünü söylüyor ve bu makalenin geri kalanının anahtarı.
  2. Çerçeve 6: Sunucu kabul ediyor. Bind başarılı, oturum açıldı.
  3. Çerçeve 7: Asıl sorgu. Base DN domain kökü, kapsam wholeSubtree, yani makalenin başında anlattığımız sub.
  4. Çerçeve 8: Eşleşen tek kayıt dönüyor. Sonucun kendisi de açık halde görünüyor.
  5. Çerçeve 9: Arama bitti, bir sonuç bulundu.
  6. Çerçeve 11: İstemci oturumu kapatıyor.

Buraya kadar her şey normal. Sorun, dördüncü satırın içine bakınca başlıyor.

Parola Pakette Duruyor

bindRequest mesajının içindeki iki alanı çıkardığımda dönen sonuç bu:

Çıktı
uid=ilker,ou=Kullanicilar,dc=lab,dc=sercebilisim,dc=com    LabParola123

Soldaki bind DN, sağdaki parolanın kendisi. Şifrelenmiş değil, karma alınmış (hash) değil, kodlanmış bile değil. Aynı paketin ham hex dökümünde de aynen okunuyor:

Çıktı
0060  6c 61 72 2c 64 63 3d 6c 61 62 2c 64 63 3d 73 65   lar,dc=lab,dc=se
0070  72 63 65 62 69 6c 69 73 69 6d 2c 64 63 3d 63 6f   rcebilisim,dc=co
0080  6d 80 0c 4c 61 62 50 61 72 6f 6c 61 31 32 33      m..LabParola123

Sağdaki sütun, soldaki byte’ların okunabilir karşılığı. Son satırın sonundaki LabParola123, ağ kablosundan geçen baytların birebir kendisi. Bu paketi yakalayan birinin şifre kırmasına, sözlük saldırısı yapmasına ya da herhangi bir çaba harcamasına gerek yok; sadece okuması yeterli.

Aynı paketin Wireshark arayüzündeki hali de bunu doğruluyor. Parolayı bulmak için özel bir filtre yazmak, veriyi dışa aktarmak ya da bir çözümleme aracı kurmak gerekmiyor: paketi seçip ağacı açmak yetiyor, simple alanının değeri orada duruyor.

Wireshark'ta LDAP simple bind paketi: bindRequest ağacında açık metin görünen parola alanı ve hex dökümünde aynı baytların karşılığı
Alanın adı zaten 'simple'. Wireshark parolayı gizlemiyor, çünkü protokol onu gizlemek üzere tasarlanmamış.

Kütüphane karşılığını makalenin başında kurmuştuk: üye kartınızı gösterirken şifrenizi bankonun önünde yüksek sesle söylemek. Fark şu ki ağda “sıranın önü” diye bir şey yok; aynı anahtarı dinleyen herkes aynı mesafede.

Aynı Ağdaki Windows Ne Yapıyor?

Bu yakalamanın en öğretici kısmı, aslında planlamadığımız bir şeydi. Filtreyi dar tutmadığımız için dosyaya başka bir makinenin trafiği de karıştı: aynı ağdaki bir Windows sunucusunda o sırada oturum açılmıştı ve makine, Domain Controller’ın dizinine bir dizi sorgu gönderiyordu.

İlginç olan, o sorguların ne olduğu değil, okunamıyor olmasıydı:

Çıktı
26  bindRequest(3)  "<ROOT>"  sasl
28  bindResponse(3) success
29  SASL GSS-API Integrity: searchRequest(4) "<ROOT>" baseObject
33  SASL GSS-API Integrity: searchRequest(6) "CN=NTDS Settings,..."
35  SASL GSS-API Integrity: searchRequest(7) "CN=Public Key Services,..."

Üç satırda okunması gereken üç şey var:

  1. bindRequest ... sasl: Windows kimliğini simple ile değil SASL ile sunuyor. Yani parolasını göndermiyor, Kerberos biletiyle kanıtlıyor.
  2. SASL GSS-API Integrity: Bind’den sonraki bütün sorgular bu etiketle geçiyor. Wireshark mesaj tipini görebiliyor ama içeriğini açamıyor.
  3. Sorgunun kendisi görünüyor, cevabı görünmüyor. Hangi nesnenin sorulduğu okunur kalıyor, taşınan veri korunuyor.

Yani tek bir yakalama dosyasında, aynı ağda, birkaç saniye arayla iki farklı dünya yan yana durdu:

Bind türüParola ağdaSorgu içeriği
Windows makine → Domain ControllerSASLYokKorunuyor
Bizim istemci → dizin sunucususimpleAçık metinOkunabiliyor

Buradan çıkan sonuç, bu makalenin belki de en önemli cümlesi: sorun LDAP protokolünde değil, protokolün nasıl kullanıldığında. Aynı ağ, aynı protokol, aynı port numarası; biri parolayı hiç göndermiyor, diğeri düz metin yazıyor. Windows istemciler bunu siz hiçbir şey yapmadan doğru tarafta yaparlar. Yanlış tarafta kalan, kendisine yalnızca “sunucu, kullanıcı adı, parola” alanları sunulan üçüncü taraf uygulamalardır: firewall, yardım masası, İK yazılımı, yazıcı sunucusu.

Şifreli Bağlantı: Aynı Bind, 636 Üzerinde

Şimdi tek bir şeyi değiştiriyorum: aynı istemci, aynı kullanıcı, aynı parola, aynı sorgu. Yalnızca port 636 ve bağlantı LDAPS. Yakalanan trafik şu:

Çıktı
 1  55204 → 636  [SYN]
 2  636 → 55204  [SYN, ACK]
 4  TLSv1    Client Hello
 6  TLSv1.3  Server Hello
 7  TLSv1.3  Change Cipher Spec
 9  TLSv1.3  Application Data
10  TLSv1.3  Application Data
12  TLSv1.3  Application Data

Bu listede dikkat çeken şey, ne olduğu değil ne olmadığı. Bir tane bile bindRequest satırı yok. searchRequest yok, dönen kayıt yok, kullanıcı adı yok. TLS el sıkışmasından sonra geriye kalan her şey Application Data, yani çözümlenemeyen şifreli yük. El sıkışmanın kendisinde ne pazarlandığını ve hangi sürümün ne kadarını şifrelediğini ayrı bir yazıda paket düzeyinde açtık.

İki yakalamayı aynı ölçütlerle karşılaştırdığımda tablo şöyle çıkıyor:

389 (LDAP)636 (LDAPS)
LDAP olarak çözümlenen paket60
Bind DN görünüyor muEvetHayır
Parola ham veride bulunuyor muEvetHayır
Sorgu ve dönen kayıt okunabiliyor muEvetHayır
TLS sürümüYokTLS 1.3
ŞifrelemeYokAES-256

Parolayı ham veride aradığımda 389 yakalamasında bulundu, 636 yakalamasında sıfır eşleşme döndü.

Aradaki tek fark bir portun numarası ve bir sertifikanın varlığı. Dizinin içeriği, kullanıcı, parola, sorgu, hepsi aynı. Şifrelemenin maliyeti bu kadarken, şifrelememenin maliyeti yukarıdaki hex dökümü.

Bu ölçümü makalenin başındaki saha hikâyesiyle birlikte okuyun: firewall dizine bir servis hesabıyla bağlanıyordu ve o bağlantı 389 üzerindeydi. Yukarıdaki hex satırında görünen şey sıradan bir kullanıcının parolası olsaydı zarar sınırlı olurdu. Orada görünen şey, dizini geniş yetkiyle okuyan hesabın parolasıdır.

LDAP Teşhisi: Boş Dönen Sorgular ve Bind Hataları

LDAP arızalarının teşhisi zordur, çünkü protokolün en sık karşılaşılan iki arızası hata üretmez. Yanlış base DN boş sonuç döndürür, dar scope boş sonuç döndürür; ikisi de teknik olarak başarılı bir sorgudur. Uygulama tarafındaki belirti ise “kullanıcılar gelmiyor” olur ve log dosyasında hiçbir şey yoktur.

Bu yüzden teşhis, hata mesajından değil belirtiden başlar.

BelirtiMuhtemel sebepİlk bakılacak
Sorgu hata vermiyor, sonuç boşYanlış base DN ya da dar scopeBase DN’i domain köküne alıp tekrar dene
Kullanıcıların bir kısmı geliyor, bir kısmı gelmiyorScope one, kullanıcılar alt OU’lardaScope’u sub yap
Ayrılmış çalışanlar listede görünüyorFiltre devre dışı hesapları elemiyorFiltreye userAccountControl koşulu ekle
Bağlantı hiç kurulmuyorPort kapalı ya da yanlış sunucu adı389 / 636 erişimini ölç
636 açık ama TLS kurulmuyorSunucuda geçerli sertifika yokSertifika deposunu kontrol et
Çok domain’li ortamda eksik kullanıcıSorgu 389’a gidiyor3268 (Global Catalog) kullan

Bind Hata Kodlarının Okunuşu

Önce bu kodların nereden okunduğunu netleştirelim, çünkü sık karıştırılır: bunlar Windows olay günlüğünde (Event Viewer) tutulan kayıtlar değildir. Sunucunun bind isteğine verdiği cevabın içinde gelirler. Yani şu üç yerde gördüğünüz şey aynı kaynağa dayanır:

  • Uygulamanın dizin ayarlarında Bağlantıyı test et dediğinizde ekrana düşen hata mesajı.
  • Wireshark yakalamasında bindResponse paketinin içi.
  • Uygulamanın kendi log dosyasına yazdığı satır (sunucunun mesajını olduğu gibi aktarıyorsa).

Bind başarısız olduğunda dönen kod, sorunun kimlikte mi yoksa yetkide mi olduğunu söyler. Active Directory bu kodların yanına kendi alt kodunu da ekler ve asıl bilgi orada durur:

KodAnlamıGerçek sebep
49Invalid credentialsKimlik bilgisi hatalı, alt koda bakılmalı
49 + data 52eKimlik geçersizParola yanlış ya da kullanıcı hiç yok
49 + data 532Parolanın süresi dolmuşServis hesabına süresiz parola politikası uygulanmamış
49 + data 533Hesap devre dışıServis hesabı kapatılmış
49 + data 701Hesabın süresi dolmuşHesaba bitiş tarihi tanımlanmış
49 + data 775Hesap kilitliYanlış parola denemeleri hesabı kilitlemiş
32No such objectBase DN dizinde yok
50Insufficient access rightsBind başarılı ama o dalı okuma yetkisi yok

İkinci satır, bu makale için lab ortamında ölçtüğümüz ve yaygın kanıyı düzelten sonuçtur. İnternetteki pek çok tabloda data 525 kodu “kullanıcı bulunamadı”, data 52e ise “parola yanlış” diye ayrı ayrı listelenir ve teşhiste bu ayrımın işinize yarayacağı söylenir.

Bunu kendi Domain Controller’ımızda sınadım. Altı farklı bind denemesi yaptım: var olmayan bir DN, var olmayan bir ad\kullanici adı, var olmayan bir UPN, sonra da gerçekten var olan bir hesabı üç ayrı biçimde yazıp kasten yanlış parola verdim. Sonuç altısında da aynı çıktı:

Çıktı
1) Olmayan DN            => kod 49, data 52e
2) Var olan + yanlis     => kod 49, data 52e
3) Olmayan ad\user       => kod 49, data 52e
4) Olmayan UPN           => kod 49, data 52e
5) Var olan UPN          => kod 49, data 52e
6) Var olan tam DN       => kod 49, data 52e

Sunucunun döndürdüğü ham mesaj da her seferinde birebir aynıydı:

Çıktı
80090308: LdapErr: DSID-0C09055B, comment: AcceptSecurityContext error, data 52e, v65f4

Yani Active Directory, “böyle bir kullanıcı yok” ile “parola yanlış” arasında ayrım yapmıyor. Bu bir eksiklik değil, kasıtlı bir güvenlik davranışıdır: ayrım yapsaydı, bir saldırgan parolayı hiç bilmeden yalnızca hata kodlarına bakarak dizindeki geçerli kullanıcı adlarını tek tek tespit edebilirdi. Buna kullanıcı numaralandırma (user enumeration) denir ve LDAP’ın internete açık olduğu ortamlarda gerçek bir risktir.

Kütüphanenin danışması da böyle davranır: “böyle bir üyemiz yok” demek, sormakla kimin kayıtlı olduğunu öğrenebileceğiniz anlamına gelirdi. Onun yerine tek bir cevap verir, “giriş yapamazsınız”. Hangi kısmın tutmadığını söylemez, çünkü söylemesi kendi kayıtlarını ele verir.

Teşhis açısından pratik sonucu şu: 52e gördüğünüzde refleks olarak parolayı yenilemeyin. O kod size yalnızca “bu ikiliyle giriş olmadı” der; bind DN’in kendisi yanlış yazılmış olabilir ve parolayı kaç kez sıfırlarsanız sıfırlayın sonuç değişmez. Doğru hamle DN’i bağımsız olarak doğrulamaktır: nesnenin distinguishedName alanını konsoldan kopyalayıp bire bir karşılaştırın.

Tablodaki diğer alt kodlar (532, 533, 701, 775) Microsoft’un dokümantasyonundan alınmıştır ve bu lab’da üretilmemiştir. Bunlar hesabın durumuna ilişkin olduğu için ayrım yapılabilir kodlardır: parola doğru olduğunda AD hesabın kilitli ya da devre dışı olduğunu söylemekten çekinmez, çünkü o noktada kimliği zaten kanıtlamışsınızdır.

Bu kodların kaynağını bilmek, tabloyu ezberlemekten daha işe yarar: data alanındaki değerler LDAP’a özgü değildir, Windows’un genel sistem hata kodlarının onaltılık (hex) yazımıdır. Yani 52e gördüğünüzde 0x52E demektir ve onluk karşılığı 1326’dır; o da Windows’un ERROR_LOGON_FAILURE kodudur. Aynı mantıkla 533 = 1331 = ERROR_ACCOUNT_DISABLED.

Pratik sonucu şu: tabloda olmayan bir kodla karşılaşırsanız çaresiz kalmazsınız. Hex değeri onluğa çevirip Microsoft’un sistem hata kodları listesinde arattığınızda kodun tam adını ve anlamını bulursunuz.

Bir de dikkat çekmeye değer bir asimetri var: 50 kodu, bind’in başarılı olduğu ama sorgunun yetkisiz kaldığı durumdur. Yani kimlik doğru, yetki yetersiz. Uygulama tarafında bu genellikle “bağlandı ama hiçbir şey gelmiyor” şeklinde görünür ve yanlışlıkla base DN sorunu sanılır.

Teşhis Sırası

Bu sırayı bozmayın; her adım bir sonrakinin ön koşuludur ve alttaki katman bozukken üsttekini incelemek zaman kaybıdır.

  1. Port açık mı? Bağlantı hiç kurulamıyorsa dizin ayarlarını incelemenin anlamı yok. 389, 636 ve gerekiyorsa 3268 için TCP erişimini ölçün.
  2. Bind çalışıyor mu? Sorguyu hiç yazmadan önce yalnızca bağlanmayı deneyin. Bind hatası alıyorsanız sorun kimlik tarafındadır ve base DN’e bakmak erkendir.
  3. Base DN doğru mu? Base DN’i geçici olarak domain köküne alın. Sonuç geliyorsa sorun base DN’de, hâlâ boşsa filtrededir.
  4. Filtre ne getiriyor? Filtreyi en yalın haline ((objectClass=user)) indirin ve sonucun geldiğini görün. Sonra koşulları tek tek geri ekleyin.
  5. Şifreleme gerçekten kuruluyor mu? Bağlantı ldaps:// ile tanımlıysa TLS el sıkışmasının tamamlandığını doğrulayın; port açık ama sertifika yoksa bağlantı sessizce düşer.

Bu sıranın kıymeti şu: dördüncü adıma kadar dizinde hiçbir şeyi değiştirmediniz, hiçbir hesabı yeniden oluşturmadınız ve arızanın hangi katmanda olduğunu ölçtünüz. LDAP arızalarında en pahalı hata, ölçmeden müdahale etmektir; servis hesabının parolasını sıfırlamak veya uygulamayı yeniden kurmak genellikle sebebi ortadan kaldırmaz, yalnızca bir süre için belirtiyi siler.

Sonuç: Katalog Doğru Kurulmuşsa Kimse Fark Etmez

LDAP’ı anlaşılmaz kılan şey karmaşıklığı değil, sessizliğidir. Doğru kurulduğunda kimse varlığını fark etmez; kullanıcı gruba eklenir, uygulama onu görür, yetki açılır. Bozulduğunda ise çoğu zaman bir hata mesajı bile üretmez: sorgu başarıyla çalışır ve boş döner.

Bu makalede kurduğumuz zincir tam da bu sessizliği kırmak içindi. Dizinin raf düzeninden DN’e, DN’den sorgunun üç bileşenine, oradan bind türlerine ve şifrelemeye. Bir LDAP arızasıyla karşılaştığınızda soracağınız soru artık “LDAP neden çalışmıyor” değil, “hangi adımda boşaldı” olmalı. İkincisinin cevabı ölçülebilir, birincisininki değil.

Kütüphanenin kataloğu, kitapların nerede olduğunu bilen tek şeydir. Rafları yeniden dizmeden önce kataloğu anlamak gerekir; ve katalogda arama yaparken hangi bölümden başladığınızı bilmiyorsanız, kitabın orada olmaması ile sizin yanlış yerde aramanız aynı sonucu verir.

LDAP Hakkında Sık Sorulan Sorular

Bir Active Directory ortamınız varsa hayır. Domain Controller kurulduğu anda LDAP arayüzü de açılır ve `389` numaralı porttan sorgu kabul etmeye başlar. Kurulacak ayrı bir ürün yoktur. Ayrı bir LDAP sunucusu (örneğin OpenLDAP) yalnızca Windows dışı bir ortamda merkezi dizin kurmak istediğinizde gündeme gelir.
Teknik olarak zorunda değilsiniz, çalışmaya devam eder. Ama düz `389` üzerinde yapılan bir simple bind işleminde kullanıcı adı ve parola ağda okunabilir halde taşınır; aynı kabloyu dinleyen biri ikisini de alır. Bu, dizini sorgulayan uygulamanın servis hesabı söz konusu olduğunda tek bir parolanın tüm dizine erişim anlamına gelmesi demektir. LDAPS'e geçmenin maliyeti bir sunucu sertifikasıdır; geçmemenin maliyeti bir kimlik altyapısıdır.
En sık sebep base DN'in yanlış olmasıdır. LDAP, aramaya başladığınız noktanın altında olmayan hiçbir nesneyi göstermez ve bunu bir hata olarak da bildirmez; sadece boş sonuç döner. İkinci sık sebep arama kapsamının (scope) dar seçilmesidir: kapsam yalnızca bir seviyeyle sınırlıysa alt birimlerdeki kullanıcılar sonuca girmez. Üçüncüsü, bind ettiğiniz hesabın o dalı okuma yetkisinin olmamasıdır.
Ortamınızdaki istemcilerin ne olduğuna bakın. Windows iş istasyonlarını yönetmeniz, grup ilkesi dağıtmanız ve tek oturum açma kurmanız gerekiyorsa Active Directory'nin yerini OpenLDAP tutmaz; AD yalnızca bir dizin değil, yanında Kerberos ve grup ilkesi altyapısını da getiren bir bütündür. Yalnızca Linux sunucular ve uygulamalar için merkezi bir kullanıcı dizini arıyorsanız OpenLDAP hafif ve yeterlidir.
İlker Pehlivan

Yazan

İlker Pehlivan

BT Danışmanı | Ağ, Sistem ve Güvenlik Yönetimi

İlker Pehlivan, karmaşık BT altyapılarını ölçeklenebilir ve güvenli sistemlere dönüştüren bir ağ ve sistem mühendisidir. Şirketlere özel teknoloji rehberleri burada.

Benzer Makaleler

Kurumsal Ağ Protokolleri: DHCP'den LDAP'a

Bir şirketi ayakta tutan ağ protokolleri: DHCP, DNS, Kerberos, LDAP, SMB, RDP, SSH ve BGP. Hangisi ne yapar, nasıl zincirlenir, bozulduğunda nereden anlaşılır.

31 dk okuma

ARP Nedir? MAC Adresi, ARP Tablosu ve Spoofing

ARP, IP adresini MAC adresine çeviren protokoldür. ARP tablosu durumları, yayın alanı sınırı ve ARP spoofing, gerçek makineden alınmış paket dökümleriyle.

41 dk okuma

DHCP Nedir? Ağda IP Adresi Nasıl Dağıtılır?

DHCP nedir, nasıl çalışır? Ağdaki cihazlara IP adresi, subnet, gateway ve DNS bilgisinin otomatik dağıtımı: DORA akışı, kira süresi, APIPA ve DHCP relay.

22 dk okuma

DNS Nedir, Nasıl Çalışır? Kayıt Türleri ve TTL

DNS nedir, nasıl çalışır? Kök, TLD ve yetkili sunucu zinciri; A, CNAME, MX, TXT kayıtları; nameserver devri, TTL ve önbellek, nslookup ile arıza teşhisi.

38 dk okuma

Kurumsal Firewall Kurulumu, Yönetimi ve Danışmanlığı

Kurumsal firewall kurulumu, yönetimi ve danışmanlığı: Fortinet, Palo Alto ve pfSense ile kural yönetimi, IPS/IDS, VPN ve sürekli izleme hizmeti sunuyoruz.

6 dk okuma

HTTP ve HTTPS Nedir? Aradaki Fark ve Şifreleme

HTTP ve HTTPS nedir, farkı ne? İstek ve yanıt anatomisi, durum kodları, şifresiz bağlantıda ne sızdığı ve TLS el sıkışması adım adım.

45 dk okuma

ICMP Nedir? Ping, TTL ve Tracert Komutu

ICMP, ping ve tracert komutunun altında çalışan protokoldür. Request timed out, Destination host unreachable ve General failure farkı, lab ölçümleriyle.

27 dk okuma

IP Adresi Nedir? Subnet Maskesi, CIDR ve IPv6

IP adresi nedir, subnet maskesi ne işe yarar, /24 ne demek? Ağ ve host kısmı ayrımını, özel adres aralıklarını ve IPv6'yı gerçek lab ölçümleriyle anlatıyoruz.

28 dk okuma

Kurumsal Kablosuz Ağ Tasarımı: Survey'den Kuruluma

Kurumsal kablosuz ağ tasarımı: survey planlamadan access point yerleşimine, PoE kablolamadan kanal planına kadar 63 AP'lik bir projede izlenen gerçek sıra.

25 dk okuma

Kerberos Nedir? Kimlik Doğrulama ve Bilet Mantığı

Kerberos nedir, nasıl çalışır? Bilet mantığını, paket düzeyinde yakalanmış gerçek akışı ve oturum açılamadığında izlenecek teşhis sırasını adım adım gösteriyoruz.

32 dk okuma

NFS Nedir? NAS ve Sanallaştırmada Dosya Paylaşımı

NFS nedir, nasıl çalışır? UID/GID kimlik modeli, root_squash ayarı, NFS ile SMB'nin aynı klasörde çakışması ve izin sorunlarının teşhisi, lab ölçümleriyle.

26 dk okuma

NTP Nedir? Kurumsal Ağda Saat Senkronizasyonu

NTP nedir, nasıl çalışır? Stratum hiyerarşisi, ağda tek saat kaynağı, Kerberos'un beş dakikalık toleransı ve saat arızalarında teşhis sırası.

23 dk okuma

Port Nedir? TCP ve UDP Farkı, Bağlantı Arızası Tespiti

Port numarası ne işe yarar, TCP ve UDP farkı nasıl işler, açık port nasıl kontrol edilir ve bağlantı kurulmadığında arıza hangi tarafta, nasıl kanıtlanır?

35 dk okuma

RADIUS Sunucusu Nedir? 802.1X ile Ağ Kimlik Doğrulama

RADIUS sunucusu nedir, nasıl çalışır? 802.1X akışını, EAP yöntemlerini ve ağa bağlanamayan kullanıcıda izlenecek teşhis sırasını paket düzeyinde gösteriyoruz.

24 dk okuma

SMB Nedir? Dosya Paylaşımı ve SYSVOL Bağımlılığı

SMB nedir, nasıl çalışır? Dosya ve yazıcı paylaşımı, sürüm farkları, SMBv1 riski ve grup ilkelerinin SYSVOL üzerinden dağıtımı.

18 dk okuma

SSH Nedir? Şifreli Yönetim ve Anahtar Tabanlı Giriş

SSH nedir, port 22'de el sıkışma nasıl olur, ana bilgisayar anahtarı neyi kanıtlar, sürüm 1 neden kapatılmalı ve parola yerine anahtarla giriş nasıl kurulur.

19 dk okuma

Kurumsal Switch, Router Kurulumu ve VLAN Yapılandırma

Kurumsal switch, router kurulumu ve VLAN yapılandırma: HSRP/VRRP yedekliliği, port güvenliği ve doğru mimari danışmanlığıyla güvenilir ağ altyapısı kuruyoruz.

7 dk okuma

Telnet Nedir? Şifresiz Yönetim Protokolü ve Riskleri

Telnet nedir, port 23 nasıl çalışır, parolayı neden düz metin taşır ve hâlâ açık bulunan cihazlarda ne yapılmalı: kapatma, SSH'a geçiş ve yönetim VLAN'ı.

16 dk okuma

VLAN Nedir? 802.1Q Etiketi, Access ve Trunk Farkı

VLAN tek switch'i mantıksal ağlara böler. 802.1Q etiketi, access ile trunk portun farkı ve native VLAN riski, gerçek paket dökümleriyle anlatılıyor.

32 dk okuma

NAT Nedir? Ağ Adresi Çevirisi Nasıl Çalışır?

NAT (Network Address Translation) nedir, SNAT ile DNAT farkı nedir, PAT nasıl çalışır ve NAT tablosu ne tutar? Çeviri tablosunu lab ortamında açıp gösteriyoruz.

32 dk okuma

RDP Nedir? Uzak Masaüstü Protokolü ve Güvenliği

RDP (Remote Desktop Protocol) nedir, 3389 portu ne yapar ve NLA ne işe yarar? Uzak masaüstü protokolünü Windows sunucuda ölçtük, güvenlik tarafıyla birlikte.

26 dk okuma

SNMP Nedir? MIB, OID ve Trap Mekanizması

SNMP nedir ve nasıl çalışır? Yönetici ve ajan mimarisi, MIB ile OID kataloğu, poll ve trap arasındaki fark, community string riski ve SNMPv3 ile çözümü.

24 dk okuma

Syslog Nedir? Facility, Severity ve 514 Portu

Syslog nedir, log satırı neye benzer? Facility ile severity tek sayıya nasıl sıkışır, 514 portu neden UDP: gerçek switch çıktısıyla anlatıyoruz.

21 dk okuma

FTP, FTPS ve SFTP Nedir? Aralarındaki Fark

FTP, FTPS ve SFTP arasındaki fark: iki kanallı mimari, aktif ve pasif mod, firewall arkasında kırılan aktarımlar ve paket düzeyinde şifresiz dosya kanıtı.

24 dk okuma

TFTP Nedir? Port 69, Switch Yedeği ve PXE

TFTP nedir, UDP 69 üzerinden nasıl çalışır ve switch yapılandırma yedeği neden bu protokolle alınır? Gerçek paket dökümü, PXE boot ve SFTP karşılaştırması.

23 dk okuma

TLS Nedir? SSL ile Farkı, Sürüm Pazarlığı ve Ölçümü

TLS nedir, SSL ile farkı ne? El sıkışmada sürüm ve şifre takımı nasıl seçilir, TLS 1.2 ile 1.3 arasında pakette ne değişir, sunucunuz hangisini konuşuyor?

34 dk okuma

IMAP Nedir, POP3 Nedir? Aralarındaki Fark

IMAP ile POP3 arasındaki fark: durumun sunucuda mı cihazda mı tutulduğu, 993 ve 995 portları, kota dolunca ne olur ve POP3'ten IMAP'a geçişin gerçek maliyeti.

18 dk okuma

SMTP Nedir? Mail Nasıl Gönderilir ve Neden Gitmez?

SMTP nedir, mail nasıl gönderilir: zarf ile başlık ayrımı, 25/587/465 portlarının farkı, STARTTLS öncesi düz metin okunan oturum ve gitmeyen mailin teşhisi.

22 dk okuma

Yapısal Kablolama ve Zayıf Akım: Kurumsal Bina Altyapısı

Kurumsal binada yapısal kablolama ve zayıf akım sistemleri nasıl kurulur? Kat kablolaması, kabinet düzeni, CAT6 ve fiber seçimi, test raporu ve saha hataları.

28 dk okuma

Ücretsiz Değerlendirme

Uygulamalarınız hâlâ 389'dan şifresiz bind ediyorsa, LDAPS'a geçişi birlikte planlayalım.

İlgili Makaleler