UFW (Uncomplicated Firewall), Linux güvenlik duvarı kurallarını daha okunabilir komutlarla yönetmek için kullanılan bir ön yüzdür. Uzak bir sunucuda kural değiştirirken önce yönetim erişimini açık tutacak SSH kuralını doğrulamak ve olası kilitlenmeye karşı ikinci bir oturum bulundurmak gerekir.
UFW Nedir?
UFW, Ubuntu ve diğer Debian tabanlı dağıtımlarda bulunan user-friendly firewall management tool’udur. Arkada iptables çalışır, ama UFW sayesinde karmaşık iptables kurallarını basit komutlarla yönetebilirsiniz.
Temel Kavramlar
# UFW status kontrolü
sudo ufw status
# UFW'yi aktif etme
sudo ufw enable
# UFW'yi devre dışı bırakma
sudo ufw disable
# Verbose output
sudo ufw status verbose
# Numaralı liste (kural silme için)
sudo ufw status numbered
Önce: uzak sunucuda erişimi kaybetmemek
ufw enable komutu, kuralları yazmadan önce çalıştırıldığında yönetim erişimini
kesebilir. Uzak bir sunucuda bu, konsol erişimi olmadan geri dönülemeyen bir durumdur.
Kural değiştirmeye başlamadan önce aşağıdaki sıra izlenmelidir.
1. Gerçek SSH portunu doğrulayın. ufw allow ssh komutu servis adını
/etc/services üzerinden çözer ve 22 numaralı portu açar. SSH başka bir porta
taşınmışsa bu kural işe yaramaz ve ufw enable bağlantıyı keser:
sudo ss -tlnp | grep sshd
2. Kuralı UFW’yi etkinleştirmeden önce ekleyin. Çıkan portu açıkça yazın:
sudo ufw allow 22/tcp
3. Kuralları uygulamadan önce sonucu görün. --dry-run, oluşacak kural setini
hiçbir değişiklik yapmadan yazdırır:
sudo ufw --dry-run enable
4. İkinci bir oturum açık tutun. Etkinleştirme sırasında mevcut SSH oturumunuzu
kapatmayın. UFW enable komutu bu nedenle onay sorar.
5. Etkinleştirin ve üçüncü bir oturumla doğrulayın. Yeni bir bağlantı kurulabildiğini görmeden mevcut oturumları kapatmayın:
sudo ufw enable
sudo ufw status verbose
Sağlayıcınızın web konsolu (KVM, seri konsol veya kurtarma modu) varsa bunu önceden denemiş olmak, kilitlenme durumunda tek geri dönüş yoludur.
Temel UFW Komutları
1. Port Yönetimi
# Belirli port'u aç
sudo ufw allow 22 # SSH
sudo ufw allow 80 # HTTP
sudo ufw allow 443 # HTTPS
# Port aralığı
sudo ufw allow 6000:6007
# Protokol belirterek
sudo ufw allow 22/tcp
sudo ufw allow 53/udp
# Port'u kapat
sudo ufw deny 23 # Telnet'i yasakla
Kaynak belirtilmeden yazılan bir allow kuralı portu tüm adreslere açar. Bu,
herkese açık olması gereken web servisleri için doğrudur; geliştirme sunucuları,
veritabanları ve yönetim arayüzleri için değildir. Bu tür servisler için bir sonraki
başlıktaki kaynak kısıtlı biçimi kullanın.
2. Service-based Rules
# Service name ile
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw allow ftp
# Service listesi
sudo ufw app list
# Specific app profile
sudo ufw allow 'Apache Full'
sudo ufw allow 'Nginx Full'
sudo ufw allow 'OpenSSH'
Servis adları /etc/services üzerinden sabit port numaralarına çözülür: ssh her
zaman 22, http 80, https 443 anlamına gelir. Servisi standart dışı bir portta
çalıştırıyorsanız servis adı yerine port numarasını yazın.
ufw limit komutu da burada anılmayı hak eder, çünkü davranışı adından anlaşılmıyor:
sudo ufw limit 22/tcp
Bu kural, aynı kaynak IP adresinden 30 saniye içinde altıncı ve sonraki bağlantı girişimlerini reddeder. Kaba kuvvet denemelerini yavaşlatır, fakat tek başına bir kimlik doğrulama önlemi değildir; anahtar tabanlı SSH ve parola girişinin kapatılması ile birlikte düşünülmelidir.
3. IP Address Rules
# Specific IP'den gelen bağlantıları izin ver
sudo ufw allow from 192.168.1.100
# IP aralığı
sudo ufw allow from 192.168.1.0/24
# Specific IP'yi yasakla
sudo ufw deny from 192.168.1.50
# Specific IP'den specific port'a
sudo ufw allow from 192.168.1.100 to any port 22
Geliştirme sunucusu için örnek kural seti
Komutları tek bir betiğe koyup topluca çalıştırmak yerine sırayla uygulamak ve her
adımda ufw status ile sonucu görmek daha güvenlidir; kural hatası ancak erişim
kaybedilmeden fark edilirse ucuza kapanır.
ufw reset mevcut tüm kuralları siler ve güvenlik duvarını devre dışı bırakır.
Çalışan bir sunucuda kullanmadan önce mevcut durumu kaydedin:
sudo ufw status numbered > ~/ufw-kurallar-yedek.txt
Temel politika ve herkese açık servisler:
# Varsayılan politika: gelen kapalı, giden açık
sudo ufw default deny incoming
sudo ufw default allow outgoing
# SSH: gerçek portu yukarıdaki bölümde doğruladıktan sonra
sudo ufw limit 22/tcp
# Herkese açık web servisleri
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Geliştirme sunucuları ve veritabanları kaynak kısıtı olmadan açılmamalıdır.
React, Flask ve Django’nun geliştirme sunucuları üretim için tasarlanmamıştır:
Flask’ın hata ayıklama konsolu tarayıcı üzerinden kod çalıştırmaya izin verir,
Django DEBUG=True ayarıyla gizli anahtarı ve veritabanı bilgilerini hata
sayfasında gösterir. İnternete açık bir port bu yüzeyleri doğrudan erişilebilir
kılar.
# Geliştirme sunucuları: yalnızca yerel ağdan
sudo ufw allow from 192.168.1.0/24 to any port 3000 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 5000 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 8000 proto tcp
# Veritabanları: yalnızca bilinen kaynaklardan
sudo ufw allow from 192.168.1.0/24 to any port 3306 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 5432 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 27017 proto tcp
Daha güvenli bir yaklaşım, geliştirme sunucusunu yalnızca geri döngü arayüzüne bağlamak ve uzaktan erişimi SSH tüneliyle sağlamaktır. Bu durumda güvenlik duvarında hiçbir ek port açmanız gerekmez:
# Sunucuda: yalnızca 127.0.0.1 dinlenir
python manage.py runserver 127.0.0.1:8000
# İstemcide: tünel açılır
ssh -L 8000:127.0.0.1:8000 kullanici@sunucu
Kural setini uyguladıktan sonra etkin politikayı ve gerçek dinleme durumunu ayrı ayrı doğrulayın:
sudo ufw status verbose
sudo ss -tlnp
Docker kullanıyorsanız UFW kurallarınız geçersiz olabilir
Bu, UFW ile ilgili en sık karşılaşılan ve en geç fark edilen sorundur.
Docker, yayımlanan portlar için kendi iptables kurallarını DOCKER-USER zincirine
yazar; bu kurallar UFW’nin ürettiklerinden önce değerlendirilir. Bir konteyneri -p
ile yayımladığınızda port, UFW’de ne yazdığından bağımsız olarak dışarıdan
erişilebilir hâle gelir:
docker run -d -p 3306:3306 mysql # port dışarıya açıldı
sudo ufw deny 3306 # bu kuralın etkisi yok
sudo ufw status # kural yine de "aktif" görünür
Pratik çözüm, portu yalnızca geri döngü arayüzüne yayımlamaktır:
docker run -d -p 127.0.0.1:3306:3306 mysql
Konteyner portlarının gerçekten dışarıya açılması gerekiyorsa filtreleme
DOCKER-USER zincirine yazılmalıdır; UFW bu zinciri yönetmez. Kuralların
uygulandığını doğrulamak için:
sudo iptables -L DOCKER-USER -n -v
Sıkı politika: giden trafiği de kısıtlamak
Giden trafiği varsayılan olarak kapatmak, ele geçirilmiş bir sistemden veri sızdırılmasını ve zararlı yazılımın dışarıya bağlanmasını zorlaştırır. Bedeli, sunucunun kurduğu her dış bağlantının açıkça izinlendirilmesi gerekmesidir.
sudo ufw default deny outgoing
sudo ufw allow out 53 # DNS
sudo ufw allow out 80/tcp # HTTP
sudo ufw allow out 443/tcp # HTTPS
sudo ufw allow out 123/udp # NTP
Bu politikaya geçmeden önce hangi işlerin kesileceğini bilmek gerekir. Yukarıdaki izinler yalnızca ad çözümleme, paket deposu erişimi ve saat eşitlemesi için yeterlidir. Şunlar açıkça izinlendirilmedikçe çalışmaz:
- SSH üzerinden git erişimi (
git clone git@github.com:...), yani giden 22 - standart dışı portlarda çalışan dış API ve veritabanı bağlantıları
- giden e-posta (SMTP 587 veya 465)
- kendi izleme veya günlük toplama sisteminize gönderim
Kesilen bağlantılar çoğunlukla zaman aşımı olarak görünür ve sebebinin güvenlik duvarı olduğu hemen anlaşılmaz. Bu nedenle politikayı önce günlüğe alarak gözlemlemek, sonra kısıtlamak daha güvenlidir.
IPv6 kuralları ayrıdır
UFW varsayılan olarak IPv6 kurallarını da üretir; bu davranış /etc/default/ufw
dosyasındaki IPV6=yes satırıyla belirlenir ve ufw status çıktısında (v6) ekli
satırlar olarak görünür.
Dikkat edilmesi gereken nokta, adres tabanlı kuralların adres ailesine özgü olmasıdır. Bir IPv4 adresini engellemek aynı sunucunun IPv6 adresini engellemez:
sudo ufw deny from 203.0.113.50 # yalnızca IPv4
sudo ufw deny from 2001:db8::50 # IPv6 için ayrı kural gerekir
Sunucunuz IPv6 üzerinden erişilebilir durumdaysa port kurallarınızın her iki adres
ailesinde de beklediğiniz gibi göründüğünü sudo ufw status verbose ile doğrulayın.
İzleme
Engellenen bağlantıları görüntüleme
UFW günlükleri varsayılan olarak kapalıdır ve açıkça etkinleştirilmelidir:
sudo ufw logging low
Günlüklerin nereye yazıldığı sistemin yapılandırmasına bağlıdır. Rsyslog kuruluysa
kayıtlar /var/log/ufw.log dosyasına düşer; kurulu değilse — modern Ubuntu Server
kurulumlarında sıkça böyledir — yalnızca çekirdek günlüğünde bulunurlar:
# Rsyslog kuruluysa
sudo grep 'UFW BLOCK' /var/log/ufw.log | tail -20
# Her durumda çalışır
sudo journalctl -k --grep='UFW BLOCK' --since '1 hour ago'
Kaynak adresi ve hedef portu alan numarasına göre değil alan adına göre ayıklamak daha dayanıklıdır; UFW satırlarındaki alan sayısı arayüze ve protokole göre değişir:
# En çok engellenen kaynak adresler
sudo journalctl -k --grep='UFW BLOCK' --since today \
| grep -oE 'SRC=[^ ]+' | sort | uniq -c | sort -nr | head -10
# En çok hedeflenen portlar
sudo journalctl -k --grep='UFW BLOCK' --since today \
| grep -oE 'DPT=[0-9]+' | sort | uniq -c | sort -nr | head -10
Düzenli rapor için systemd timer
Sürekli çalışan bir kabuk döngüsü yerine zamanlanmış bir servis kullanmak daha öngörülebilirdir: zamanlama, günlükleme ve hata durumunda davranış sistem tarafından yönetilir, PID dosyası tutmak gerekmez.
/usr/local/bin/ufw-rapor betiği:
#!/usr/bin/env bash
set -euo pipefail
esik=100
sayi=$(journalctl -k --grep='UFW BLOCK' --since '1 hour ago' | wc -l)
echo "Son bir saatte engellenen bağlantı: ${sayi}"
if (( sayi > esik )); then
echo "UYARI: eşik (${esik}) aşıldı" >&2
exit 1
fi
/etc/systemd/system/ufw-rapor.service:
[Unit]
Description=UFW engelleme raporu
[Service]
Type=oneshot
ExecStart=/usr/local/bin/ufw-rapor
/etc/systemd/system/ufw-rapor.timer:
[Unit]
Description=UFW engelleme raporunu saatlik çalıştır
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
Devreye alma ve izleme:
sudo systemctl daemon-reload
sudo systemctl enable --now ufw-rapor.timer
journalctl -u ufw-rapor.service
Betik standart çıktıya yazdığı için ayrı bir günlük dosyası tutmak gerekmez;
çıktıyı journald toplar. Eşik aşıldığında servis başarısız duruma geçer ve bu
durum OnFailure= ile bir bildirim unit’ine bağlanabilir.
Kuralları yedeklemek ve geri yüklemek
UFW kurallarını /etc/ufw/user.rules (IPv4) ve /etc/ufw/user6.rules (IPv6)
dosyalarında tutar. Yedek alırken ikisini birden almak gerekir; yalnızca IPv4
dosyasını geri yüklemek IPv6 kurallarının eski hâlde kalmasına yol açar.
Okunabilir bir anlık görüntü için:
sudo ufw status numbered > ~/ufw-durum-$(date +%F).txt
Bu dosya doğrudan geri yükleme için kullanılamaz, fakat neyin değiştiğini karşılaştırmak ve kuralları elle yeniden kurmak için en güvenilir kayıttır.
Yapılandırmanın tamamını yedeklemek:
sudo tar czf ~/ufw-yedek-$(date +%F).tar.gz -C / etc/ufw etc/default/ufw
Geri yükleme güvenlik duvarını durdurmayı gerektirir. Uzak bir sunucuda bu işlem erişimi kesme riski taşır; öncesinde konsol erişiminizin olduğundan emin olun:
sudo ufw disable
sudo tar xzf ~/ufw-yedek-2026-09-06.tar.gz -C /
sudo ufw enable
sudo ufw status verbose
Dosyaları elle düzenlediyseniz etkinleştirmeden önce oluşacak kural setini
sudo ufw --dry-run enable ile gözden geçirin.
Sık karşılaşılan sorunlar
SSH erişimini kaybettim
Bağlantı koptuktan sonra sunucuya SSH ile ulaşamazsınız; geriye yalnızca sağlayıcınızın web konsolu, seri konsol veya fiziksel erişim kalır. Konsola düştükten sonra:
sudo ufw status numbered # hangi kuralın eksik olduğunu görün
sudo ss -tlnp | grep sshd # SSH'ın gerçek portunu doğrulayın
sudo ufw allow 22/tcp # çıkan portu açın
sudo ufw reload
Bu bölümün asıl değeri sonradan düzeltmekte değil, duruma hiç düşmemektedir.
Yazının başındaki sıra bu yüzden vardır: gerçek portu doğrulayın, kuralı enable
öncesinde ekleyin, ikinci bir oturum açık tutun, üçüncü bir oturumla doğrulayın.
Port erişilemiyor
Sorunun güvenlik duvarında mı uygulamada mı olduğunu ayırmak ilk adımdır. Uygulama
yalnızca 127.0.0.1 üzerinde dinliyorsa hiçbir UFW kuralı onu dışarıya açmaz:
# Hangi süreç hangi adres ve portu dinliyor
sudo ss -tlnp | grep :3000
# Güvenlik duvarı tarafındaki kural
sudo ufw status | grep 3000
ss çıktısındaki yerel adres 127.0.0.1:3000 ise sorun güvenlik duvarında
değildir; uygulamanın 0.0.0.0 veya ilgili arayüz üzerinde dinlemesi gerekir.
Süreci sonlandırmanız gerekiyorsa önce SIGTERM gönderin; SIGKILL ancak yanıt
alınamadığında kullanılır:
sudo kill -s TERM <PID>
Kural çakışmaları ve tekrarlar
UFW kuralları sırayla değerlendirir ve eşleşen ilk kuralı uygular. Bu nedenle
geniş bir allow kuralı, altında yer alan daha dar bir deny kuralını etkisiz
bırakabilir. Sıra numaralarını görüntüleyip gereksiz kuralları tek tek silmek,
kural setini sıfırlamaktan güvenlidir:
sudo ufw status numbered
sudo ufw delete 5
Kuralın belirli bir konuma eklenmesi gerekiyorsa:
sudo ufw insert 1 deny from 203.0.113.50
ufw reset yalnızca kural setini baştan kurmaya hazır olduğunuzda ve yedek
aldıktan sonra kullanılmalıdır; komut güvenlik duvarını devre dışı bırakır ve tüm
kuralları siler.
Sonuç
UFW, güvenlik duvarı politikasını sadeleştirir; ancak yanlış kural sırası veya eksik envanter erişimi yine kesebilir. Temel ilkeler:
- Keep it simple: Gereksiz port açmayın
- Default deny: Her şeyi kapatıp sadece gerekeni açın
- Rate limiting: Brute force saldırılarına karşı koruma
- Monitor logs: Düzenli log kontrolü yapın
- Backup rules: Configuration’ları yedekleyin
Kuralları uygulamadan önce mevcut servisleri ve kaynak ağları çıkarın, değişiklikten sonra etkin politika ile gerçek bağlantıyı ayrı ayrı doğrulayın.