Poniżej zostanie zaprezentowany sposób na blokowanie szeregu adresów IP przy pomocy filtru pakietów iptables. Zostanie tutaj także użyty ipset, który to będzie zawierał niepożądane przez nas klasy adresów. Tego typu mechanizm można wykorzystać do blokowania np. facebooka czy też innych serwisów społecznościowych o ile posiadamy informacje na temat adresów ip, na których te serwisy działają. Dodatkowo, jeśli mamy router z większą ilością pamięci RAM/flash i korzystamy przy tym z jakiegoś klienta torrent na routerze, np transmission, możemy załadować blacklisty adresów IP bezpośrednio do pamięci i przy pomocy iptables w prosty sposób zablokować niegrzecznych użytkowników sieci p2p.
Musimy się pierw zaopatrzyć w odpowiednie pakiety:
# opkg update
# opkg install ipset kmod-ipt-ipset
Po instalacji trzeba zresetować router, bo niektóre potrzebne moduły nie zostaną od tak załadowane.
# reboot
Listy w ipsecie tworzymy w następujący sposób:
# ipset create facebook hash:net family inet maxelem 5000
Opcja maxelem definiuje ile elementów może się znajdować w secie. Zależność jest prosta im ten parametr ma większą wartość, tym więcej pamięci operacyjnej dany set konsumuje, dlatego też trzeba go dobierać ostrożnie.
Załóżmy teraz, że użytkownicy naszej sieci zbyt często przesiadują na fejsie (lub dowolnych innych stronach) i chcemy im trochę popsuć zabawę. Na necie można znaleźć adresy IP używane przez facebooka. Mając adresy, możemy zacząć je dodawać do seta:
root@the-mountain:~# ipset add facebook 66.220.144.0-66.220.159.255
root@the-mountain:~# ipset add facebook 69.63.176.0-69.63.191.255
root@the-mountain:~# ipset add facebook 69.171.224.0-69.171.255.255
root@the-mountain:~# ipset add facebook 204.15.20.0-204.15.23.255
root@the-mountain:~# ipset add facebook 65.201.208.24/29
root@the-mountain:~# ipset add facebook 65.204.104.128/28
root@the-mountain:~# ipset add facebook 66.92.180.48/28
root@the-mountain:~# ipset add facebook 66.93.78.176/29
root@the-mountain:~# ipset add facebook 66.199.37.136/29
root@the-mountain:~# ipset add facebook 67.200.105.48/30
root@the-mountain:~# ipset add facebook 74.119.76.0/22
root@the-mountain:~# ipset add facebook 173.252.64.0/18
root@the-mountain:~# ipset add facebook 31.13.80.1-31.13.93.238
By zacząć blokować połączenia z powyższymi klasami adresów, dodajemy do naszego skryptu firewalla poniższe wpisy:
iptables -t raw -N ipset_in
iptables -t raw -A PREROUTING -j ipset_in
iptables -t raw -A ipset_in -m set --match-set facebook src -j DROP
Od tej pory cała komunikacja z fejsem będzie niemożliwa, nie ważne co dana osoba spróbuje zrobić by się połączyć, nie uda jej się to, no chyba, że skorzysta z VPN.
By ten mechanizm był trwały, trzeba zapisać wzór listy wraz z jej adresami. Robimy to przez wydanie poniższego polecenia:
root@the-mountain:~# ipset save facebook
create facebook hash:net family inet hashsize 1024 maxelem 5000
add facebook 31.13.80.4/30
add facebook 31.13.81.0/24
add facebook 31.13.80.16/28
add facebook 66.92.180.48/28
add facebook 31.13.80.8/29
add facebook 31.13.93.192/27
add facebook 31.13.80.64/26
add facebook 65.201.208.24/29
add facebook 31.13.80.32/27
add facebook 204.15.20.0/22
add facebook 31.13.84.0/22
add facebook 65.204.104.128/28
add facebook 66.199.37.136/29
add facebook 31.13.80.128/25
add facebook 31.13.80.1
add facebook 31.13.82.0/23
add facebook 66.93.78.176/29
add facebook 31.13.93.232/30
add facebook 74.119.76.0/22
add facebook 31.13.93.0/25
add facebook 31.13.93.236/31
add facebook 173.252.64.0/18
add facebook 67.200.105.48/30
add facebook 69.171.224.0/19
add facebook 31.13.80.2/31
add facebook 31.13.92.0/24
add facebook 31.13.93.238
add facebook 31.13.93.128/26
add facebook 66.220.144.0/20
add facebook 31.13.93.224/29
add facebook 31.13.88.0/22
add facebook 69.63.176.0/20
Możemy także przekierować wyjście do pliku, z którego to set zostanie automatycznie utworzony, a adresy dodane przy starcie routera:
root@the-mountain:~# mkdir /etc/ipset/
root@the-mountain:~# ipset save facebook > /etc/ipset/facebook
Dopisujemy do naszego skryptu firewalla w bloku start() na samym początku poniższą linijkę:
ipset restore -exist -f /etc/ipset/facebook
Trzeba także pamiętać o dodaniu odpowiednich regułek w przypadku zatrzymywania skryptu, z tym, że je trzeba dodać na końcu bloku, a to z tego względu, że listy ipseta nie mogą zostać usunięte gdy operuje na nich iptables.
ipset flush faceboook &> /dev/null
ipset destroy faceboook &> /dev/null
Cały skrypt firewalla powinien się prezentować następująco:
#!/bin/sh /etc/rc.common
START=17
start() {
ipset restore -exist -f /etc/ipset/facebook
iptables -t raw -F
iptables -t raw -X
iptables -t raw -N ipset_in
iptables -t raw -A PREROUTING -j ipset_in
iptables -t raw -A ipset_in -m set --match-set facebook src -j DROP
iptables -t filter -F
iptables -t filter -X
iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -P OUTPUT ACCEPT
iptables -t filter -N tcp
iptables -t filter -N udp
iptables -t filter -N icmp_in
iptables -t filter -N fw-interfaces
iptables -t filter -N fw-open
iptables -t filter -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -t filter -A INPUT -i lo -j ACCEPT
iptables -t filter -A INPUT -p icmp -m conntrack --ctstate NEW -j icmp_in
iptables -t filter -A INPUT -p udp -m conntrack --ctstate NEW -j udp
iptables -t filter -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j tcp
iptables -t filter -A INPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -t filter -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
iptables -t filter -A INPUT -j REJECT --reject-with icmp-proto-unreachable
iptables -t filter -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A FORWARD -m conntrack --ctstate INVALID -j DROP
iptables -t filter -A FORWARD -m conntrack --ctstate NEW -j fw-interfaces
iptables -t filter -A FORWARD -m conntrack --ctstate NEW -j fw-open
iptables -t filter -A FORWARD -j REJECT --reject-with icmp-host-unreachable
iptables -t filter -A icmp_in -p icmp -i br-lan -s 192.168.1.0/24 -j ACCEPT
iptables -t filter -A tcp -p tcp -i br-lan -s 192.168.1.0/24 -j ACCEPT
iptables -t filter -A udp -p udp -i br-lan -s 192.168.1.0/24 -j ACCEPT
iptables -t filter -A udp -p udp --sport 68 --dport 67 -s 0.0.0.0 -d 255.255.255.255 -j ACCEPT -m comment --comment "DHCP-broadcast"
iptables -t filter -A udp -p udp --dport 68 -j ACCEPT -m comment --comment "Allow-DHCP-Renew"
iptables -t filter -A fw-interfaces -i br-lan -s 192.168.1.0/24 -j ACCEPT
# iptables -t filter -A fw-open -i eth0 -o br-lan -d 192.168.1.150 -p tcp --dport 22222 -j ACCEPT
# iptables -t filter -A fw-open -i eth0 -o br-lan -d 192.168.1.150 -p udp --dport 22222 -j ACCEPT
# iptables -t filter -A icmp_in -p icmp -i eth0 -j ACCEPT
# iptables -t filter -A tcp -p tcp -i eth0 -m tcp --dport 22 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j SNAT --to-source 22.33.44.55
# iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j MASQUERADE
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22222 -j DNAT --to-destination 192.168.1.150
# iptables -t nat -A PREROUTING -i eth0 -p udp --dport 22222 -j DNAT --to-destination 192.168.1.150
}
stop() {
for TABLE in \
"-t raw" \
"-t mangle" \
"-t filter" \
"-t nat"
do
iptables $TABLE -F
iptables $TABLE -X
done
iptables -t filter -N tcp
iptables -t filter -N udp
iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -A INPUT -i br-lan -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT -i lo -j ACCEPT
iptables -t filter -A INPUT -i br-lan -p icmp -m conntrack --ctstate NEW -j ACCEPT
iptables -t filter -A INPUT -i br-lan -p udp -m conntrack --ctstate NEW -j ACCEPT
iptables -t filter -A INPUT -i br-lan -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j ACCEPT
iptables -t filter -A INPUT -p tcp -j REJECT --reject-with tcp-reset
iptables -t filter -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
iptables -t filter -A INPUT -j REJECT --reject-with icmp-proto-unreachable
ipset flush facebook &> /dev/null
ipset destroy facebook &> /dev/null
}
Samo tworzenie skryptu iptables zostało opisane w tym wątku.
Oczywiście ipset może także posłużyć jako filtr adresów w drugą stronę, tj. jeśli chcemy zezwolić naszej sieci na połączenia do określonych hostów, wtedy do listy ipseta dodajemy pożądane adresy i zmieniamy -j DROP na -j ACCEPT .