Proxmox Üzerinde Kurumsal Ağ Laboratuvarı: LACP, VLAN, Sophos XG, Active Directory ve WDS ile Golden Image

13 Ekim 2026 • 14 dk okuma

Bir şirket ağının nasıl çalıştığını okuyarak öğrenmek bir yere kadar mümkün. Kablonun switch'e takıldığı andan bir istemcinin ağdan Windows kurup etki alanına katıldığı ana kadar her katmanı kendim kurmak istedim. Ağustos 2026 boyunca Proxmox üzerinde küçük bir şirket ağını uçtan uca simüle eden bir laboratuvar kurdum.

Bu yazı bir kurulum rehberinden çok bir saha günlüğü. Her bölümde ne kurduğumu, neyin bozulduğunu ve bunu nasıl bulduğumu anlatıyorum. İç IP adresleri ve etki alanı adı laboratuvara ait; gerçek bir ağa ait değil.

Topoloji

İnternet
   │
Sophos XG ──── ağ geçidi, VLAN'lar arası yönlendirme, NAT, DHCP relay
   │  LAG (2 port)
3Com 4500 ──── yalnızca L2: 802.1Q trunk + access portlar
   │  LACP (2 port)
Proxmox VE ─── bond0 → vmbr0
   ├─ AD01: DC, DNS, DHCP, WDS
   ├─ D01: etki alanı istemcisi
   └─ referans VM, Kali
  • Proxmox VE host: iki portlu LACP bond ile switch'e bağlı. Yönetim için ayrı ve izole bir köprü daha var.
  • 3Com 4500 yönetilebilir switch: yalnızca katman 2. VLAN'lar burada tanımlı, yönlendirme yapmıyor.
  • Sophos XG: VLAN'ların ağ geçidi. Her VLAN için LAG üzerinde bir alt arayüz var; NAT, güvenlik duvarı kuralları ve DHCP relay de burada.
  • AD01 (Windows Server 2022): etki alanı denetleyicisi, DNS, DHCP ve WDS. Etki alanı: adfirsth.local.
  • D01: etki alanına katılmış bir Windows 10 istemcisi. Ayrıca golden image için bir referans VM ve testler için bir Kali VM.

Laboratuvara dışarıdan erişim için Proxmox'a Tailscale kurdum ve lab ağını subnet router olarak duyurdum. Böylece internete hiçbir port açmadan her yerden yönetebiliyorum.

1. Fiziksel katman: LACP bond ve NetworkManager

Proxmox ile switch arasında iki kabloyu tek bir mantıksal bağlantı gibi kullanmak için 802.3ad (LACP) bond kurdum:

auto bond0
iface bond0 inet manual
        bond-slaves nic1 nic2
        bond-miimon 100
        bond-mode 802.3ad
        bond-xmit-hash-policy layer2+3

Belirti: Switch günlüğünde sürekli LACP is not enabled on the remote end of port Ethernet1/0/23 uyarısı vardı. Lab çalışıyor ama yavaştı ve ping 8.8.8.8 yaklaşık %25 paket kaybı gösteriyordu.

Sebep: Bond yarım çalışıyordu. Proxmox'ta kurulu kalan NetworkManager, nic1'i kendine alıp sürekli DHCP deniyor ve karta bond'a katılma fırsatı vermiyordu. ip link çıktısında bu görünmüyordu; ancak journalctl kayıtlarında ortaya çıktı. Switch iki porta trafik dağıtıyor, Proxmox ise yalnızca birinden cevap veriyordu.

Çözüm: Proxmox ağ yapılandırmasını ifupdown2 ile yönettiği için NetworkManager'a ihtiyaç yoktu:

systemctl stop NetworkManager
systemctl disable NetworkManager
systemctl mask NetworkManager
ifreload -a
cat /proc/net/bonding/bond0 | grep -E "Bonding Mode|Number of ports|Slave Interface"
Number of ports: 2
Slave Interface: nic2
Slave Interface: nic1

Switch tarafında da iki portun Selected durumuna geçtiğini doğruladım. Paket kaybı sıfırlandı:

<4500> display link-aggregation verbose
...
Port                     Status  Priority  Key    Flag
Ethernet1/0/23           S       32768     1      {ACDEF}
Ethernet1/0/24           S       32768     1      {ACDEF}

Yan sorun: açılışta içe aktarılamayan ZFS havuzu

Bu sırada yapılan bir yeniden başlatmada Proxmox açılışta Failed to start zfs-import@storage1.service hatası verdi. Havuzun gerçek adı deneme1'di; daha önce oluşturulmuş bir systemd birimi ise artık var olmayan storage1 adlı havuzu arıyordu. Eski birimi devre dışı bırakmak yetti:

systemctl disable zfs-import@storage1.service
zpool status

2. VLAN'lar ve Sophos XG

Switch'i yalnızca katman 2'de bıraktım: Proxmox ve Sophos'a giden bağlantılar 802.1Q trunk, istemci portları ise kendi VLAN'larına atanmış access port. Beş VLAN var: 10.10.10.0/24'ten 10.10.50.0/24'e kadar. VLAN 10 sunucuların bulunduğu ağ.

Sophos'ta switch'e giden LAG üzerinde her VLAN için bir alt arayüz oluşturdum (LAG11.20, LAG11.30 …). Her alt arayüz kendi VLAN'ının .1 adresini alıp o VLAN'ın ağ geçidi oluyor; VLAN 10'da ağ geçidi Sophos'un 10.10.10.11 adresi.

İlk denemede istemciler gateway'e ulaşıyor ama internete çıkamıyordu. ping 10.10.10.11 çalışıyor, ping 8.8.8.8 çalışmıyordu; bu, sorunun DNS değil Sophos'un WAN tarafında olduğunu gösteriyordu. Eksik üç şey vardı: WAN bacağının yapılandırması, LAN'dan WAN'a NAT kuralı ve DNS yönlendirmesi. Üçü tamamlanınca çıkış çalıştı.

Bu süreçte Proxmox'un varsayılan ağ geçidinin de yanlış olduğunu fark ettim. Laboratuvarın ilk günlerinde internet paylaşımı yapan bilgisayarımın adresini gösteriyordu; Sophos'a çevirdim.

3. Active Directory ve DNS

AD01'e AD DS ve DNS rollerini kurup adfirsth.local ormanını oluşturdum. Her şey çalışıyor gibi görünüyordu, ta ki ipconfig /all çıktısına dikkatle bakana kadar:

DNS Servers . . . : fec0:0:0:ffff::1%1
                    fec0:0:0:ffff::2%1
                    fec0:0:0:ffff::3%1

Etki alanı denetleyicisinin DNS sunucusu olarak Windows'un IPv6 yer tutucu adresleri tanımlıydı; yani DC kendi DNS'ini hiç kullanmıyordu. O ana kadar işlerin yürümesi büyük ihtimalle NetBIOS yayınları sayesindeydi. Bu tür bir hata sessizce bekler ve en beklenmedik anda patlar. DC'yi kendi DNS'ine yönlendirdim ve ad çözümlemesini doğruladım:

Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 127.0.0.1
Resolve-DnsName D01.adfirsth.local
nltest /dsgetdc:adfirsth.local

nltest çıktısında DC'nin PDC, GC, KDC ve DNS rollerinin hepsi görünüyordu.

4. DHCP: beş kapsam ve Sophos üzerinden relay

DHCP sunucusu VLAN 10'daki DC'de çalışıyor. Diğer VLAN'lardaki istemcilerin DHCP yayınları VLAN sınırını geçemediği için Sophos'ta her VLAN alt arayüzüne DC'yi gösteren bir DHCP relay tanımladım. Kapsamları DC'de oluşturdum:

$vlans = 10, 20, 30, 40, 50
foreach ($v in $vlans) {
    $net = "10.10.$v.0"
    $gw  = if ($v -eq 10) { "10.10.10.11" } else { "10.10.$v.1" }
    Add-DhcpServerv4Scope -Name "VLAN$v" -StartRange "10.10.$v.100" -EndRange "10.10.$v.200" `
        -SubnetMask 255.255.255.0 -State Active
    Set-DhcpServerv4OptionValue -ScopeId $net -Router $gw -DnsServer 10.10.10.20 -DnsDomain "adfirsth.local"
}
Add-DhcpServerInDC -DnsName AD01.adfirsth.local -IpAddress 10.10.10.20

Bu kısımda üç ayrı hata üst üste bindi:

  • Yanlış relay hedefi: Sophos'taki relay'ler ağda olmayan bir adresi gösteriyordu. Dördünü de DC'nin adresine düzelttim.
  • Sophos'ta LAN'dan LAN'a kural yoktu: Relay paketleri VLAN'lar arasında geçemiyordu. Bir LAN-to-LAN kuralı ekleyip Sophos'un policy test aracıyla trafiğin kabul edildiğini doğruladım.
  • DHCP sunucusu hiçbir arayüzü dinlemiyordu: Get-DhcpServerv4Binding çıktısında BindingState: False vardı. Kapsamlar tanımlı ve etkin olsa da servis gelen isteklere cevap vermiyordu.
Get-DhcpServerv4Binding
Set-DhcpServerv4Binding -InterfaceAlias "Ethernet" -BindingState $true

Son testte VLAN 30'daki bir istemci, başka bir VLAN'daki DC'den adres aldı. Bu, relay zincirinin uçtan uca çalıştığını kanıtlıyordu:

IPv4 Address . . . : 10.10.30.100
Default Gateway  . : 10.10.30.1
DHCP Server  . . . : 10.10.10.20
DNS Servers  . . . : 10.10.10.20

5. GPO ile uzaktan yönetim: WinRM

Hedefim, DC'den tek komutla istemcilerde parola girmeden işlem yapabilmekti. Bunun için WinRM'in her istemcide açık olması gerekiyor ve bunu elle değil Grup İlkesi ile yapmak istiyordum.

OU ile Container farkı

İlk GPO hiç uygulanmadı. Sebebi, D01'in varsayılan CN=Computers konteynerinde durmasıydı. Bu bir organizational unit (OU) değil, bir container; GPO'lar container'lara bağlanamaz. Bir OU oluşturup bilgisayarı oraya taşıdım ve GPO'yu bu OU'ya bağladım.

GPO tek başına yetmiyor

GPO ile WinRM servisini otomatik başlattım, dinleyiciyi açtım ve güvenlik duvarı kuralını ekledim. Get-CimInstance artık çalışıyordu, ama Invoke-Command AccessDenied veriyordu. Hata mesajlarını katman katman okumak burada çok işe yaradı:

  • CannotConnect: dinleyici yok veya port kapalı.
  • LogonFailure: kimlik bilgisi yanlış.
  • AccessDenied: kimlik doğrulama başarılı, ama hedefte izin yok.

Sorun, Grup İlkesi'nin WinRM dinleyicisini açması ama PowerShell remoting uç noktasını (session configuration) kaydetmemesiydi. Bunu Enable-PSRemoting yapıyor. Çözümü de yine GPO ile otomatikleştirdim: aynı GPO'ya bir başlangıç betiği ekledim.

# \\adfirsth.local\SysVol\adfirsth.local\Policies\{GPO-ID}\Machine\Scripts\Startup\EnableWinRM.ps1
Enable-PSRemoting -Force -SkipNetworkProfileCheck
Invoke-Command -ComputerName D01 -ScriptBlock { hostname }
d01

Kalıcı olduğunu görmek için D01'de WinRM'i bilerek bozup makineyi yeniden başlattım; hiçbir müdahale olmadan geri geldi. Artık OU'ya katılan her makine ilk açılışta kendini yapılandırıyor ve DC'den parola veya TrustedHosts gerekmeden Kerberos ile yönetilebiliyor.

Saat farkı ve Kerberos

Bir gün aynı komut 0x80090324 hatası verdi. D01'in saati kaymıştı ve Kerberos, saat farkı beş dakikayı aşınca biletleri reddediyor. Saati düzeltmek anlık çözümdü. Kalıcı çözüm, istemcilerin saati etki alanı hiyerarşisinden almasıydı: Configure Windows NTP Client ilkesinde tür NT5DS.

6. WDS/PXE ve golden image

Son hedef, yeni bir makinenin ağdan açılıp hazır bir Windows imajıyla kurulmasıydı. DC'ye WDS rolünü kurdum, boot ve install imajlarını ekledim. Ardından şu akışla bir golden image hazırladım:

  1. Referans makine: etki alanına katılmamış bir Windows 10 VM; gerekli yazılımlar ve ortak ayarlar kuruldu.
  2. Snapshot: sysprep geri alınamaz, bu yüzden önce Proxmox'ta pre-sysprep snapshot'ı aldım.
  3. Sysprep: /generalize /oobe /shutdown ile makineye özgü bilgiler silinip kapatıldı.
  4. Capture: makine WinPE ile açılıp imaj bir WIM dosyasına alındı.
  5. Dağıtım: WIM, WDS'e install image olarak eklendi ve yeni bir VM ağdan bu imajla kuruldu.

Capture'ın üç kez başarısız olması

Kâğıt üzerinde basit olan dördüncü adım en çok zaman alan kısım oldu:

  • Birinci deneme: WDS capture sihirbazı WIM'i aynı sanal diske yazıp sonra ağdan yüklemeye çalıştı. Aynı disk hem okunup hem yazıldığı ve ağ 100 Mbps olduğu için işlem saatler sürdü ve yarıda kaldı.
  • İkinci deneme: DISM ile doğrudan DC'deki bir ağ paylaşımına yazdım. Bu sefer işlem sırasında paylaşımın hedefi kapanınca 9,6 GB'lık ama bozuk bir dosya oluştu: dism /get-wiminfo Error: 13 The data is invalid dedi.
  • Üçüncü deneme: WinPE ağ kartını hiç görmedi. VM'de VirtIO ağ kartı vardı ve WinPE boot imajında VirtIO sürücüsü yoktu.

Çözüm: Ağı capture sürecinden tamamen çıkardım. Referans VM'e boş bir ikinci disk ekledim ve imajı WinPE'de DISM ile bu yerel diske aldım:

REM WinPE, referans makinede (D: = Windows, W: = boş ikinci disk)
dism /capture-image /imagefile:W:\Win10-Golden.wim /capturedir:D:\ /name:"Win10-Golden" /compress:fast

Ardından diski referans VM'den ayırıp DC'ye canlı olarak taktım. Ağ üzerinden tek bir dosya kopyalamaya bile gerek kalmadı:

# Referans VM'den ayrılan diski DC'ye canlı olarak tak
qm config 102 | grep -i unused
qm set 100 -scsi2 <depolama>:102/vm-102-disk-N.qcow2
dism /get-wiminfo /wimfile:E:\Win10-Golden.wim

Bu sefer WIM sağlamdı. WDS'e ekleyip yeni bir VM'i PXE ile açtım ve golden image'ı seçerek kurdum. Makine, referans imajdaki yazılımlarla ve sysprep sayesinde kendine özgü bir SID ile geldi.

Sonuç ve çıkardığım dersler

  • Hata mesajı bir katmanı işaret eder. CannotConnect, LogonFailure ve AccessDenied üç farklı yere bakmayı gerektiriyor. Ping'i de katman katman yapmak (ağ geçidi, IP, DNS) sorunu tek adımda daraltıyor.
  • Sessiz hatalar en tehlikelileri. DC'nin DNS'i, DHCP binding'i ve NetworkManager'ın tuttuğu kart; üçü de hiçbir hata mesajı vermeden bir şeyleri yarım bırakıyordu.
  • Elle yapılan düzeltme kalıcı değildir. WinRM'i bir kez elle açmak işe yaradı, ama yeni bir makine aynı duvara çarpacaktı. Asıl çözüm, bunu GPO ile her makinenin kendi kendine yapmasıydı.
  • Büyük veri taşırken ağı devreden çıkar. Golden image'ı yerel diske almak ve diski taşımak, ağ üzerinden yapılan tüm denemelerden hızlı ve güvenilir oldu.
  • Geri alınamayan adımdan önce snapshot al. Sysprep öncesi alınan snapshot, birkaç kez baştan başlamamı sağladı.

Sıradaki adımlar: autounattend.xml ile kurulum sırasında hiçbir tıklama gerektirmeyen tam otomatik dağıtım, MAC adresine göre önceden tanımlanmış (prestaged) cihazlar ve DC'nin saati dış bir NTP kaynağından alıp etki alanına dağıtması.