Linux Güvenlik Duvarı: ufw ve iptables Kuralları Rehberi

ufw ile hızlı kurulumu, iptables ile ince kontrolü, SSH port değişikliğini ve kural testini gerçek komutlarla anlatan pratik bir güvenlik duvarı rehberi.

Linux
Linux Güvenlik Duvarı: ufw ve iptables Kuralları Rehberi

Bir sunucu internete açıldığı andan itibaren hedef hâline gelir: güvenlik duvarı devrede değilse otomatik tarama botları açık SSH ve veritabanı portlarını genelde ilk birkaç dakika içinde bulur. Linux'ta bu koruma iki araçla kurulur: ufw ve iptables. İkisi de aynı çekirdek bileşenini (netfilter) kullanır, aralarındaki fark yalnızca arayüzdedir. Hangisini ne zaman tercih edeceğinizi ve pratikte hangi kuralları yazmanız gerektiğini bu yazıda ele alıyorum.

ufw neden çoğu sunucu için yeterlidir?

ufw (Uncomplicated Firewall), iptablesin üzerine kurulu basitleştirilmiş bir arayüzdür ve Ubuntu ile türevlerinde varsayılan olarak gelir. Temel kurulum üç komuttan oluşur:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh

Sıra burada önemlidir: önce varsayılan politika reddetmeye ayarlanır, ardından SSH açık bırakılır. Kuralı eklemeden ufw enable komutunu çalıştırırsanız uzak bağlantınız o anda kesilir; sunucuya konsoldan ya da fiziksel olarak erişemiyorsanız dışarıda kalırsınız. ufw enable öncesinde bu sırayı mutlaka kontrol edin.

Bulut üzerinde çalışan sunucularda (DigitalOcean, Hetzner, AWS gibi) sunucu içindeki ufwnin ötesinde ikinci bir katman daha vardır. Bu katman, sağlayıcının kendi güvenlik grubu ya da bulut paneli üzerindeki port ayarlarından oluşur. Bu panel, sunucu içindeki ufw kurallarını hiç görmez; sağlayıcı tarafında bir port kapatılmışsa ufw o portu açık gösterse bile dışarıdan hiçbir bağlantı geçmez. Bir bağlantı sorununda yalnızca sunucunun içine bakmak yanıltıcı bir teşhis çıkarır; sağlayıcı panelini de aynı anda kontrol etmek gerekir.

Web sunucusu için HTTP ve HTTPS portlarını açmak:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Kuralları numaralı biçimde listelemek için:

sudo ufw status numbered

Numarasını bildiğiniz bir kuralı doğrudan silebilirsiniz: sudo ufw delete 3. Belirli bir IP'den gelen bağlantıya izin vermek için, örneğin ofis IP'nizden yönetim paneline erişim açmak için:

sudo ufw allow from 203.0.113.10 to any port 8080

Kurulu servisler için hazır uygulama profilleri de vardır. sudo ufw app list komutu bu profilleri (Nginx, Apache gibi) listeler; sudo ufw allow 'Nginx Full' yazarak port numarasını hiç bilmeden kural eklenebilir.

SSH portunu değiştirdiyseniz ufw'yi nasıl güncellersiniz?

Varsayılan 22 portunu değiştirmek otomatik tarama botlarının büyük kısmını devre dışı bırakır. Ancak port değiştiyse ufw allow ssh artık işe yaramaz; bu kısayol /etc/services dosyasındaki 22 numaralı tanıma bakar, yeni port numarasını tanımaz.

Terminalde ufw ile özel SSH portunun izin verilmesi
sudo ufw allow 2222/tcp comment 'SSH ozel port'
sudo ufw delete allow ssh

comment etiketi, aylar sonra ufw status çıktısına bakıldığında "bu kural neden eklendi" sorusuna cevap verir. Kural listesi büyüdükçe bu küçük alışkanlık zaman kazandırır, özellikle sunucuya birden fazla kişi erişiyorsa. ufw ile hız sınırlama da kolaydır; brute-force SSH denemelerine karşı kullanılır:

sudo ufw limit 2222/tcp

limit kuralı, aynı IP'den 30 saniye içinde 6'dan fazla bağlantı denemesi gelirse o IP'yi geçici olarak engeller. fail2ban kadar gelişmiş değildir ama tek satırla ek bir koruma katmanı ekler. Daha kalıcı bir çözüm için fail2ban kurup SSH log dosyasını izletmek, tekrarlayan başarısız girişleri iptables seviyesinde otomatik engeller:

sudo apt install fail2ban
sudo systemctl enable --now fail2ban

Varsayılan yapılandırma SSH'ı zaten korur. /etc/fail2ban/jail.local dosyasında maxretry ve bantime değerleri risk toleransına göre ayarlanır. Örnek olarak, beş yanlış denemenin ardından bir saat süreyle engelleme uygulamak dengeli bir başlangıç sayılır. fail2ban'ın ufw limit'ten farkı, engellediği IP'yi belirli bir süre sonra kendiliğinden serbest bırakmasıdır; bu da kendinizi yanlışlıkla dışarıda bırakma ihtimalinizi düşürür.

iptables ile ince kontrol ne zaman gerekir?

Günlük kullanımda ufw yeterlidir. Ama NAT kurulumu, port yönlendirme ya da çok adımlı zincir mantığı gerektiren senaryolarda iptables'a doğrudan inmek daha fazla esneklik sağlar. Mevcut kuralları görmek için:

sudo iptables -L -n -v --line-numbers

-L parametresi kuralları listeler, -n isim çözümlemesini (DNS lookup) devre dışı bırakarak komutu hızlandırır, -v ise her kuralın paket ve bayt sayaçlarını ekrana getirir. iptables üç ana zincir üzerinden çalışır: gelen trafik INPUT'tan, giden trafik OUTPUT'tan, yönlendirilen trafik FORWARD'dan geçer. Bir web sunucusunda kuralların büyük kısmı INPUT zincirinde tutulur; FORWARD ise sunucu bir yönlendirici ya da Docker sunucusu olarak çalışıyorsa devreye girer. Temel bir güvenli yapılandırma şöyledir:

sudo iptables -P INPUT DROP
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Kuralların sırası burada belirleyicidir. Değerlendirme yukarıdan aşağıya ilerler ve bir paket ilk eşleştiği kuralla işlem görür. lo (loopback) arabirimine izin verilmezse sunucudaki servisler birbiriyle iletişim kuramaz; pratikte sık karşılaşılan bir hata budur. ESTABLISHED,RELATED satırı eksikse her paket baştan değerlendirmeye girer ve hâlihazırda kurulu bağlantılar da bu yüzden kesilebilir.

ICMP (ping) trafiğini komple engellemek ilk bakışta mantıklı görünür, ama bazı ağ teşhis araçları bu trafiği kullanır. Tercih edilmesi gereken, tamamen kapatmak değil hızını sınırlamaktır:

sudo iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

Bu kural saniyede birden fazla ping talebini reddeder; böylece olası bir ICMP flood girişimi sınırlanır ama traceroute ya da ping gibi olağan teşhis işlemleri etkilenmez.

iptables kurallarını kalıcı hale getirmek neden ayrı bir adım?

iptables ile eklenen kurallar varsayılan olarak yalnızca çalışma belleğinde durur; sunucu yeniden başlatıldığında tüm kurallar sıfırlanır. Debian/Ubuntu'da iptables-persistent paketi bu sorunu çözer:

ufw ve iptables kullanım senaryolarını karşılaştıran karar şeması
sudo apt install iptables-persistent
sudo netfilter-persistent save

Bu iki komut mevcut kural tablosunu /etc/iptables/rules.v4 dosyasına kaydeder ve sunucu her açıldığında bu kuralları otomatik olarak yeniden yükler. RHEL/CentOS tabanlı dağıtımlarda bu görevi firewalld üstlenir; ancak firewalld, iptablesten farklı bir kavram modeliyle (zone tabanlı) çalışır. İki sistemi aynı makinede birlikte aktif bırakmayın, çakışan kurallar ortaya çıkar.

iptables yalnızca IPv4 trafiğini kapsar; IPv6 kullanan bir sunucuda ip6tables kurallarını ayrıca tanımlamanız gerekir. ip6tables-persistent paketi (çoğunlukla iptables-persistent ile birlikte kurulur) aynı mantıkla bu kuralları kalıcı hâle getirir. Sunucuda IPv6 açıkken yalnızca iptables kuralları tanımlıysa IPv6 trafiği güvenlik duvarını hiç görmeden geçer; sık gözden kaçan bir açık budur. iptables'ın arkasındaki çerçeveyi geliştiren netfilter projesi, kuralların çekirdek düzeyinde nasıl işlediğini belgeler.

ufw ile iptables karışık kullanılırsa ne olur?

ufw, aslında perde arkasında iptables kurallarını kendisi yazan ve yöneten bir katmandır; /etc/ufw/ dizinindeki dosyaları açtığınızda bu ham kuralları doğrudan görebilirsiniz. İki aracı aynı anda elle yönetmeye çalışmak öngörülemeyen sonuçlar doğurur: ufw çalışırken iptables -A ile doğrudan kural eklerseniz, sonraki bir ufw reload bu kuralı silebilir ya da tamamen yok sayabilir.

Terminalde iptables log kuralı ile reddedilen paketlerin kaydedilmesi
SenaryoÖnerilen araç
Standart web/SSH sunucusu, hızlı kurulumufw
Karmaşık NAT, port yönlendirme, çoklu arayüziptables doğrudan
RHEL/CentOS tabanlı sistemfirewalld
Zaten ufw kurulu, özel bir kural gerekiyorufw içinde /etc/ufw/before.rules düzenle

ufw kullanıp yalnızca tek bir özel kurala ihtiyaç duyuyorsanız, bunu doğrudan iptables -A ile değil /etc/ufw/before.rules ya da after.rules dosyasına yazarak ekleyin; bu dosyalar her ufw yüklemesinde okunduğu için kural kalıcı kalır.

Docker kullanan sunucularda farklı bir risk vardır. Docker, konteyner portlarını dışarı açarken kendi kurallarını doğrudan DOCKER zincirine yazar ve bu, çoğu zaman ufwnin deny politikasını devre dışı bırakır. Özetle kapalı sandığınız bir konteyner portu aslında dışarıdan erişilebilir durumda olabilir; bunu anlamanın tek yolu, konteyner çalışırken sunucuyu dışarıdan taramaktır.

Kuralları test etmeden güvenmek neden riskli?

Eklediğiniz her güvenlik duvarı kuralının fiilen beklediğiniz gibi çalıştığını doğrulamak, kuralı yazmak kadar önemli bir adımdır. Kuralı eklemeden önce hangi sonucu beklediğinizi net biçimde tanımlayın, sonra bu beklentiyi test edin. Güvenlik duvarında "muhtemelen çalışıyordur" kabul edilebilir bir sonuç değildir. nmap, sunucuyu dışarıdan tarayarak hangi portların gerçekten açık göründüğünü gösterir:

nmap -Pn -p 1-1000 sunucu-ip-adresi

nmap taramasını sunucunun üzerinden değil, ayrı bir makineden çalıştırın. Sunucunun kendi üzerinden yapılan tarama lo arabirimi yüzünden farklı, yanıltıcı bir sonuç verebilir. Kapalı beklediğiniz bir port taramada açık çıkarsa sorun genelde kural sırasındadır. Listede daha önce gelen ve trafiği zaten kabul eden geniş kapsamlı bir kural, beklediğiniz kısıtlayıcı kuralın önüne geçmiş olabilir.

Bunu ss -tulnp komutuyla tamamlayabilirsiniz; bu komut sunucu tarafında hangi servisin hangi portu dinlediğini gösterir:

sudo ss -tulnp

nmap dışarıdan neyin göründüğünü, ss ise sunucuda gerçekte neyin çalıştığını gösterir. İkisi çelişiyorsa iki olası durum vardır: güvenlik duvarı dinlemeyen bir portu gereksiz açık bırakmıştır ya da tam tersi. Her değişiklikten sonra bu iki komutu birlikte çalıştırmak, "kural eklemiştim, çalıştığını sanıyordum" tipi sürprizleri baştan önler.

Engellenen bağlantıları nasıl izlersiniz?

Bir kural bağlantıyı reddettiğinde sebebi belirsizse, çözüm loglamayı açmaktır. ufw için:

sudo ufw logging on
sudo tail -f /var/log/ufw.log

Bu ayar, reddedilen her paketi zaman damgası, kaynak IP ve port bilgisiyle log dosyasına yazar. Meşru bir istemcinin neden bağlanamadığını anlamak için tahmin yürütmek yerine doğrudan bu dosyaya bakmak sorunu genelde dakikalar içinde ortaya çıkarır. Doğrudan iptables kullanıyorsanız benzer bir log kuralı ekleyebilirsiniz:

sudo iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4
sudo iptables -A INPUT -j DROP

Log kuralı mutlaka DROP kuralından önce tanımlanmalıdır; sıralama tersine dönerse paket loglanmadan doğrudan atılır. Bu loglar zamanla /var/log/syslog ya da /var/log/kern.log altında birikir; trafiği yoğun bir sunucuda hacim hızla büyür. logrotate ile üst sınır koyun.

Yapılan kural değişikliklerini bir yerde kayıt altına almak da faydalıdır. iptables-save çıktısını Git gibi bir sürüm kontrol sistemine eklemek, hangi kuralın ne zaman ve hangi gerekçeyle eklendiğini sonradan takip etmenizi sağlar:

sudo iptables-save > /root/firewall-kurallari-$(date +%F).txt

Bu basit alışkanlık, ileride "önceden çalışıyordu, aradan ne değişti" tarzı sorulara hızlı cevap bulmanızı sağlar. Daha karmaşık senaryolar için Ubuntu'nun resmi ufw belgelerine ve netfilter.org üzerindeki iptables kılavuzuna bakabilirsiniz.

Celil Uyanikoglu

Yazan Celil Uyanikoglu

Bilgisayar mühendisiyim; 25 yılı aşkın süredir bilgi işlem sektörünün içindeyim. Bu blogu 2020'de, işimde her gün karşılaştığım sorunların çözümlerini bir yere yazmak için açtım: Linux, güvenlik, tarayıcılar, yapay zeka araçları. Yazdığım her rehberi önce kendi bilgisayarımda ya da sunucumda deniyorum; çalıştığını görmediğim adımı yayınlamam. Hatalı ya da eskimiş bir şey görürsen iletişim sayfasından yaz — düzeltirim.

Yorum

Henüz yorum yok.

Sohbete katıl. Yorumlar yayınlanmadan önce moderasyondan geçer.

Yorum yap

E-posta adresin yayınlanmaz. Yorumlar moderasyondan sonra yayınlanır.

Sırada

İlgili notlar

jekcms 61602b0e6293b42004a1