EnderUNIX YGT @ Türkiye
Yazılım Geliştiricisi
<ozkan ~
enderunix.org>
Telif Hakkı © 2006 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
Güvenlik Duvarları, bir sistemin özel kısımlarını, genel kullanıma açık kısımlarından ayıran, kullanıcıların kendilerine tanınan haklardan daha fazlasını almalarını engelleyen ve belirlenen güvenlik politikalarını uygulayan yapılardır.
IPFW bir güvenlik duvarıdır. Trafik Düzenleme (bantgenişliği vb.), Layer2 paket filtreleme, statefull inspection, transparent forwarding gibi özellikleri barındırır. IPFW, en fazla 65535 kural içeren bir listeden oluşur. Aksi belirtilmediği sürece IPFW, bir elek sistemi gibi çalışır. Her firewall kuralını bir elek gibi düşünürsek, elekler üst üste gelecek ve bir firewall kural listesi oluşacaktır. Güvenlik duvarına gelen paketler en üstteki elekten başlayarak sırayla aşağııya doğru incelenir. Paketin herhangi bir eleğe takılması durumunda ise diğer eleklere paket geçmediği için incelenmez. Takıldığı elekte hangi işlem tanımlanmışsa o işlem gerçekleştirilir.

Güvenlik duvarı, ağ üzerinde Router ile Yerel Ağ arasında ağ geçidi olarak yer almalıdır. Yerel ağdaki kullanıcıların ağ geçidi olarak Güvenlik Duvarının yerel ağ'a bakan arayüzünün ip adresi tanımlanmalı. Güvenlik Duvarının ağ geçidi ise Router olarak atanacaktır.
Güvenlik duvarının, Router ile Yerel arasına yerleştirilmemesi durumunda, kullanıcılar ağ geçitlerini değiştirerek güvenlik duvarını atlayabilirler.
IPFW, çekirdek tarafında çalışan bir yapıdadır. Ancak belirleyeceğimiz kuralları sisteme bildirmek için kullanıcı tarafında bi yönetim aracına ihtiyaç vardır. Bu araç /sbin/ipfw yazılımıdır.
FreeBSD ile standart olarak gelen GENERIC kernelda IPFW aktif değildir. Çekirdeği yeniden derlemeden ipfw modülünü yükleyerek IPFWyi faal hale getirebiliriz. Ancak, bu sistemi sürekli bir güvenlik duvarı olarak kullanmayı düşünüyorsanız, çekirdeği tekrar derlemenizi tavsiye ederim.
IPFW'yi modül olarak yüklemek istersek burada dikkat etmemiz gereken bir husus var. Eğer FreeBSD'ye ağ üzeriden bağlı iseniz, modülü yüklediğiniz anda bağlantınız kopacaktır. Çünkü ipfw'nin standart kuralı her paket engelleme işlemidir. Bunun önüne geçmek için modülü aşağıdaki şekilde yüklemelisiniz:
# kldload ipfw && ipfw add allow all from any to any
Eğer FreeBSD ye direk konsoldan bağlı iseniz,
# kldload ipfw
komutunu çalıştırarak ipfw modülünü yükleyebilirsiniz. Ancak tüm network bağlantıları kesilecektir.
GENERIC kernelda IPFW yer almadığı için, çekirdeğe IPFWyi ekleyip yeniden derlemeliyiz. Çekirdek dosyası kullanılan donanımın mimarisine göre değişiklik göstermektedir. Çekirdek dosyasının olduğu klasör: /usr/src/sys/<MİMARİ>/conf/ tur. Buradaki GENERIC dosyasını firewall ismiyle kopyalayalım.
# cd /usr/src/sys/i386/conf # cp GENERIC firewallÇekirdek dosyasına bir takım satırlar eklemeliyiz. Eklenecek satırlar:
options IPFIREWALL #Firewall'ı aktif eder
options IPFIREWALL_VERBOSE #Log tutma (syslogd)
options IPFIREWALL_VERBOSE_LIMIT=200 #Kural başına düşen log limiti
options IPFIREWALL_FORWARD #Transparent Forwarding desteği (Transparent Proxy için gerekli)
options IPFIREWALL_FORWARD_EXTENDED #Geliştirilmiş Transparent Forwarding desteği
options IPFIREWALL_DEFAULT_TO_ACCEPT #Standart kuralı izin ver olarak ayarlar.
options IPDIVERT #Nat vb. Divet Soketlerini kullanan programlar için gerekli.
options DUMMYNET #Traffic Shaper. Band genişliği ve kuyruk(queue) ayarları için gereklidir.
options IPSTEALTH #Bu firewalldan geçen paketlerin TTL'lerinin değiştirmeden geçmesini sağlar.
# Firewall'u traceroute gibi araçlardan gizlemek için gereklidir.
options TCP_DROP_SYNFIN #SYN+FIN Paketlerini düşür
Çekirdek dosyasına yukarıdaki satırları ekledikten sonra,
aşağıdaki şekilde çekirdeği derleyebiliriz:
# cd /usr/src # make buildkernel KERNCONF=firewall # make installkernel KERNCONF=firewall
Uyarı Eğer KernelSecurityLevel 2 veya daha yüksek ise make installkernel işlemini Single User Modeda yapmalısınız.
İşletim sistemi açılırken firewall'un başlayıp, kurallarınızın faal hale gelmesi için bir takım ayarlar yapmalıyız. RC sisteminin konfigürasyon dosyası olan /etc/rc.conf dosyasına birkaç satır ekleyeceğiz:
firewall_enable="YES" # Firewall'u aktif hale getir. firewall_script="/etc/ipfw.rules" # Firewall kurallarını /etc/ipfw.rules dosyasından oku. gateway_enable="YES" # Ağ kartları (Ör. Ethernet) arasında iletime izin ver (Ağ geçidi modu) tcp_drop_synfin="YES" # SYN+FIN Paketlerini düşür.
IPFW'nin durumunu görmek ve kuralları güncellemek için kullanıcıya /sbin/ipfw ismiyle bir kontrol yazılımı sağlanmıştır. ipfw, güvenlik politikalarını ve kurallarını bir konfigürasyon dosyasından okuyabildiği gibi, kuralları tek tek de ekleyip/çıkarma imkanını sağlıyor.
Önceki bölümlerde, IPFW'yi üst üste yerleştirilmiş bir elek gibi düşünebileceğimize değinmiştik. Bu sisteme göre, tüm elekleri geçmeyi başaran (hiçbir kuralla eşleşmeyen) paketler için ne yapılacağı önem kazanıyor. Bu tür paketlere ne uygulanacağını 65535 nolu kural belirler. Çekirdeği derleken options IPFIREWALL_DEFAULT_TO_ACCEPT seçeneğini eklerseniz, 65535 nolu kural, paketlerin firewallda geçmesine izin verecektir. Aksi halde, 65535 nolu kural, paketlerin firewalldan geçmesini engelleyecektir. Uygulamak istediğiniz güvenlik politikasına göre bu seçimi yapmalısınız.
Örneğin, ağınızda web siteleri dışında hiçbir erişim sağlanmasını istemiyorsunuz. Bu durumda öncelikle dns ve web isteklerinin ve gelen yanıtların geçmesine izin vermeli, ve son olarak da tüm geçişleri yasaklamalıyız. Böyle bir güvenlik politikası için IPFIREWALL_DEFAULT_TO_ACCEPT seçeneğini eklememeliyiz.
Başka bir örneği ele alalım, ağınızda pop3 kullanımını engellemek istiyor, ancak geri kalan internet erişimlerine izin vermek istiyorsunuz. Bu güvenlik politikasını uygulamak için, önce pop3 erişimlerini engelleyip, ardından her türlü erişime izin vermeliyiz. Her türlü erişime izin verebilmek için de options IPFIREWALL_DEFAULT_TO_ACCEPT seçeneği çekirdemize eklemeliyiz.
IPFW'de kuralları yazarken aşağıdaki sözdizimine göre yazmalıyız:
Sözlü olarak:
<ekle/sil> <eylem> <eylemin uygulanacağı paketin protokolü> <eylemin uygulanacağı paketlerin tanımı>
Uygulamada:
{add|delete} {allow|deny|fwd|...} <paketin tanımı> [seçenekler]
Aşağıda paketlere uygulanabilecek eylemler alfabetik sırayla listelenmiştir:
allow
Paketlerin firewalldan geçmesine izin verir. Ancak paket, hiçbir trafik düzenleme işlemine tabii tutulmaz.
count
Paket tanımına uyan paketleri sayar, kural olarak algılanmaz. Count eylemi elek gibi davranmaz. Yani sayaçlar arttırıldıktan sonra, bu paket incelenmek üzere bir sonraki kurala teslim edilir.
deny
Paketlerin firewalldan geçmesini engeller ve paketi yok eder. Paketi gönderen bilgisayara hiçbir cevap gönderilmez. Dolayısı ile paketi gönderen bilgisayar birkaç deneme daha yaptıktan sonra Bağlantı Zaman Aşımına Uğradı olarak yorumlar.
divert <port>
Paketlerin üzerinde inceleme, değişiklik yapmak üzere tasarlanmış ve divert soketlerini kullanan programların firewalldan paketleri alabilmesi için kullanılır. Örnek: natd
fwd <host[,port]>
Forward eylemi 2 amaçla kullanılır. Birinci amacı, paketin yönlendirileceği ağ geçidini belirlemektir. Bu sayede birden fazla internet bağlantısının kullanımı, yük dengeleme gibi işlemler yapılabilir. Fwd eyleminin bu amaçla kullanmak için port numarasını belirtmemeliyiz. Diğer amacı ise gelen paketleri transparent proxy yazılımına iletmektir. Ancak bunu yapabilmek için transparent proxy yazılımı firewall'un olduğu sistemde çalışıyor olmalıdır. Proxy'nin başka bir sunucuda yer alması durumunda WCCP protokolü kullanılmalıdır.
pipe <numara>
Pakete bantgenişliği sınırlaması getirmek için kullanılır. Numarası verilen pipe'in önceden tanımlanmış olması gerekmektedir. Aksi halde paketler kaybolacaktır.
queue <numara>
Pakete belirli kuyruk disiplinlerini uygulamak için kullanılır. Numarası verilen queue'nin önceden tanımlanmış olması gerekmektedir. Aksi halde paketler kaybolacaktır.
reset
Paketin firewalldan geçmesini engeller ve TCP Reset (RST) uyarısı gönderir.
skipto <kuralno>
Paketin diğer kurallara uğramadan direk verilen kural numarasından itibaren incelenmesini sağlar.
unreach <unreach_kodu>
Paketin firewalldan geçmesini engeller ve cevap olarak verilen unreach_koduna göre ICMP Unreachable mesajı gönderilir. En çok kullaılan kodlar: net, host, port, needfrag, srcfail, net-unknown, host-unknown.
Paket tanımlamada, yakalamak istediğiniz paketi protokol, gönderen adresi, kaynak-port, alıcı adresi ve hedef-port bilgilerine göre ayırt edebiliyoruz. Aşağıdaki kuralda paket tanımlama kısmını inceleyelim:
add allow tcp from 10.0.0.0/24{5,10-32,87-138} to any 80 setup keep-state
\---------------paket tanımlama--------------/
Paket Tanımlama kısmı protokol tanımı ile başlar. IPFW'de kullanılabilen protokoller /etc/protocols dosyasında tanımlanmıştır.
Protokol tanımından sonra from kelimesi ile birlikte paketi gönderenin adresi tanımlanmalıdır. Bu kısmın mutlaka paket tanımlamada yer almalıdır. Bu kısımda doğrudan ip adresi yazılabilecği gibi maskeleme yöntemi ile networkler de temsil edilebilir. (Ör: 192.168.0.0/16 veya 192.168.0.0:255.255.0.0 bu ifade 192.168.*.* iplerini temsil eder) Ayrıca örnekteki gibi de belirli ip aralıkları da tanımlanabilmektedir. 10.0.0.0/24{5,10-32,87-138} ifadesi 10.0.0.5, 10.0.0.10-10.0.0.32 arası, 10.0.0.87-10.0.0.138 arası iplerini temsil eder. IP adresi veya network tanımlamak yerine bir domain yazmanız durumunda ise dns sorgusu yapılarak, ip karşılığı bulunur ve kurala ip adresi yazılır. Bu alanda kullanılabilecek diğer özel ifadeler table(numara), any ve me dir.
table(numara) ifadesi, önceden oluşturulmuş, birden fazla ip adresi içeren tabloların kullanılmasına imkan sağlar. Oluşacak kural, tablodaki tüm ipleri kapsar. Tabloların tanımlanması için Kısım 4.3.2 ye bakınız.
Not: table() ifadesi 13 Aralık 2005 tarihinde IPFW2 ye eklenmiştir. IPFW'de ve önceki tarihli IPFW2'lerde bu özellik yer almamaktadır.
any ifadesi, tüm ipleri temsil eder.
me ifadesi ise firewall'un kendisi ip adresini (ve tüm ip aliaslarını da) temsil eder.
Göndericinin adresi belirlendikten sonra bir boşluk bırakılarak kaynak port numarası doğrudan numara yazılarak belirtilir. Eğer port numarası kontrol edilmeyecekse bu kısımın paket tanımlamaya yazılmayabilir. Port numaraları, 1 ile 65535 arasındadır. Portlar liste ve aralık halinde de belirtilebilir. (Ör: 25,80,110,2000-3000)
Kaynak port adresi tanımlı ise bu tanımdan sonra, eğer tanımlı değilse gönderici adresinden sonra to kelimesi gelir ve ardından alıcının adresi tanımlanır. Alıcı adresi mutlaka paket tanımlamasında yer almalıdır. Alıcı adresi belirtilirken, gönderici adresi belirtmedeki tüm yöntemler kullanılabilir.
Alıcı adresi tanımlamasından sonra bir boşluk bırakılarak hedef port numarası doğrudan numara yazılarak belirtilir. Eğer port numarası belirtilmeyecekse bu kısım paket tanımlamaya yazılamayabilir. IPFW2 kullanılıyorsa, ipfw otomatik olarak port numarasının önüne dst-port ifadesini ekleyecektir. (Not: FreeBSD 5.x, 6.x ve 7.x-CURRENT branşlarında IPFW2 standart olarak gelmektedir.)
Bazı kurallarda önceden tanımlanmış ifadeler kullanılması gerekmektedir. Örneğin trafik düzenleme işlemini gerçekleştirebilmek için bandgenişliği, kuyruk uzunluğu / disiplini gibi parametreler.
pipe ve queue tanımları trafik düzenleme işlemlerinde kullanılmaktadır. Trafik düzenleme konusu apayrı bir konu olması nedeniyle bu konudan bir başka yazıda bahsedeceğim. Kısaca pipe tanımı aşağıdaki şekilde yapılabilir:
# ipfw pipe 1 config bw 512Kbit/sYukarıdaki komut 1 numaralı bir pipe yaratacak ve bu pipe'in bandgenişliğini 512Kbit/s ile sınırlandıracaktır.
queue tanımına bir örnek:
# ipfw queue 1 config weight 5 pipe 1
Uyarı Firewall kurallarında tanımı yapılmamış bir pipe veya queue'ya yönlendirme yapılması durumunda paketler drop işlemine tabii tutulacaktır!
Tablolar, paket tanımlama aşamasında kullanılmaktadır. En fazla 128 tablo oluşturulabilir. Tablolar 0 - 127 arasındaki rakamlarla numaralandırılır. Firewall kurallarınızda alıcı veya hedef ip adresi bölümüne birden fazla ip yada network tanımlamaya ihtiyaç duyduğunuzda table tanımları imdadınıza yetişecektir.
Bir tabloya eleman eklemek için:
# ipfw table tablo_no add <IP Adresi veya Network Adresi> Örnek: # ipfw table 0 add 192.168.1.5 # ipfw table 0 add 192.168.2.0/24Tablonun elemanlarını görmek için:
# ipfw table tablo_no list Örnek: # ipfw table 0 list 192.168.1.5/32 0 192.168.2.0/24 0Tablodan bir eleman silmek için:
# ipfw table tablo_no delete <IP Adresi veya Network Adresi> Örnek: # ipfw table 0 delete 192.168.1.5Tabloyu sıfırlamak:
# ipfw table tablo_no flush Örnek: # ipfw table 0 flush
IPFW kuralları bir dosyadan okuyabildiği gibi, hem preprocessor aracılığı ile hem commandline aracılığı ile hem de stdin'den kuralları okuyabilr. Kurallarımızı oluşturduktan sonra kural listemizin en üstüne -f flush satırını eklemeliyiz. Çünkü daha önce mevcut olan kurallar silinmezse, güvenlik politikanız doğru uygulanmayabilir. flush işlemi ile mevcut tüm kurallar silinir.
Kurallarımızı her kural 1 satıra gelecek şekilde /etc/ipfw.rules isimli bir dosyaya kaydedelim. Kuralları uygulamak için:
# ipfw /etc/ipfw.ruleskomutunu kullanabilir. Ancak bu şekilde çalıştırırsak, ipfw yaptığı tüm işlemleri ekrana yazacaktır. Eğer bunu yapmasını istemiyorsak (mesela bir scriptin içerisinden çağırıyorsak):
# ipfw -q /etc/ipfw.ruleskomutunu kullanırız.
Diğer bir yöntem ise kurallarınızı tek tek sisteme kendiniz eklemenizdir. Bu yöntem genellikle küçük değişiklikler için tercih edilir:
# ipfw add allow tcp from 10.0.0.0/24 to any 80 keep-state
Firewall kurallarınız oluşturup uyguladıktan sonra, kuralların işini yerine getirip getirmediğinden emin olmak için firewall'un durumunu kısa bir süre dahi olsa izlemek gereklidir. IPFW, her kural için 2 adet sayaç tutar. Bunlardan biri paket tanımına uyan paket sayısı, diğeri ise bahsi geçen paketlerin byte cinsinden toplam boyutudur. Bu sayaçların artıp artmamasına göre firewall'un sizin beklediğiniz işlemleri yerine getirip getirmediği hakkında fikir edinebilirsiniz.
Firewall'un mevcut kurallarını görmek için ipfw list komutu kullanılmaktadır. Kuralları sayaçlarla birlikte görmek için ipfw show komutu kullanılabilir.
# ipfw list 65535 allow ip from any to any # ipfw show 65535 2569000 595273716 allow ip from any to any
Yukarıdaki örnekte firewallda tanımlı tek kural, default kural olan tüm paketlere izin ver işlemidir. ipfw show un çıktısında ikinci sütunda (2569000 sayısı) bu kurala uyan paketlerin sayısı yer almaktadır. Üçüncü sütunda ise bu paketlerin byte cinsinden toplam boyutu gösterilmektedir. Bu rakamları takip ederek yazdığımız kuralın iş görüp görmediğini anlayabiliriz. Yazdığınız kuralın doğru olduğunu düşünmenize rağmen kurala uyan paket sayısı sıfır ise ya tanımladığınız özelliklere uygun bir network trafiği yoktur, ya da daha üstteki kurallarda bu paket tanımını kapsayan daha geniş kapsamlı bir kural olabilir. Bu tür durumlarda firewall kurallarınızı genel olarak tekrar gözden geçirin.
İlgili kurala en son ne zaman paket uyduğunu ise ipfw -t show komutu ile görebiliriz. -t parametresi timestamp'i yazdırır.
# ipfw -t show 65535 2573615 595826141 Sat Jun 10 11:44:13 2006 allow ip from any to any
Bu örnekte www, pop3, smtp ve dns bağlantıları dışındaki tüm bağlantıların engelleneceği bir yapı ele alınmıştır.
---- /etc/ipfw.conf ---- -f flush add allow ip from any to any via lo0 add deny ip from any to 127.0.0.0/8 add allow tcp from any to any 25,80,110 add allow tcp from any 25,80,110 to any add allow udp from any to any 53 add allow udp from any 53 to any add deny ip from any to any ------------------------
Basit firewall örneğindeki yapıyı aynen burada statefull mimari ile uygulayacağız.
---- /etc/ipfw.conf ---- -f flush add allow ip from any to any via lo0 add deny ip from any to 127.0.0.0/8 add check-state add allow udp from any to any 53 keep-state add deny ip from any to any established add allow tcp from any to any 25,80,110 setup keep-state add deny ip from any to any ------------------------
Kompleks bir firewall örneği ele alalım. 2 ayrı internet bağlantısına sahip, 4 farklı fiziksel networke doğrudan bağlı bir güvenlik duvarı tasarımı yapacağız.
___________
LAN1 <--> bge0 | |
LAN2 <--> bge1 | | em0 <--> 2Mbit Frame Relay
LAN3 <--> bge2 | FreeBSD | em1 <--> 2Mbit ADSL
LAN4 <--> bge3 | |
-----------
LAN1 - 192.168.1.0/24, LAN2 - 192.168.2.0/24, LAN3 - 192.168.3.0/24, LAN4 - 192.168.4.0/24 network adresleri ile çalışıyor olsunlar. Frame Relay Networku 1.1.1.0/29 olsun, FrameRelay Router'i ise 1.1.1.1 olsun. ADSL'e PPPoE ile bağlanalım ve servis sağlayıcıdan aldığımız IP adresi 2.2.2.2/32 olsun.
---- /etc/ngnat.sh ---- #!/bin/sh kldload ng_ipfw kldload ng_nat ngctl mkpeer ipfw: nat 100 out ngctl name ipfw:100 framerelay ngctl connect ipfw: framerelay: 110 in ngctl msg framerelay: setaliasaddr 1.1.1.2 ngctl mkpeer ipfw: nat 200 out ngctl name ipfw:200 framerelay ngctl connect ipfw: framerelay: 210 in ngctl msg framerelay: setaliasaddr 2.2.2.2 ----------------------- ---- /etc/ipfw.conf ---- -f flush table 1 flush table 1 add 192.168.1.0/24 // LAN1 table 1 add 192.168.2.0/24 // LAN2 table 1 add 192.168.3.0/24 // LAN3 table 1 add 192.168.4.0/24 // LAN4 add allow ip from any to any via lo0 add deny ip from any to 127.0.0.0/8 add deny ip from any to any not versrcreach in via bge0 add deny ip from any to any not versrcreach in via bge1 add deny ip from any to any not versrcreach in via bge2 add deny ip from any to any not versrcreach in via bge3 add fwd 1.1.1.1 ip from 1.1.1.0/29 to any add fwd localhost,3128 tcp from not me to any 80 add allow tcp from any to me 22 keep-state add prob 0.5 netgraph 100 tcp from table(1) to any 25,80,110,443 add netgraph 200 tcp from table(1) to any 25,80,110,443 add prob 0.5 netgraph 100 udp from table(1) to any 53 add netgraph 200 udp from table(1) to any 53 add netgraph 110 ip from any to me via em0 add netgraph 210 ip from any to me via em1 add allow ip from me to any via em1 add deny ip from any to any ------------------------
Uyarı 1.1.1.2 Nolu IP Adresini em0'a ve 2.2.2.2 nolu IP Adresini em1'e atamayı unutmayın. Aksi halde natlanan paketler geri dönemeyecektir.