IP setleri tekrar ziyaret edildi
IP setlerinden bahseden bir cevap zaten var. Bununla birlikte, klasik kurallar üzerinden elde edilen performansa odaklanması ve IP setlerinin CIDR notasyonunda kolayca bir alt ağ olarak ifade edilemeyecek birçok bireysel IP adresi olan sorunu hafifletmesi gerçeği bir boyutludur.
Aşağıda kullanılan gösterim
Çünkü ipset
yazım tarafından okunan ipset restore
ve yazılan gösterimi kullanacağım ipset save
.
Buna göre iptables
(ve ip6tables
) kurallar için gösterimi, okuduğu iptables-restore
ve yazdığı şekilde kullanacağım iptables-save
. Bu, daha kısa bir gösterim sağlar ve potansiyel IPv4-sadece (önek -4
) veya IPv6-sadece (önek -6
) kurallarını vurgulamama izin verir .
Bazı örneklerde paket akışını başka bir zincire yönlendireceğiz. Bu noktada zincirin olduğu varsayılır, bu nedenle zincirleri oluşturan satırlar üretilmez (sonunda tablo adı veya belirtilen komutlar da belirtilmez COMMIT
).
Gelişmiş IP setleri
IP setleri diğer cevaplarda belirtilenden çok daha fazlasını yapabilir ve buradaki kısa girişin yanı sıra IP set belgelerini ( ipset(8)
) kesinlikle okumanız gerekir iptables-extensions(8)
.
Mesela ben esas olarak üç set üzerinde duralım: hash:ip
, hash:net
ve list:set
fakat daha fazlası var ve hepsi geçerli kullanım durumları var.
Örneğin , yalnızca IP adreslerini değil, port numaralarını da eşleştirebilirsiniz .
Kaydetme ve ile IP kümelerini geri iptables-save
veiptables-restore
IP seti bildirimlerini toplu olarak oluşturabilir ve içine aktararak içe aktarabilirsiniz ipset restore
. Komutunuzu mevcut girişlere karşı daha esnek hale getirmek istiyorsanız, kullanın ipset -exist restore
.
Kurallarınız denilen bir dosyadaysa, default.set
şunları kullanırsınız:
ipset -exist restore < default.set
Bunun gibi bir dosya, create
kümelere ve add
içine girdiler için girdiler içerebilir . Ancak genellikle komut satırındaki komutların çoğunun dosyalarda karşılık gelen bir sürümü var gibi görünmektedir. Örnek (bir dizi DNS sunucusu oluşturma):
create dns4 hash:ip family inet
create dns6 hash:ip family inet6
# Google DNS servers
add dns4 8.8.8.8
add dns4 8.8.4.4
add dns6 2001:4860:4860::8888
add dns6 2001:4860:4860::8844
Burada IPv4 ( dns4
) için bir tane ve IPv6 ( dns6
) için bir set oluşturulur .
IP setlerinde zaman aşımları
IP setlerindeki zaman aşımları, set başına ve ayrıca giriş başına varsayılan olarak ayarlanabilir. Bu, birini geçici olarak engellemek istediğiniz senaryolar için çok yararlıdır (örneğin port taraması veya SSH sunucunuzu kaba şekilde zorlama girişiminde bulunmak için).
Bunun çalışması şu şekildedir (IP kümelerinin oluşturulması sırasında varsayılan):
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
Aşağıda bu belirli kümelere ve neden oldukları gibi belirlenmelerinin gerekçesine geri döneceğiz.
Zaman aşımınızı belirli bir IP adresi için ayarlamak isterseniz, şunu söyleyebilirsiniz:
add ssh_dynblock4 1.2.3.4 timeout 7200
IP 1.2.3.4'ü (ayarlanan) varsayılan yarım saat yerine iki saat süreyle engellemek için.
ipset save ssh_dynblock4
Kısa bir süre sonra buna bakarsanız, aşağıdaki satırlarda bir şeyler görürsünüz:
create ssh_dynblock4 hash:ip family inet hashsize 1024 maxelem 65536 timeout 1800
add ssh_dynblock4 1.2.3.4 timeout 6954
Zaman aşımı uyarıları
- zaman aşımları verilen herhangi bir sette bulunan bir özelliktir. Set zaman aşımı desteği ile oluşturulmadıysa bir hata alırsınız (örn.
Kernel error received: Unknown error -1
).
- zaman aşımları saniye cinsinden verilir. Örneğin, dakikadan saniyeye ulaşmak için Bash aritmetik ifadelerini kullanın. Örneğin:
sudo ipset add ssh_dynblock4 1.2.3.4 timeout $((120*60))
Bir girişin belirli bir IP setinde olup olmadığını kontrol etme
Komut dosyalarınızın içinde bir girişin var olup olmadığını görmek yararlı olabilir. Bu ipset test
, giriş varsa sıfırı döndürür, aksi takdirde sıfır saymazsa başarılabilir . Böylece normal kontroller bir betiğe uygulanabilir:
if ipset test dns4 8.8.8.8; then
echo "Google DNS is in the set"
fi
Bununla birlikte, çoğu durumda -exist
anahtarı, ipset
mevcut girişler hakkında şikayet etmemek için yönlendirmek amacıyla kullanmak isteyeceksiniz .
IP kümelerini iptables
kurallardan doldurma
Bu, benim görüşüme göre, IP setlerinin katil özelliklerinden biridir. Bir IP setinin girişleriyle eşleşmekle kalmaz, mevcut bir IP setine de yeni girişler ekleyebilirsiniz.
Örneğin, bu sorunun cevabında sizde:
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
... hız sınırı bağlantısı amacıyla SSH'ye çalışmayı deniyor (TCP port 22). Kullanılan modül recent
son bağlantı girişimlerini takip eder. Bununla birlikte , state
modül yerine, modülü tercih ederim conntrack
.
# Say on your input chain of the filter table you have
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
# Then inside the SSH chain you can
# 1. create an entry in the recent list on new connections
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
# 2. check whether 3 connection attempts were made within 2 minutes
# and if so add or update an entry in the ssh_dynblock4 IP set
-4 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock4 src --exist
-6 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock6 src --exist
# 3. last but not least reject the packets if the source IP is in our
# IP set
-4 -A SSH -m set --match-set ssh_dynblock4 src -j REJECT
-6 -A SSH -m set --match-set ssh_dynblock6 src -j REJECT
Bu durumda , her bir kural için SSH
kendimi tekrar etmek zorunda kalmayacağım şekilde akışı zincire yönlendiriyorum -p tcp --dport ssh
.
Tekrarlamak için:
-m set
yapar iptables
biz gelen anahtarları kullanıyoruz farkında set
(hangi IP setlerini kolları) modülü
--match-set ssh_dynblock4 src
source ( ) adresi ile belirtilen set ( )
iptables
ile eşleşmesini söylersrc
ssh_dynblock4
- bu, karşılık gelir
sudo ipset test ssh_dynblock4 $IP
( $IP
paket için kaynak IP adresini içeren)
-j SET --add-set ssh_dynblock4 src --exist
paketteki source ( src
) adresini IP setine ekler veya günceller ssh_dynblock4
. Bir giriş varsa ( --exist
) sadece güncellenir.
- bu, karşılık gelir
sudo ipset -exist add ssh_dynblock4 $IP
( $IP
paket için kaynak IP adresini içeren)
Bunun yerine hedef / hedef adresiyle eşleştirmek istiyorsanız, dst
yerine kullanırsınız src
. Daha fazla seçenek için kılavuza bakın.
Kümeleri
IP kümeleri başka kümeler içerebilir. Şimdi makaleyi buraya kadar izlerseniz, kümeleri birleştirmenin mümkün olup olmadığını merak etmişsinizdir. Ve elbette öyle. Yukarıdaki IP kümeleri için iki ortak küme oluşturabiliriz ssh_dynblock
ve ssh_loggedon
sırasıyla sadece IPv4 ve sadece IPv6 kümelerini içeririz:
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
# Sets of sets
create ssh_loggedon list:set
create ssh_dynblock list:set
# Populate the sets of sets
add ssh_loggedon ssh_loggedon4
add ssh_loggedon ssh_loggedon6
add ssh_dynblock ssh_dynblock4
add ssh_dynblock ssh_dynblock6
Ve aklınızda bulunması gereken bir sonraki soru, IP setlerini agnostik bir şekilde IP setleriyle eşleştirip manipüle etmemize izin verip vermeyeceğidir .
Ve bunun cevabı bir yankılandı: EVET! (ne yazık ki, bu son kontrol ettiğimde açıkça belgelenmedi)
Sonuç olarak, önceki bölümdeki kurallar okumak için yeniden yazılabilir:
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
Bu çok daha özlü. Ve evet, bu denenmiş ve test edilmiş ve bir cazibe gibi çalışıyor.
Hepsini bir araya getirmek: SSH kaba kuvvet savunması
Sunucularımda cron
, bir sürü ana bilgisayar adı alan ve bunları IP adreslerine çözen, ardından "güvenilir ana bilgisayarlar" için ayarlanan IP'ye besleyen bir iş olarak çalışan bir komut dosyası var . Buradaki fikir, güvenilir ana makinelerin sunucuya giriş yapmak için daha fazla girişimde bulunmaları ve mutlaka başka hiç kimse tarafından engellenmemeleri gerektiğidir.
Bunun tersine, tüm ülkelerin SSH sunucuma bağlanmalarını engelledim, güvenilir ana bilgisayarların (potansiyel kurallar dışında) (potansiyel) istisnasıyla.
Ancak, bu okuyucu için bir egzersiz olarak bırakılmıştır. Burada ssh_loggedon
, sonraki bağlantı girişimlerinin gerçekleştirilebilmesini ve diğer paketlerle aynı incelemeye tabi tutulmamasını sağlamak için sette bulunan setleri kullanacak temiz bir çözüm eklemek istiyorum .
Aşağıdaki kurallara bakarken, 90 dakikalık ssh_loggedon
ve 30 dakikalık varsayılan zaman aşımlarını hatırlamak önemlidir :ssh_dynblock
iptables
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m set --match-set ssh_loggedon src -j ACCEPT
-A SSH -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
Şimdiye kadar kendinize, bağlı IP adresinin ssh_loggedon
alt kümelerde nasıl sona erdiğini sormalısınız . Öyleyse okumaya devam et ...
Bonus: SSH oturumu sırasında giriş yaptığınız IP'yi eklemek
sshrc
Arkadaşlarınızla ve deneyimleriniz varsa , onun eksikliklerini öğrendiniz. Ancak PAM kurtarmaya gelir. Adlı modül pam_exec.so
, kullanıcının kabul edildiğini bildiğimiz bir noktada SSH oturumu sırasında bir komut dosyası çağırmamızı sağlar.
In /etc/pam.d/sshd
aşağıda pam_env
ve pam_selinux
girişleri aşağıdaki satırı ekleyin:
session optional pam_exec.so stdout /path/to/your/script
ve betiğin ( /path/to/your/script
yukarıdaki) sürümünün var olduğundan ve çalıştırılabilir olduğundan emin olun .
PAM, olup bitenleri iletmek için ortam değişkenlerini kullanır, böylece bunun gibi basit bir komut dosyası kullanabilirsiniz:
#!/bin/bash
# When called via pam_exec.so ...
SETNAME=ssh_loggedon
if [[ "$PAM_TYPE" == "open_session" ]] && [[ -n "$PAM_RHOST" ]]; then
[[ "x$PAM_RHOST" != "x${PAM_RHOST//:/}" ]] && SETNAME="${SETNAME}6" || SETNAME="${SETNAME}4"
ipset -exist add $SETNAME "$PAM_RHOST"
fi
Maalesef, ipset
yardımcı programın yerleşik netfilter akıllıları görünmüyor. Bu yüzden, girişimizi eklerken IPv4 ve IPv6 IP setlerini ayırt etmemiz gerekir. Aksi takdirde , IP yerine kümelere ipset
başka bir küme eklemek istediğimizi varsayacağız . Ve elbette, IP adresinden sonra bir set olması pek mümkün değildir :)
Bu yüzden :
IP adresini kontrol ederiz ve 6
bu durumda set adını 4
ekleriz.
Son.