magmalinux-paket-filtreleme

4  Paket Filtreleme

Bu bölümde Linux çekirdeğinin filtreleme (filter) tablosunu düzenleyip, gelen ve giden paketlerimizi filtrelemeyi inceleyeceğiz. Filter tablosunda hali hazırda tablosunda 3 tane zincir (chain) vardır:

  • INPUT bilgisayarımıza gelen paketler için uygulanacak kuralları içeren zincirdir.
  • OUTPUT bilgisayarımızdan dışarı giden paketler için uygulanacak kuralları içeren zincirdir.
  • FORWARD bilgisayarımızdan geçen yönlendirilecek paketler için uygulanacak kuralları içeren zincirdir.

Bu zincirleri bir diagramda inceleyelim:
 

                          _____
Gelen                    /     \         Giden
    -->[Yönlendirme]--->|FORWARD|------->
       [  Kararı   ]     \_____/        ^
            |                           |
            v                         ____
           ___                       /    \
          /   \                     |OUTPUT|
         |INPUT|                     \____/
          \___/                         ^
            |                           |
             ---->   Yerel İşlemler  ----

Zincirler, paketler için uygulanacak kuralların listesi olarak da düşünülebilir. Bir paket, bir zincire vardığında, paketin kaderini belirlemek için bu zincirdeki kurallara sırayla bakılır. Eğer paket, herhangi bir kuralda belirtilen koşullara uyuyorsa, bu kurala göre paket reddedilir (DROP ya da REJECT) veya paket kabul edilir (ACCEPT). Eğer paket, zincirde tanımlanan kuralların hiçbiri ile eşleşmemiş ise, zincirin varsayılan politikası (policy) uygulanır.

Her bir kural, paketler için belli koşullar belirler. Ve bu koşullara uyan paketlere ne yapılacağını tanımlar. Örneğin ICMP protokolü kullanılarak bize gelen bütün paketleri (INPUT) görmezden gelmek (DROP) istediğimizi düşünelim. Bu durumda kurallımızın koşulu gelen paketin protokolünün ICMP olması, hedefi ise DROP’tur. Bu kuralı yaratmadan önce test için ping aracı ile kendi bilgisayarımıza ICMP paketleri gönderelim:

# ping -c 4 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.035 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.041 ms

--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 0.035/0.042/0.053/0.006 ms

Yukarıda görüldüğü gibi, 127.0.0.1 IP adresine (kendi bilgisayarımız) gönderdiğimiz ICMP paketleri kabul edildi. Şimdi iptables INPUT zincirinde bir kural tanımlayıp ICMP paketlerini görmezden gelelim:

# iptables -A INPUT -p icmp -j DROP

Bu komuttaki -A (append) parametresi, belirtilen zincirin sonuna bir kural ekler (Bizim örneğimizde INPUT zinciri). Bu kural -p (protocol) parametresi ile paketler için ICMP protokolü koşulunu tanımlamıştır. Yani bu kural sadece ICMP paketlerini etkileyecek bir kuraldır. Kısaca bu kuralın söylediği şey; gelen (INPUT) ICMP paketleri (-p icmp), DROP hedefine (-j DROP) gönderilir. Hedef, bir diğer deyişle paketin kaderidir. -j parametresi ile belirtebileceğimiz hedefler:

  • ACCEPT paket kabul edilir.
  • DROP paket engellenir ve paketi gönderen kişi paketin engellendiğinden haberdar edilmez.
  • REJECT paketi engeller fakat paketi gönderen kişiye paketin gönderilemediği haber edilir.

Tanımladığımız bu kuraldan sonra, tekrar ICMP paketleri göndermeyi deneyelim:

# ping -c 4 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

--- 127.0.0.1 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3012ms

Bir süre bekledikten sonra zaman aşımına uğrayıp, ping uygulaması cevap beklemekten vazgeçecek.


Zincirleri ve bu zincirlerdeki kuralları listelemek için --list (ya da kısaca -L) parametresini kullanabiliriz:

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       icmp --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Çıktıyı incelediğimizde, INPUT, FORWARD ve OUTPUT isminde üç tane zincirimiz olduğunu ve INPUT zincirinde bir tane kuralımız olduğunu görürüz.

Bir kuralı silmek için; iptables uygulamasının -D (delete) parametresine silmek istediğimiz kuralın bulunduğu zincir ile birlikte, kuralın bu zincirde göründüğü sıra numarasını belirtmeliyiz. Örneğin iptables -L komutu ile INPUT zincirinde gördüğümüz 1. kuralı silmek için:

# iptables -D INPUT 1

komutunu kullanabiliriz. Bir kuralı silmenin bir başka yöntemi, onu tanımladığımız komuttaki -A parametresini -D ile değiştirip, komunun geri kalanını aynı bırakmaktır. Örneğin iptables -A INPUT -p icmp -j DROP komutu ile oluşturduğumuz kuralı silmek için:

# iptables -D INPUT -p icmp -j DROP

komutunu kullanabiliriz. Bir zincirde çok fazla kural bulunduğunda, silinmesi istenen kuralın kaçıncı sırada olduğunu bulmak zorlaşacağı için, bu yöntem kullanışlıdır (Birden fazla aynı kural bulunduğu durumda, sadece zincirde ilk karşılaşılan kural silinecektir).

Belge boyunca denemelerinizi yaparken, zincirleri sık sık temizlemeniz gerekecek. Çünkü -A parametresi ile eklediğiniz her kural zincirin sonuna eklenir. Dolayısıyla yapacağınız testleri önceden tanımladığınız kurallar da etkileyecektir. Kuralları tek tek temizlemek yerine, bütün zincirlerdeki kuralları silmek için –flush (ya da -F) parametresini kullanabilirsiniz:

# iptables -F


Eğer sadece belli bir zincirdeki kuralları temizlemek istiyorsanız -F parametresinden sonra, ilgili zincirin adını verebilirsiniz. Örneğin:

# iptables -F INPUT


Bir paket zincirdeki hiç bir kuralla eşleşmediği durumda, zincirin politikası (policy) uygulanır.  Zincir için geçerli olan politikayı değiştirmek için -P parametresini kullanabilirsiniz (bütün zincirler için varsayılan politika ACCEPT’tir). Örneğin INPUT zincirinin politikasını DROP yapalım:

# iptables -P INPUT DROP

Böylelikle, bir paket, INPUT zincirindeki hiç bir kural ile eşleşmediği vakit engellenecektir.

Dikkat! iptables -F komutu zincirler için varsayılan politikaları ayarlamaz. Sizin her seferinde iptables -P komutu ile ayarlamanız gerekir.

 

4.1  Kaynak ve Hedef Adresine Göre Filtrelemek

Paketin kaynağına göre (paketi gönderene) göre filtreleme yapmak için iptables uygulamasının -s (ya da --source, --src) parametresini kullanabiliriz. Aynı şekilde paketin hedefine göre (paketin gönderileceği adrese) filtreleme yapmak için -d (ya da --destination, --dst) parametresini kullanabiliriz.

Kaynak ya da hedef adresi belirtilirken IP adresi kullanıldığı gibi, alan adı veya bir IP aralığı da belirtilebilir. Örneğin:

# iptables -A INPUT -s www.linuxum.com -j DROP

komutu www.linuxum.com adresinden gelen bütün paketleri engelleyecektir. Alan adı yerine IP adresi ile bir örnek verelim:

# iptables -A OUTPUT -d 78.188.77.207 -j DROP

komutu, 78.188.77.207 IP adresine giden bütün paketleri engelleyecektir.

IP aralığı kullanarak bir örnek verelim:

# iptables -A OUTPUT -s 10.1.0.0/24 -j DROP

komutu, 10.1.0.0 – 10.1.0.255 aralığındaki bütün IP adreslerinden gelen paketleri engeller (IP aralığı kullanılırken CIDR gösterimi yerine netmask’te kullanılabilir. Örneğin 10.1.0.0/24 yerine 10.1.0.0/255.255.255.0 yazmanız aynı anlama gelecektir).

Ayrıca -s ve -d parametrelerini bir arada da kullanabiliriz:

# iptables -A OUTPUT -s 10.1.0.0/24 -d www.linuxum.com -j DROP

komutu, 10.1.0.0 – 10.1.0.255 aralığındaki bütün IP adreslerinden gelip www.linuxum.com adresine giden paketleri engeller.
 

4.1.1  Değil (!) İşleci

Bazı Iptables parametrelerinin önüne ! işareti konularak, istenen özellik tersine çevrilebilir. Örneğin 10.1.0.0/24 IP adresi aralığının dışındaki IP adreslerini belirtmek için -s ! 10.1.0.0/24 şeklinde kullanılabilir:

# iptables -A OUTPUT -s ! 10.1.0.0/24 -j DROP

! işareti, sadece -s paremetresi ile değil aynı zamanda -d parametresi ve daha bir çok Iptables parametresi ile birlikte de kullanılabilir.

 

4.2  Protokole göre filtrelemek

Protokole göre filtreleme yapmak için Iptables’ın -p parametresini kullanırız (Daha önceki örneklerimizde ICMP protokolü ile ilgili işlemler yaparken, -p parametresini kullanmıştık). -p parametresine icmp yanında, tcp ya da udp değerini de verebiliriz (-p parametresinin alacağı değerler büyük/küçük harf duyarsızdır. Yani tcp ile TCP aynı şeydir).

-p parametresi ile birlikte değil ! işareti de kullanılabilir. Örneğin bir kural içerisinde -p ! tcp şeklinde kullanıldığında bu kural TCP dışındaki diğer protokolleri etkiler. Örneğin:

# iptables -A OUTPUT -s 10.1.0.0/24 -p ! tcp -j DROP

komutu, 10.1.0.0/24 IP aralığındaki bilgisayarların tcp protokolü dışındaki protokolleri kullanmalarını engeller.

 

4.3  Arayüze (aygıta) göre filtrelemek

Linux’ta fiziksel ethernet kartınızla, bir arayüz ismi ile iletişim kurarsınız (Örneğin sisteminizdeki birinci ethernet kartının arayüz ismi eth0 iken, bir diğerinin ki eth1 veya başka bir isimde olabilir). Iptables kurallarınızı tanımlarken, bu kuralın sadece belirli bir arayüz için geçerli olmasını istiyorsanız -i (ya da --in-interface) parametresini veya -o (ya da --out-interface) parametresini kullanabilirsiniz.

INPUT zinciri için kural tanımlarken, ortada giden paket olmayacağı için -o parametresini kullanmak anlamsızdır. INPUT zinciri ile sadece -i parametresini kullanmalısınız. INPUT zincirinde -o parametresi belirtilerek tanımlanmış kurallar hiçbir paketle eşleşmeyecektir. Aynı şekilde OUTPUT zinciri için kural tanımlarken, -i parametresini kullanmak anlamsızdır. OUTPUT zincirini için kural tanımlarken yalnızca -o parametresini kullanmalısınız.

Örneğin:

# iptables -A INPUT -i eth0 -j DROP

kuralı eth0’a gelen paketleri engelleyecektir.

# iptables -A OUTPUT -o eth1 -j ACCEPT

kuralı eth1’den giden paketlere izin verecektir.

Yalnızca FORWARD zinciri için tanımlanan kurallarda hem -i hem de -o parametresi kullanılabilir.

Kural tanımlarında arayüz belirtilirken arayüzün o anda aktif olması (up) zorunlu değildir. Aktif olmayan arayüzler için tanımlanan kurallar, arayüz aktif hale geldiğinde etkili olacaktır.

Ayrıca arayüz belirtirken, arayüz isminin sonunda + belirtilmesi durumunda, belirttiğiniz isimle başlayan bütün arayüzler bu kuraldan etkilenecektir. Örneğin -i eth+ şeklinde bir tanımlama, eth0, eth1 … gibi eth ile başlayan bütün arayüzleri etkiler.

Son olarak -i ya da -o parametresinden sonra ! işaretini, belirtilen arayüz dışındaki arayüzleri kastetmek amacıyla kullanabilirsiniz. Örneğin -i ! eth+ parametresi ile tanımlanmış bir kural, eth ile başlamayan arayüzleri etkileyecektir.

 

4.5  Kullanıcı Tanımlı Zincirler

Var olan zincirlerin yanında, -N parametresi ile kendiniz de zincir tanımlayabilirsiniz:

# iptables -N TCPKURALLARI

Yarattığımız bu zincire bir kural ekleyelim:

# iptables -A TCPKURALLARI -s 10.1.0.116 -p tcp -j DROP

Yarattığımız bu zincirin kullanılması için, bu zincirin tanımladığınız kurallardan birinin hedefi olması gerekir. Örneğin:

# iptables -A INPUT -p tcp -j TCPKURALLARI

Bir paket kullanıcı tanımlı zincirdeki hiçbir kural ile eşleşmez ise, geldiği zincire geri döner. Yukarıdaki örneğimizde gelen paket TCPKURALLARI içerisindeki hiçbir kural ile eşleşmediği durumda, TCPKURALLARI zincirinden çıkılıp; INPUT zincirindeki, bir sonraki kuraldan devam edilir. Bu yüzden, kullanıcı tanımlı zincirler için politika belirtemezsiniz.


Bir zinciri silmek için, önce -F ZINCIRADI parametresi ile o zincirdeki bütün kuralları temizlemeli, ardından boş olan zinciri silmek için, -X ZINCIRADI parametresini kullanmalısınız. Örneğin:

# iptables -F TCPKURALLARI
# iptables -X TCPKURALLARI

-X parametresi zincir adı belirtilmeden kullanıldığında, boş olan tüm kullanıcı tanımlı zincirleri silecektir.

 

4.5  Iptables Eklentileri

Iptables’ı eklenti kullanarak genişleyebilir yapıya sahiptir. Örneğin, -p parametresi ile protokol belirttiğinizde belirttiğiniz protokole özgü eklenti otomatik olarak yüklenip size ekstra koşullar (testler) sunar.

4.5.1  TCP Eklentileri

Iptables’a -p tcp parametresi verdiğinizde TCP eklentileri otomatik olarak yüklenir. Bu eklenti hakkında bilgi almak için:

# iptables -p tcp --help

komutunu çalıştırıp, çıktının en altında TCP eklentisinin sürümünü ve seçeneklerini görebilirsiniz.

TCP eklentisinin bize sağladığı bazı testleri inceleyelim:

--source-port (ya da --sport) TCP paketinin kaynak portuna göre bir kural tanımlamamızı sağlar. 80 gibi port numarası yerine www gibi isimler de kullanılabilir (bu kullanılan isimlerin port numarası karşılıkları /etc/services dosyasına bakılarak bulunur). Ayrıca belli port aralıkları da belirtilebilir. Örneğin --source-port 4400:4500 şeklinde kullanıldığında, 4400 ve 4500 aralığındaki bütün portlar kastedilir. Ayrıca tanımlanan kuralın 4400 den büyük portlar ile eşlenmesi isteniyorsa --source-port 4400: şeklinde, 4400 den küçük portlar ile eşlenmesi isteniyorsa --source-port :4400 şeklinde kullanılabilir. Örneğin 22 ve 23 numaralı porta dışarıdan bağlanılmasına izin verelim:

# iptables -A INPUT -p tcp --dport 22 -j ACCEPT

--destination-port (ya da –dport) TCP paketinin hedef portuna göre bir kural tanımlamamızı sağlar. Kullanım şekli --source-port ile aynıdır.
 

–tcp-flags parametresi, TCP bayrakları üzerinde maskeleme yapıp, belli bayrakların durumunu kontrol etmemizi sağlar. Kullanımı:

–tcp-flags maske karşılaştırma

şeklindedir. Örneğin, 23 numaralı porta gelen SYN paketlerine izin vermek istemiyorsak:

# iptables -A INPUT -p tcp –dport 23 –tcp-flags SYN,ACK,RST,FIN SYN -j DROP
 

–syn parametresi –tcp-flags SYN,RST,ACK,FIN SYN parametresi için kısa addır.
 

4.5.2  UDP Eklentileri

UDP eklentileri, iptables’a -p udp parametresini verdiğimizde otomatik olarak yüklenir. UDP Eklentileri ile birlikte gelen parametreler, TCP eklentisinde olduğu gibi –source-port (–sport) ve –destination-port (–dport) tur. Aynı şekilde kullanılır.