IPFIREWALL ve Snort_Inline ile IPS – Part 1: IPFW Kurulumu
Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYxbPnWH' (Errcode: 28 - No space left on device) in /usr/share/nginx/html/syslogs/wp-includes/class-wpdb.php on line 2349
Bir kaç gündür IPFW ve Snort_Inline ile oluşan open source bir IPS sistemini devreye almak için uğraşıyordum. Bu iki bölümlük yazıda kurulumun nasıl yapıldığı ve konfigurasyonlarla ilgili notları paylaşacağım. Siz de networkünüzde IPS olarak IPFW/Snort_Inline ikilisinden yararlanmak isterseniz belki bu döküman işinize yarayabilir.
Zira binlerce dolar ödeyip karşılığında alacağınız bir hardware IPS yerine hiç bir ücret ödemeden bir IPS sistemine sahip olmak cazip bir seçenek olabilir. Kaldıki Snort'un sektörde artık bir standart haline gelmiş olması kafanızdaki şüpheleri ortadan kaldırabilir Önce IPFIREWALL. |
IPFIREWALL NEDİR ?
Namı diğer IPFW, freebsd tarafından geliştirilen hem Stateless hem de Statefull firewall mimarisini üzerinde barındıran güzel bir ip tabanlı firewall yazılımıdır. Ayrıca, traffic shaping, transparent forwarding ile NAT ve PATgibi özellikler sağlar. Bu özellikler ile ilgili detayli bilgiyi, dökümanın “ipfw komutları” bölümünde bulabilirsiniz. Öncelikle nasıl kurulduğuna değineceğim.
NASIL KURULUR
Aslında IPFW, freebsd ile birlikte loadable module olarak geldiği için NAT uygulaması kullanmak istemeniz haricinde ekstradan herhangi bir kuruluma ihtiyaç duymazsınız. Açılışta firewall'un devreye girmesi için rc.conf dosyasına aşağıdaki satırı girmeniz yeterlidir.
firewall_enable="YES"
Ancak NAT kullanmak istemeniz durumunda (ki snort_inline için gerekmektedir.) kernelinize options IPDIVERT satırını eklemeniz ve yeniden derlemeniz gerekmektedir. Kernelinizi yeniden nasıl derleyebileceğiniz ile ilgili bilgiye, daha önce yazmış olduğum Custom Kernel dökümanından ulaşabilirsiniz.
NAT dışında gerekli olmasa da bilgi olması açısından IPFW'nin kernel opsiyonları şu şekilde.
KERNEL OPTIONS
options IPFIREWALL
Firewall'un enable edilmesi için.
options IPFIREWALL_VERBOSE
Firewall'un üzerinden geçen trafiği loglamak için kullanılır. Kurallarınızın nasıl işlediğini /var/log/security isimli log dosyasından takip edebilirsiniz.
options IPFIREWALL_VERBOSE_LIMIT=200
Bir kurala ait işlemin kaç kez loglanacağını belirler. Bu örnekte 200 satır. Herhangi bir kuralla ilgili olarak loglanan bir işlem 200 kere tekrarlandığı zaman, loglama işlemi o kural için durdurulur. Loglama işlemine kısıtlama getirerek servera binen işlemci yükünü hafifletebilirsiniz. Ayrıca birinin firewall'unuza devamli paket göndermesi ve bunların hepsini loglamanız durumunda oluşacak syslog flooading (DoS) saldırısının da önüne geçmiş olabilirsiniz.
options IPFIREWALL_DEFAULT_TO_ACCEPT
Bu opsiyon default olarak gelen ve giden herşeyin kabul edilmesini sağlar. Bu opsiyon aktifleştirilmezse firewall'unuz closed modda çalışacaktır. Yani herşey deny edilecektir. Bu durumda izin vermek istediğiniz bağlantılar için rulelar oluşturmanız gerekir.
UYARI: Eğer firewall ile ilgili işlemleri SSH bağlantısı ile uzaktan yapıyorsanız, bu seçeneği aktif etmemeniz ya da kendiniz için SSH bağlantısına izin veren bir rule tanımlamamanız durumunda bindiğiniz dalı kesmiş olursunuz. Bir console bağlantısına sahip olmanız yararınızadır :)
Ya da kerneli yeniden derlemeden önce rc.conf dosyanıza firewall_type=”open” satırını ekleyip gelen giden herşeye izin verebilirsiniz. Firewall_Type ile ilgili rc.conf seçeneklerini bir sonraki bölümde bulabilirsiniz. |
options IPV6FIREWALL options IPV6FIREWALL_VERBOSE options IPV6FIREWALL_VERBOSE_LIMIT options IPV6FIREWALL_DEFAULT_TO_ACCEPT
IP Version6 için gerekli opsiyonlar. Gördüğünüz gibi IPv4 opsiyonları ile aynı.
options IPDIVERT
NAT (Network Address Translation) yapabilmek için gerekli opsiyon. Ayrıca, Snort_Inline gibi Divert soketinden paketleri alıp inceleyen yazılımlara yönlendirme yapmak için de gerekiyor. Bu özellik default olarak gelmemekte, devreye almak için bu kernel parametresini girip kerneli yeniden derlemeniz gerekmektedir.
options DUMMYNET
Trafik shaping yapmak için. Banwith limitlemesi ya da queue düzenlemesine olanak sağlar.
RC.CONF SEÇENEKLERİ
firewall_enable="YES”
Açılışta firewall'u devreye alır.
firewall_type="open"
Firewall'un hangi tipte çalışacağını belirler. Seçenekler ve ne iş yaptılkları şöyle:
open : Gelen giden herşeye izin ver.
client : Sadece bu makineyi koru.
simple : T0üm ip networkünü koru.
closed : Loopback interfacei hariç gelen giden herşeyi yasakla.
filename : firewall rulelarini içeren dosya.
Kurallarınızı firewall'a uygulamanız için iki yol bulunmaktadır. Birincisi rc.conf dosyasında
firewall_type="filename"
parametresi ile belirttiğimiz rule dosyamıza yazacağımız rulların açılışta devreye
alınmasını sağlamak.
Mesela, /etc dizini altında ipfw.rules isimli bir dosya oluşturalım ve içerisine aşağıdaki “gelen giden herşeye izin ver” anlamındaki firewall rulelarını yazalım.
add any in all add any out all
Sonra /etc/rc.conf dosyamıza firewall_type=”/etc/ipfw.rules” satırını ekleyip kaydedelim. Bu durumda serverı restart ettiğiniz zaman açılışta firewall devreye alınacak ve type satırında yazan pathteki dosyada bulunan rulelar sisteme eklenecektir. Bu şekilde herhangi bir command-line komutu kullanmadan rulelarınızı devreye alabilirsiniz.
Bir diğer yöntem ise bir shell script oluşturup ruleları sisteme eklemektir:
Gene /etc altında ipfw.rules isimli bir dosya oluşturup içerisine aşağıdaki satırları girelim.
#!/bin/sh ipfw -q flush ipfw add block in all ipfw add block out all
Daha sonra /etc/rc.conf dosyasına firewall_script=”/etc/ipfw.rules” yazalım.
Şimdiki yöntemde rc.conf dosyasında firewall'a ruleları içeren script dosyasının yerini söyleyip restart ettiğiniz zaman, açılışta firewall devreye alındıktan sonra bu script dosyası çalıştırılacak ve rulelar sisteme eklenecektir. Bu yöntemin güzel bir özelliği rule scriptinde herhangi bir değişiklik yaptıktan sonra sistemi restart etmenize gerek kalmaksızın script dosyasını çalıştırmak suretiyle değişiklikleri devreye almanıza izin vermesidir. Rule Script' konusunda detaya “Ipfw komutları” bölümünde yer vereceğim.
firewall_logging="YES"
Firewall üzerinden geçen trafiği loglamak için. Bu noktada dikkat etmek gereken bir şey var. Normalde bu satırı eklediğiniz zaman net.inet.ip.fw.verbose isimli sysctl variable'ı 1 olarak set ediliyor ve devreye alınıyor.Ancak log limiting için herhangi bir rc.conf ayarı yok. Eğer kernelinizi options IPFIREWALL_VERBOSE_LIMIT=200 satırı ile yeniden derlemediyseniz, bu ayarı /etc/sysctl.conf dosyanızda manuel olarak girmeniz gerekiyor.
net.inet.ip.fw.verbose_limit=5
Not: Benim kurulumunda, kernel'i log limit seçeneği ile yeniden derlemiş olmama rağmen loggingde sorun çıkmıştı. Bu nedenle sysctl.conf dosyasına net.inet.ip.fw.verbose=1 satırını manuel olarak ekledim. Ayrıca limit işlemi için de script dosyası içerisinde “logamount” isimli ipfw komutunu kullanıyorum. Bu komutla ilgili bilgi “ipfw komutları” kısmında bulunuyor.
gateway_enable="YES"
Bu parametre, freebsd'yi gateway olarak kullanmak ve ethernet kartları arasında geçiş sağlamak için gereklidir. Bir firewall kurduğumuza ve muhtemelen networkümüzün çıkış kapısı olarak kullanacağımıza göre bu FreeBSD'yi gateway olarak kullanmanız gerekecektir.
tcp_drop_synfin="YES"
SYN+FIN içeren TCP paketlerini drop eder. Bu özelliğin nmap ile işletim sisteminizin algılanmaması gibi işlevleri vardır.
ÇALIŞMA PRENSİBİ
IPFW'yi devreye aldıktan sonra, sıra networkümüze ve güvenlik politikamıza göre kurallar oluşturmaya geliyor. Ancak önce ipfw'nin mantığından ve söz diziminden bahsedelim. Öncelikle yazının başında adı geçen statless ve stateful firewall kavramlarına değinmekte yarar var. Zira bu her iki firewall kavramını IPFW'de uygulamanız mümkün.
Sateless Firewall:
Stateles (durum kontrolsüz) firewall, kuralların statik olarak tanımlandığı temel paket filtreleme yöntemidir. Ancak eski ve çeşitli alanlar haricinde pek güven vermeyen bir yöntemdir. Zira ilk nesil paket filtreleme teknolojisi olan bu yöntem, IP ve transport layer'da çalışan ve gelen paketlerin sadece header bilgilerinden hareketle karar veren bir yapı olduğu için oldukça basit olarak çalışır. Data akışını kontrol etmeksizin gelen ya da giden paketlerin kaynak ipsini, ulaşmak istediği port ve protokolünü inceler. Eğer üzerinde bağlantı isteğine uyan bir kural varsa , kuralın aksiyon bölümünden hareketle paketi geçirir ya da keser. Bağlantının akışını takip etmediğinden dolayı, firewall'dan daha önceden geçerek kurulmuş bir bağlantının abuse edilmesi suretiyle sisteme saldırıda bulunulmasının önüne geçemez.
Eski olmasına ve güven vermemesine rağmen çeşitli ortamlarda halen kullanmak mümkündür. Örneğin iki farklı lokasyonunuz olması durumunda lokasyonlar arası trafik için stateless kurallar kullanabilirsiniz. Zira kendi kendinize saldırmak gibi bir durum söz konusu olmaz heralde. :)
Stateful Firewall:
Stateful inspection (durum kontrolü) olarak da anılan Stateful (dinamik filtreleme) yapısı, stateless yapısından ayrı olarak bağlantı oturumlarını da gözeterek kuralları bu doğrultuda uygulayan bir yöntemdir ve dinamik kurallar oluşturarak işlem yapabilen mimarilerdir. Bu yapıya ait örnekleri söz dizimi ve komutlar kısmında bulabilirsiniz.
Stateful ve Stateless kavramlarına kısaca değindikten sonra, firewall'un çalışma prensibine geçelim.
Her bir rule için bir kural numarasına ihtiyaç vardır ve ipfw 65535 adet kural tanımlamasına izin vermektedir. Firewall tipini closed olarak tanımladıysanız. 65535 nolu kural “deny ip from any to any” olacak ve gelen giden herşeyi yasaklayacaktır. Firewall mantığında gelen paketler kural numaralarına göre yukarıdan aşağıya doğru adım adım incelenir, paket birinci kural ile eşleşmiyorsa ikinci kurala ikinci ile eşleşmiyorsa üçüncü, dördüncü vs. şeklinde incelenir. Eğer hiçbir kural ile eşleşmeyen bir paket varsa o zaman 65535 no'lu kural devreye girer ve paket bu kurala göre muamele görür. Eğer kernelinizi IPFIREWALL_DEFAULT_TO_ACCEPT opsiyonu ile yeniden derlediyseniz 65535. kural herşeyi geçir manasına gelen “allow ip from any to any” olacaktır.
Bence bir firewall uygulamasında izlenmesi gereken yöntem. Firewall'u closed modda çalıştırmak ve daha sonrasında izin vermek istediğimiz bağlantı çeşitleri için kurallar oluşturmaktır. Ancak henuz bu konuda pek tecrübeli değilseniz başlangıç için firewall'unuzu open modda çalıştırmak ve yasaklamak istediğiniz bağlantılar için kurallar oluşturarak denemeler yapmak iyi bir fikirdir. Konuyu özümsedikten sonra firewall'unuzu closed moda alıp kurallarınızı yeniden oluşturabilirsiniz.
SÖZ DİZİMİ VE KOMUTLAR
Temel olarak ipfw söz dizimi şu şekildedir.
Komut | Kural_Numarası | Aksiyon | Loglama | Seçenek
İşte bu söz dizimine uygun stateles bir ipfw kuralı.
# ipfw add 00010 allow log all from any to any
Bu komutu command-line'dan girdiğiniz zaman firewall'a gelen ve giden tüm paketler için izin ver manasına gelen bir rule tanımlamış olursunuz.
Söz dizimine ait açıklamalar şöyle;
Komut
Örnekte kural eklemek için ipfw add, silmek için ipfw delete.
Kural_Numarası
Her bir kuralın bir numarası olması gerektiğini söylemiştik. 1 ile 65534 (65535 default kural için kullanılır) arasında olabilir. Eşleştirme işlemi kural numaralarına göre yukarıdan aşağıya doğru yapıldığından sıralamaya dikkat etmeniz gerekmektedir.
Aksiyon
Bir çok aksiyon seçeneği bulunmaktadır.
allow: Paketin geçmesine izin verir. Allow yerine aynı anlama gelen “accept”, “pass” ya da “permit” kelimelerini de kullanabilirsiniz.
deny: Paketin geçnesine izin vermez. Ilgili paket silinir. deny yerine aynı anlama gelen “drop” kelimesini de kullanabilirsiniz.
check-state: Stateful kurallar aracılığı ile oluşturulmuş dinamik rulların kontrol edilmesini sağlar. Paker dinamik kurallar ile eşleşmezse bir sonraki kuraldan arama devam eder.
count: Kuralla eşleşen paketleri saymak için kullanılır. Arama işlemi sonraki kuraldan devam eder.
divert (port): Divert soketi kullanan herhangi bir yazılıma port yönlendirmesi yapmak için kullanılır. Eşleşen paketler kuralda belirtilen porta yönlendirilir. Bu özelliği snort_inline için kullanacağız. Yazının başında bahsettiğim gibi bu özellikten yararlanmak için kernelinize options IPDIVERT satırını ekleyip yeniden derlemeniz gerekmektedir.
fwd (ipaddr[port]) : Paketi herhangi bir porta ya da ip adresine yönlendirir. Bu sayede belirlediğiniz tarzdaki bağlantılar için routing işlemi yapabilir birden çok gateway kullanabilirsiniz. Ayrıca mesela hedefi 80 olan istekleri port forwarding ile proxy serverınızın portuna yönlendirebilir ve transparent proxy uygulaması yapabilirsiniz.
nat (numara): Network address translation için kullanılır.
pipe (numara): Bantgenişliğini düzenlemek için kullanılır. Bu sayede limitleme işlemi yapabilirsiniz.
queue(numara): Paket kuyruklarını düzenlemek için kullanılır.
skipto (numara): Paketin diğer kurallarla eşleştirilmeden verilen numaradan başlayarak incelenmesini sağlar.
reset: Eşleşen paketin reddedilmesini sağlar ve karşı tarafa TCP reset (RST) uyarısı gönderir.
tee (port): Eşleşen paketin bir kopyasını divert kullanan bir yazılıma ait porta gönderir. Arama bir sonraki kuraldan devam eder.
Log: İlgili kurala ait işlemlerin loglanmasını sağlar. log logamount (numara) derseniz ilgilil kuralın kaç satır boyunca loglanacağını belirtmiş olursunuz.
Seçenek
Bu kısımda protokol'ü, (tcp/udp/icmp), kaynağı, hedefi, port numarasını, geliş ya da gidişi, hangi interface üzerinden geçtiğini, TCP bağlantı requesti olması durumunda SYN flag ile başlaması gerektiğini ve ilgili kural için dinamik kural oluşturulup oluşturulmayacağını belirleyebilirsiniz.
Temel olarak söz dizimi ile ilgili bilgiler hemen hemen bu kadar. Daha fazlası için ipfw(8) man dosyasını okuyabilirsiniz.
IPFW'nin durumu ile ilgili bilgi almak için komutlar ise şu şekilde:
ipfw list : Kuralları listeler.
ipfw -d list : Dinamikler de birlikte olmak üzere tüm kuralları listeler.
ipfw -d -e list : Expire olmuş dinamik kuralları listeler.
ipfw show : Kuralları, sayaçlarla birlikte listeler.
ipfw zero : Sayaçları resetler.
ipfw resetlog : Log sayaçlarını resetler. (kernelinize, options IPFIREWALL_VERBOSE_LIMIT=200 satırını eklediyseniz ya da logamount ile loglanacak kurallar için satır sınırlaması yaptığınız zaman bu komut oldukça işinize yarayacaktır.)
Söz dizimi ve temel komutlar bu şekildeydi.
Şimdiki aşamada örnek olması açısından kendi kurduğum IPFW konfigurasyonu ve açıklamalarına değinmek istiyorum.
Öncelikle Firewall için kurduğum FreeBSD'nin kerneli'ni aşağıdaki parametrelerle yeniden derledim. Kernel derlemek adetimdir :)
options IPFIREWALL options IPFIREWALL_VERBOSE options IPFIREWALL_VERBOSE_LIMIT=200 options IPFIREWALL_FORWARD options IPDIVERT options DUMMYNET options IPSTEALTH
Serverın gateway olarak kullanılması ve açılışta firewall'un devreye girerel kuralların sisteme tanımlanması için /etc/rc.conf dosyasına aşağıdaki satırları ekledim.
gateway_enable="YES" firewall_enable="YES" firewall_script="/etc/ipfw.rules" firewall_logging="YES" tcp_drop_synfin="YES"
/etc/ipfw.rules isimli bir script dosyası yaratarak içerisine kurallar ile ilgili tanımlamaları girdim.
Script dosyasının örnek içeriği şu şekilde.
# FW Listesini sil.. ipfw -q -f flush # Prefixler lanif="fxp0" wanif="fxp1" lan="192.168.0.0/24" cmd="ipfw -q add" log="log logamount 200" #KURALLAR $cmd 00010 allow all from any to any via lo0 $cmd 00020 allow all from $dmz to $lan $cmd 00030 allow all from $lan to $dmz $cmd 00040 check-state $cmd 00050 allow tcp from 192.168.0.199 to me 22 setup keep-state
Şimdi açıklamalar.
Bu yapıda FreeBSD restart olduğu zaman rc.conf dosyasında belirtilmiş olan script dosyası çalıştırılıyor ve kural tanımlamaları otomatik olarak yapılıyor. Yazının başında kurallar için izlenebilecek iki yöntem olduğunu bahsetmiştim ve ikinci yöntem olan script ile kural tanımlamanın daha iyi bir yol olduğunu, çünkü kural tanımlamalarında yapılan değişikliklerden sonra sistemi reboot etmeye gerek kalmadığını söylemiştim.
Herhangi bir ayar değişikliği yapmanız durumunda, yeni ayarlar için script dosyasını çalıştırmanız yeterlidir.
# sh /etc/ipfw.rules
Yukarıdaki örnek script dosyasının içeriğine dair açıklamalar ise şöyle;
ipfw -q -f flush
Daha önceden eklenmiş kuralları siler.
Prefixler
Script dosyasına bir kural eklerken işin tembelliğine kaçmak için güzel bir yol. Örnekte gördüğünüz gibi kendi network kartlarınızı ve ip networklerinizi prefix olarak ekleyebilirsiniz. Ayrıca ipfw -q add ve log logamount komutunu da ekleyip, kural tanımlamasında $lan vs. gibi bu prefixleri kullanabilirsiniz.
$cmd 00010 allow all from any to any via lo0
Bu kural ile Firewall'un loopback interfaceindeki işlemlerin hepsine izin vermiş oluyoruz.
$cmd 00020 allow all from $dmz to $lan $cmd 00030 allow all from $lan to $dmz
DMZ'ten LAN'a, LAN'dan DMZ'te gidiş geliş full erişim sağlayan stateless kural.
$cmd 00040 check-state
Daha önceden oluşturulmuş dinamik rulların kontrol edilmesini sağlayan tanımlama. (Stateful)
$cmd 00050 allow tcp from $lan to me 22 setup keep-state
LAN'dan gelip Firewall'un 22.(SSH) portuna erişmek isteyen paketler için izin veren stateful kural.
Bu örnek script dosyası ile firewall'a SSH ve LAN DMZ arası trafik için izin verdik. Firewall closed olarak çalıştığı için geri kalan herşer yasaklı durumda. Gördüğünüz gibi yukarıdaki 00040 ve 00050 numaralı kurallar stateful. Bu kurallarda geçen stateful firewalling için kullanılan kelimelerin anlamlarına bakarak bu mimari konusunda daha iyi fikir sahibi olabiliriz.
keep-state
0005o numaralı kuralda geçen keep-state ibaresi bu kural ile eşleşen paketler için birer dinamik kural oluşturulmasını söylüyorlar. Yani siz LAN'dan firewall'un 22. portuna doğru bir bağlantı açarsanız şu şekilde bir kural oluşturulur.
SSH bağlantısı kurdunuz ve dinamik rule oluşturuldu. Artık sizin ip'niz ve source portunuz ile serverin 22. portu arasında tcp trafiğine izin veren bir kural oluşmuş bulunuyor. Kuralın lifetime'ı süresince -ki birazdan lifetime konusunda değineceğim.- ilgili kural sistemde tanınımlı olarak bulunacaktır. 00040 numaralı kural, daha önceden oluşturulan dinamik kuralları check et manasına geldiği için bu tcp bağlantısında giden gelen paketler, dinamik kural ile eşleşecek ve izin verilecektir.
Oluşturulan her dinamik kuralın bir lifetime'ı bulunmaktadır ve süresi biten kurallar sistemden silinir. Lifetime'lar ise paket içeriklerine göre sysctl variable'larıyla belirlenir. Default olarak tanımlanmış bu variableları görmek için aşağıdaki komutu kullanabilirsiniz.
# sysctl -a | grep 'dyn.*lifetime'
Default değerler şöyledir.
net.inet.ip.fw.dyn_short_lifetime: 5 net.inet.ip.fw.dyn_udp_lifetime: 10 net.inet.ip.fw.dyn_rst_lifetime: 1 net.inet.ip.fw.dyn_fin_lifetime: 1 net.inet.ip.fw.dyn_syn_lifetime: 20 net.inet.ip.fw.dyn_ack_lifetime: 300
Yukarıdaki dinamik rule örneğinde lifetime olarak belirlenen (300s), açılan oturum için gerçekleştirilen three-way handshake işleminin son adımı olan, client tarafından servera gönderilen ACK paketinden kaynaklanmaktadır. Yani client olarak siz servera bir ACK paketi gönderdiniz ve oturumu açmış oldunuz. Bu durumda firewall sizin bağlantınız için ömrü 300 s olan bir dinamik rule oluşturdu. Söz konusu olan işlem SYN paketi içeren bir bağlantı isteğine ait olsaydı kuralın lifetime'ı 20 saniye olacaktı. Çıktıda gördüğünüz gibi UDP bağlantılar için 10 saniye süre belirlenmiş durumda. short_lifetime değeri ise ICMP paketleri için kullanılıyor.
setup
Yukarıda, three-way handshake işleminden bahsettim, setup'in tam olarak ne işlevi olduğunu idrak etmek için bu handshake olayına da değinmek gerekiyor. Normalde bir yerden bir yere bir tcp bağlantısı kurmak istediğiniz zaman gerçekleşen adımlar şöyle:
1 – Client bligisayar, bağlantı kurma isteğini belirtmek için bir SYN (Synchronization) paketi gönderir.
2 – Server SYN paketini aldığını belirtmek üzere cliente bir ACK (Acknowledge) paketi ve bir SYN paketi gönderir. (ACK+SYN)
3 – Son adım olarak client, servera bir ACK paketi gönderir ve oturum başlatılmış olur.
Dolayısı ile bu three-way handshaking işlemi bir oturum açmak üzere izlenmesi gereken bir durumdur. Aksi data transferi için bir oturum açılamaz. İşte stateful bir mimari, yukarıda bu konu ile ilgili kısa bilgi verdiğim bölümde de söylediğim gibi bu oturum durumlarını inceleyerek usulsüz bir durum oluşması durumunda gelen paketi otomatik olarak engelleyebilir. Setup ibaresi bu durumu göz eder ve mesela eğer bir SYN/ACK paketi bir oturumun devamı olmaması durumunda engellenmesini sağlar. Ya da bağlantı isteğinin nereden başlatılması gerektiğini belirleyebilir ve aksi durumlarda engellenmesini sağlayabilir. Bu ifade TCP flaglarının kullanımından da anlaşıldığı üzere sadece tcp bağlantılar için oluşturulan kurallar da kullanılmaktadır.
check-state, keep-state ve setup ifadeleri kullanılarak oluşturulmuş güzel bir örnek var. Bu örnek üzerenden ifadelerin çalışma prensibini inceleyelim.
$cmd 01000 check-state $cmd 02000 allow tcp from any to any 22 in setup keep-state
Firewall closed modda çalışıyor ve bu iki kural tanımlanmış durumda. Bu senaryoya göre, firewall'a hedef portu 22 olan bir paket ulaştığı zaman oluşacak işlem adımları şu şekilde.
1 – 172.16.0.1 ip adresli bir bilgisayarın 1234 numaralı portundan, firewall'un arkasında bulunan 192.168.0.1 ip'li bir serverın 22. portuna erişmek üzere legal bir bağlantı isteği (SYN) içeren bir paket geliyor.
2 – 01000 numaralı kural, dinamik ruleları check eden kural olduğundan dolayı kaynağı 172.16.0.1:1234 ve hedefi 192.168.0.1:22 olan hanhangi bir dinamik rule olup olmadığını kontrol ediyor ve daha önce böyle bir bağlantı kurulmamış olduğundan bulamıyor.
3 – Dinamik bir rule bulunamamasından dolayı arama işlemi 02000 numaralı kuraldan devam ediyor. Paket bu kuralda kontrol ediliyor ve eşleşme sağlanıyor. Ayrıca kuralın söz diziminde “keep-state” ifadesi kullanıldığı için bu bağlantı için 20 saniye lifetime'ı olan dinamik bir kural oluşturuluyor. (daha önce bahsettiğim gibi SYN paketleri için default sysclt variable'i 20 saniyedir.)
4 – Şimdiki aşamada, Server, cliente onay niteliğindeki bir ACK paketini gönderiyor.(Ayrıca bir de SYN paketi gönderiyor.)
5 – Normal şartlarda client, serverdan gelen SYN paketini aldığını belirten bir ACK paketi gönderiyor. Bu paket firewall'a ulaştığı zaman tekrar arama işlemi yapılıyor 01000 numaralı kural dinamik ruleları check ediyor ve paket daha önce oluşturulan ve lifetime'ı bitmemiş dinamik rule ile eşleşiyor ve paket firewall üzerinden geçiriliyor. Bu durumda da oturum başlatılmış oluyor.
6 – Eğer 5. adımda client tarafından gönderilen ACK paketi spoof edilmiş olsaydı ve firewall stateless olarak çalışsaydı, spoof edilen paketin geçişine izin verilecekti.
7 – Ama 5. adımda gönderilen ACK paketi spoof edilerek gönderildi ve firewall stateful kurallarımız var. Bu durumda ilgili paket firewall'a geldiğinde 01000 numaralı kural, dinamik ruleları kontrol edecek, ancak herhangi eşleşen bir kayıt bulamayacak. Zira spoof edilmiş paketlerin hedef ip ve portu aynı olmasına rağmen kaynak ip ve portu atakta bulunan kişiler tarafından değiştirilir. Bu durumda 01000 ile eşleşmeyen paket için arama bir sonraki kuraldan devam edecektir.
8 – 02000 numaralı kurala gelen paket, içerisinde SYN flagi içermediğinden dolayı bu kural ile de eşleşmeyecektir. (Zira bu kuralda setup ifadesini kullandık ama bu paketin içeriğinde SYN değil ACK paketi var ve kaynak ip ve portu elimizdeki dinamik ruleda belirtilen kaynak ip ve port numarası ile uyuşmuyor.) Haliyle arama işlemi bir sonraki kuraldan devam edecek.
9 – Firewall closed olduğu ve 65535 numaralı son kuralımız herşeyi yasaklıyor olduğundan dolayı spoof edilen paket bu kurala takılacak ve sistemden geçirilmeyecektir.
Böylece, stateful mimari kullanan iki adet rule ile bir spoof atağı kesmiş olduk. Ancak elbette IPFW ile DoS atakları kesme konusunda belli bir oranda başarı sağlayabilrisiniz. Zira çok yüklü miktarda istek geldiği zaman başetmek de o oranda zorlaşacaktır ki DoS atakların temeli, çok hızlı ve fazla sayıda istekte bulunarak karşı tarafın kaynaklarını tüketmekten ibarettir. Ayrıca her türlü DoS atağı kesmek de pek mümkün değildir.
established
Son olarak, yukarıdaki örnekte geçmeyen ancak stateful mimarisinde kullanılan “established” ifadesine de değinmek istiyorum. Daha önceden kurulmuş olan bir oturuma ait paketlere default izin vermek için kullanılan established ifadesininin geçtiği kuralın söz dizimi şöyledir.
$cmd 00500 allow tcp from any to any established
Bu kural daha önceden kurulmuş bağlantılara ait paketlerin geçişine izin veren genel geçer bir durum olduğundan dolayı, hedef ve kaynak any olarak kullanılmaktadır. Ancak bir önceki spoof edilmiş paket ile ilgili anlatılan örnekte, eğer bu kuralı da kullanmış olsaydık, spoof edilmiş ilgili paket SYN içermemesine rağman, zaten kurulmuş bir bağlantıya ait olduğu gerekçesi ile 00500 tarafından sistemden geçirilecekti.
Stateful ve Stateles firewalling konusuna değindikten sonra, biraz da IPFW'nin trafik limitleme ve kullanım kolaylığı sağlayarak çok işe yarayan table kullanımıyla ilgili örneklere yer vermek istiyorum.
Pipe
Mesela, kullanıcılarınızdan bazıları tüm interneti download etmek için yanıp tutuşuyor ve internete çıkmak için kullandığınız hatlarda hep bir satürasyon durumu yaşıyorsunuz. Bu durumda bazı kullanıcılar, servisler vs. için bandwidth limitleme ihtiyacı hissedebilirsiniz. Bu işlem için firewallunuza pipe ifadesi içeren rulelar girmeniz ve istediğiniz tipteki trafik için limitleme yapmanız gerekecektir. İşte bir torrent yazılımının kullandığı portlar için uygulanan bir limitleme işlemine ait kurallar.
$cmd pipe 1 tcp from $lan to any 43871 $cmd pipe 2 udp from any to $lan 20228 ipfw pipe 1 config bw 1024Kbit/s ipfw pipe 2 config bw 512Kbit/s
1. satır lokal networkten, bir torrent yazılımının download için kullandığı 43871 numaralı porta doğru olan tarfik için bir pipe tanımlamasından ibaret.
2. satır ise, aynı torrent yazılımının upload için default olarak kullandığı 20228 numaralı port için pipe işlemi.
3. satırda, torrent download için 1Mbit sınırlama getiriliyor.
4. satır ise torrent upload için 512Kbit sınırlama getiren tanımlama.
Table
Kaynak adresi ya da hedef adresi birden cok ip'den olusan kurallar girmeye ihtiyacınız olabilir. Normalde bu işi subneting ile yapmak mümkün. Ama bir server farmınız olduğunu ve bu farmdaki serverların bazıları için uygulanacak ortak bir kural girmeniz gerektiğini ancak ilgili serverlara ait ip adreslerinin ardaşık ve subneting ile ifade edilemeyecek adresler olduğunu düşünelim. Bu durumda her bir server için bir kural tanımlamak mi gerekiyor ? IPFW'nin table özelliğini kullanırsanız hayır.
Aynı şey birden çok ip networkü tanımlamak için de geçerlidir.
İşte şöyle.:
Eklemek istediğiniz ip adresi ya da networkleri bu komut ile bir tabloya atayabilirsiniz. Sonra ipfw'ye
ipfw add 00500 allow all from "table(0)" to any keep-state
gibi bir kural girip 0 numaralı tablo içerisinde bulunan tüm ipler için tek kural ile tanımlama yapabilirsiniz. Sisteme 0 ile 127 aralığında ancak 128 adet tablo ekleyebilirsiniz. Tablo kullanımı ile ilgili diğer temel kurallar ise şöyle;
Tablodaki kayıtları görmek için:
Tablodan bir kayıt silmek için:
Herhangi bir tabloyu sıfırlamak.
Tablo kullanımı ile ilgili dikkat edilmesi gereken bir şey var. Tablolarınızı ilgili komutları vererek oluşturup, table ifadesi içeren kurallarınızı yazdınız. Herşer serverı ilk reboot edişinize kadar güzel çalışacaktır. Ancak reboottan sonra tablo kayıtları uçacağı için yazdığınız kurallar bir şey ifade etmeyecektir.
Bu durumu aşmanın yolu ise, açılış sırasında (firewall kurallarının eklenmesi gibi) tabloların da sisteme eklenmesini sağlamaktır. Ben bu iş için gene bir script dosyası kullanıyorum.
/etc/ altında ipfw.tablolar isimli bir dosya açın ve tablo tanımlarınızı girin; mesela şöyle.
#Oncelikle tabloları sifirla. ipfw table 0 flush #Heryere erisenler ipfw table 0 add 192.168.0.5 ipfw table 0 add 192.168.0.199 ipfw table 0 add 192.168.0.122 ipfw table 0 add 192.168.0.150
Bu dosya gördüğünüz gibi önce eski tabloların içeriğini siliyor; sonra ekleme işlemlerini yapıyor.
Daha sonra, sistem açılışında çalışığ, fw kurallarını otomatik olarak tanımlamak için rc.conf dosyana yazdığımız ipfw.rules dosyasının içerisine (kural satırlarından önce) /etc/ipfw.tablolar satırını girin. Bu şekilde, sistem açılırken ipfw.rules dosyası çalışacak ve ipfw.tablolar scriptini çalıştırarak tabloları oluşturacak ve kuralları devreye alacaktır.
Not: Eğer table kullanımında, ilk önce tabloları flush etmezseniz ya da daha script içerisinde ayni ifade iki kere geçerse, bu nedenle hata alır ve sorun yaşarsınız. bu konuya dikkat etmeniz iyi olur :)
IPFW ile ilgili kurulum notları, açıklamalar ve örnekler bu kadar. Bu yazının ikinci bölümünde IPFW kullanarak divert ile snort_inline kurulumu ve konfigurasyonuna ait notları paylaşacağım.
Bkz: http://www.syslogs.org/2008/07/snort_inline-kurulumu/
Kaynaklar:
http://www.freebsd.org/doc/en/books/handbook/firewalls-ipfw.html
http://en.wikipedia.org/wiki/Ipfw
http://www.freebsd-howto.com/HOWTO/Ipfw-HOWTO
Bu yazılar da ilginizi çekebilir:
- IPFIREWALL ve Snort_Inline ile IPS – Part 2: Snort_Inline Kurulumu
- Squid ve IPFIREWALL ile Transparan Proxy Kurulumu
- Apache HTTP DoS Tool ve Önlemler
- Apache için mod_security Kurulumu
- CentOS Üzerine MongoDB Kurulumu
Yorumlar
Trackbacks
Yorumda bulunun.
Çok faydalı ve ayrıntılı bir yazı olmuş.
Tebrikler.
[Cevapla]
Teşekkür ederim.
[Cevapla]
yazıyı henüz uygulama imkanım olmadı ama çok detaylı hazırlanmış, bu kadarı bile en azından birteşekkürü çoktan hakediyor :)
bir ara IPCOP için uğraşmıştım ama yeterli ingilizcem olmadığı için çözememiş ve bırakmıştım. bu tür yazılımların kurulmasında bir şey yok, önemli olan konfigüre edilmeleri.
dolaısıyla çok işe yarayacak bir döküman olmuş, elinize, emeğinize sağlık.
[Cevapla]
Verdiğiniz bilgiler için teşekkür ederim
benim size bir sorum olacaktır xx.xxx.xxx.xxx ipli bir w2003 serverim var SQL server kurulu buna bağlı bazı uygulamalarda çalışıyor kullanıcılar hem web hemde serverda çalışan uygulamaların clientleriyle sisteme bağlanıp yeni bir account oluşturup yada sistemde farklı işlemlerde yapılıyor IPFW firewall kurdum güvenliğimi sağlıyor öyleki bazı ipler botnet saldırısı yapıp hem sitemi hemde server da çalışan programın “login server” ını çökertip yavaşlatıyor bu ip yi ve diğer ip subetlerini engelleyebileceğim bir rule yazmak istiyorum yardımcı olursanız çok sevinirim.
[Cevapla]
Merhaba,
Asagidaki adreste bulunan sunum dosyasi size fikir verecektir.
http://blog.lifeoverip.net/2010/04/02/ozgur-yazilimlarla-ddos-engelleme-sunum-dosyasi/
[Cevapla]