Това е четвъртата част от серия от статии в които ще обясня как да създадем перфектният SOHO рутер. Държа да отбележа че това е моята идея за рутер със всичките и предимства и недостатъци.
Серията се състои от следните статии:
След като вече сме инсталирали нашият рутер и сме пуснали някои услуги е време да конфигурираме самият процес на рутиране. Това се постига чрез стандартни инструменти като route, iptables, arp, iproute2.
В тази част ще покажем следните варианти:
- Прост елементарен рутер – това е най елементарният но за сметка на това не предлага кой знае какви възможности
- Рутер който изпълнява NAT/masquerade и firewall функции – това е може би най-разпространеният вариант.
- Рутер който изпълнява баланс на трафика от два или повече доставчика – това вече е по-напреднала тема но въпреки всичко има полза от нея.
Примерите и конфигурациите ще са доста опростени като ще покажем само скелета на системата, тъй като всеки има различни изисквания. В края на статията ще дам малко връзки с допълнителна информация за четене и помощ.
Прост рутер
При тази ситуация нашият рутер просто развърта тряфика. В общият случай не се прави маскиране или филтрация на трафикатъй като като цяло е решено че не е необходимо. Това решение обикновенно се ползва при големи мрежи просто за да се сегментира мрежата. Постига се особенно елеменарно тъй като изисква включване на една единствена опци в кернела и разрешаването и за изпълнение. Опцията е IP FORWARDING. Може да бъде разрешена по два различни начина:
- Посредством proc системата (тя е налична при всички случаи):
echo "1" > /proc/sys/net/ipv4/ip_forward
- Посредством sysctl системата (може да не е налична):
sysctl -w net.ipv4.ip_forward=1
Тази настройка разрешава препращане на пакети между интерфейсите на рутерът ни и така реално го стартираме. Необходимо е тази настройка да бъде сложена на такова място че при стартирането на нашата машина тя да бъде изпълнена автоматично. Добро място за тази настройка е /etc/rc.local или отделен файл който се изпълнява съвсем в края на процеса на стартиране.
Както забелязвате това е един много опростен рутер който не предлага почти никакви ползи. За да работи правилно всяка от клиентските машини трябва да има собствен адрес, който е разпознаваем в обхвата на мрежата. Този рутер не изпълнява филтрация и не предпазва по никакъв начин машините зад него. Като цяло това решение е удачно за големи мрежи които искат да сегментират адресното си пространство и които имат сериозен рутер и firewall на входа им.
Рутер който изпълнява NAT/masquerade и firewall функции
Това е може би най-често използваното решение. Предимствата му са че зад един адрес могат да се скрият (маскират) доста олям брой машини (теоретично почти неограничен стига да имаме процесорна мощ).
Конфигурацията за този пример ще изградим при следните предпоставки:
- Външен интерфейс: eth0 със съответно назначения му адрес и маска
- Вътрешен интерфейс: eth1 със съответно назначения му адрес и маска
- Проста защита от DoS, DDoS атаки и сканиране
- Лимит на специфични ICMP заявки
- Достъп до http и ssh от външната страна на рутера ни
- Достъп до http, ssh, dns, dhcp от вътрешната страна
- SNAT за всички клиенти на рутера ни (дори при динамичен адрес)
- Препращане на 10 порта за всеки клиент – за удобство на потребителите ни
- Изрична филтрация на част от боклука във външната/вътрешната ни мрежа
Темата за ограничения по TTL изрично ще я пропусна. Реализира се просто и има достатъчно документация по въпроса.
#!/bin/bash
# Simple firewalling router
# author: vvitkov
# contact: http://www.getoto.net/az/
#
# Licence: CC NC-BY-SA v3
# Disclaimer: i take no responsibility for the consequences of using or not using this.
# It is up to you to decide what to do with this stuff.
# Please if you use this write me a note and don't remove the author info.
#######
# Settings, vars
#######
echo "Setting Up Variables ..."
IPT="/sbin/iptables"
if [ -x /sbin/sysctl ] ; then
SYSCTL="/sbin/sysctl -w"
fi
# define external interface, ip, mask, broadcast
EXT_IF="eth0"
EXT_IP="$(/sbin/ifconfig $EXT_IF | grep "addr:" | cut -d":" -f2 | cut -f1 -d" ")"
EXT_NM="$(/sbin/ifconfig $EXT_IF | grep "addr:" | cut -d":" -f4 | cut -f1 -d" ")"
EXT_BC="$(/sbin/ifconfig $EXT_IF | grep "addr:" | cut -d":" -f3 | cut -f1 -d" ")"
# define internal interface, ip, mask, broadcast
INT_IF="eth1"
INT_IP="$(/sbin/ifconfig $INT_IF | grep "addr:" | cut -d":" -f2 | cut -f1 -d" ")"
INT_NM="$(/sbin/ifconfig $INT_IF | grep "addr:" | cut -d":" -f4 | cut -f1 -d" ")"
INT_BC="$(/sbin/ifconfig $INT_IF | grep "addr:" | cut -d":" -f3 | cut -f1 -d" ")"
INT_NET="$INT_IP"/"$INT_NM"
# define the loopback
LO_IF="lo"
LO_IP="127.0.0.1"
# define allowed ports
EXT_IN_TCP="22 80"
EXT_IN_UDP="33434:33524"
INT_IN_TCP="22 53 67 68 80"
INT_IN_UDP="53 67 68 33434:33524"
#######
# Lets go
#######
echo "Tunning ..."
if [ -z $SYSCTL ] ; then
# stop forwarding
$SYSCTL net.ipv4.ip_forward=0
# fix our routing a bit
$SYSCTL net.ipv4.conf.default.accept_redirects=0
$SYSCTL net.ipv4.conf.default.accept_source_route=0
$SYSCTL net.ipv4.conf.default.send_redirects=0
$SYSCTL net.ipv4.conf.default.rp_filter=1
# don't log strange packets
$SYSCTL net.ipv4.conf.default.log_martians=0
# smurf rpotection
$SYSCTL net.ipv4.icmp_echo_ignore_broadcasts=1
$SYSCTL net.ipv4.icmp_ignore_bogus_error_responses=1
$SYSCTL net.ipv4.conf.default.proxy_arp=0
# keep quiet about arp requests/answers
$SYSCTL net.ipv4.conf.default.arp_filter=1
$SYSCTL net.ipv4.conf.default.arp_announce=2
$SYSCTL net.ipv4.conf.default.arp_ignore=2
# set the ttl to a windows like box (additional layer of security)
$SYSCTL net.ipv4.ip_default_ttl=128
# recycle fast unused buckets for packet infos
$SYSCTL net.ipv4.tcp_tw_recycle=1
$SYSCTL net.ipv4.tcp_tw_reuse=1
# do not stamp the packets
$SYSCTL net.ipv4.tcp_timestamps=0
else
echo "0" > /proc/sys/net/ipv4/ip_forward
echo "0" > /proc/sys/net/ipv4/conf/default/accept_redirects
echo "0" > /proc/sys/net/ipv4/conf/default/accept_source_route
echo "0" > /proc/sys/net/ipv4/conf/default/accept_send_redirects
echo "1" > /proc/sys/net/ipv4/conf/default/rp_filter
echo "0" > /proc/sys/net/ipv4/conf/default/log_martians
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo "0" > /proc/sys/net/ipv4/conf/default/proxy_arp
echo "1" > /proc/sys/net/ipv4/conf/default/arp_filter
echo "2" > /proc/sys/net/ipv4/conf/default/arp_announce
echo "2" > /proc/sys/net/ipv4/conf/default/arp_ignore
echo "128" > /proc/sys/net/ipv4/ip_default_ttl
echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
fi
# Clear all tables
echo "Start on clean ..."
$IPT -F
$IPT -t nat -F
$IPT -t mangle -F
$IPT -X
$IPT -t nat -X
$IPT -t mangle -X
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
echo "Setting custom chains ..."
$IPT -N bad_packets
$IPT -N bad_tcp_packets
$IPT -N icmp_packets
$IPT -N tcp_in
$IPT -N udp_in
$IPT -N tcp_out
$IPT -N udp_out
echo "Setting some protections ..."
echo " General"
$IPT -A bad_packets -p ALL -i $EXT_IF -s $INT_NET -j DROP
$IPT -A bad_packets -p ALL -m state --state INVALID -j DROP
$IPT -A bad_packets -p tcp -j bad_tcp_packets
$IPT -A bad_packets -p ALL -j RETURN
echo " TCP"
$IPT -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPT -A tcp_in -p TCP -s 0/0 --destination-port 113 -j REJECT
$IPT -A bad_tcp_packets -p tcp -j RETURN
echo " ICMP"
$IPT -A icmp_packets --fragment -p ICMP -j DROP
$IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -m limit --limit 1/s -j ACCEPT
$IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT
$IPT -A icmp_packets -p ICMP -j RETURN
echo " UDP"
$IPT -A udp_in -p UDP -s 0/0 --dport 137 -j DROP
$IPT -A udp_in -p UDP -s 0/0 --dport 139 -j DROP
$IPT -A udp_in -p UDP -s 0/0 --dport 113 -j REJECT
echo "Filling the chains ..."
echo " UDP INCOMING"
for PORT in $EXT_IN_UDP ; do
$IPT -A udp_in -p UDP -i EXT_IF -s 0/0 --dport $PORT -j ACCEPT;
done
for PORT in $INT_IN_UDP ; do
$IPT -A udp_in -p UDP -i INT_IF -s 0/0 --dport $PORT -j ACCEPT;
done
$IPT -A udp_in -j RETURN
echo " UDP OUTGOING"
$IPT -A udp_out -p UDP -s 0/0 -j ACCEPT
echo " TCP INCOMING"
for PORT in $EXT_IN_TCP ; do
$IPT -A tcp_in -p TCP -i $EXT_IF -s 0/0 --dport $PORT -j ACCEPT
done
for PORT in $INT_IN_TCP ; do
$IPT -A tcp_in -p TCP -i $INT_IF-s 0/0 --dport $PORT -j ACCEPT
done
$IPT -A tcp_in -p TCP -j RETURN
echo " TCP OUTGOING"
$IPT -A tcp_out -p TCP -j ACCEPT
echo " INCOMING"
$IPT -A INPUT -p ALL -i $LO_IF -j ACCEPT
$IPT -A INPUT -p ALL -j bad_packets
$IPT -A INPUT -p ALL -d 224.0.0.1 -j DROP
$IPT -A INPUT -p ALL -i $INT_IF -s $INT_NET -j ACCEPT
$IPT -A INPUT -p ALL -i $INT_IF -d $INT_BC -j ACCEPT
$IPT -A INPUT -p UDP -i $INT_IF --sport 68 --dport 67 -j ACCEPT
$IPT -A INPUT -p ALL -i $EXT_IF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p ALL -i ! $EXT_IF -m state --state NEW -j ACCEPT
$IPT -A INPUT -p TCP -i $EXT_IF -j tcp_in
$IPT -A INPUT -p UDP -i $EXT_IF -j udp_in
$IPT -A INPUT -p ICMP -i $EXT_IF -j icmp_packets
$IPT -A INPUT -m pkttype --pkt-type broadcast -j DROP
echo " FORWARD"
$IPT -A FORWARD -p ALL -j bad_packets
$IPT -A FORWARD -p tcp -i $INT_IF -j tcp_out
$IPT -A FORWARD -p udp -i $INT_IF -j udp_out
$IPT -A FORWARD -p ALL -i $INT_IF -j ACCEPT
$IPT -A FORWARD -i $EXT_IF -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -p ALL -i $EXT_IF -m state --state NEW -j ACCEPT
echo " OUTPUT"
$IPT -A OUTPUT -m state -p icmp --state INVALID -j DROP
$IPT -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IPT -A OUTPUT -p ALL -o $LO_IF -j ACCEPT
$IPT -A OUTPUT -p ALL -s $INT_IP -j ACCEPT
$IPT -A OUTPUT -p ALL -o $INT_IF -j ACCEPT
$IPT -A OUTPUT -p ALL -o $EXT_IF -j ACCEPT
echo " NAT"
echo " PORT FORWARDING"
TMP="`echo $INT_IP | cut -d\. -f1-3`"
for HOST in `seq 2 254` ; do
PORTR=$((10000+HOST*10)):$((10009+HOST*10))
echo " $PORTR for $TMP.$HOST"
$IPT -A FORWARD -p udp -i $EXT_IF --dport $PORTR -d $TMP.$HOST -j ACCEPT
$IPT -A FORWARD -p tcp -i $EXT_IF --dport $PORTR -d $TMP.$HOST -j ACCEPT
$IPT -t nat -A PREROUTING -p udp -i $EXT_IF --dport $PORTR -j DNAT --to $TMP.$HOST
$IPT -t nat -A PREROUTING -p tcp -i $EXT_IF --dport $PORTR -j DNAT --to $TMP.$HOST
done
$IPT -t nat -A POSTROUTING -o $EXT_IF -j SNAT --to $EXT_IP
if [ -z $SYSCTL ] ; then
$SYSCTL net.ipv4.ip_forward=1
else
echo "1" > /proc/sys/net/ipv4/ip_forward
fi
Като цяло това е един относително добър базов firewall. В него има няколко интересни момента а именно:
- Начинът по който вземаме адресите на мрежовите карти – както сте забелязали единствените променливи които не се извличат това са имената на интерфейсите. По този начин самият firewall става по гъвкав и приложим за почти всякакъв вид връзки.
- Начина по който реализираме маскирането. Правим го със SNAT тъй като той е по лек отколкото MASQUERADE. За хората които ще кажат че при динамични връзки (pppoe, ip идващо от dhcp) това не е подходящо, да по принцип сте прави. Обаче ако използваме възможностите на DHCP клиента/pppoe клиента това може да бъде избегнато. В момента в който нашият адрес бъде подменен можем принудително да изпълним отново нашият firewall и той отново да си вземе правилния адрес и да се оправи както си му е редът.
- Начинът по който препращаме портове на машините зад нас – използвана е конструкция която е валидна само в bash с която да се генерират две числа които използваме за начало и край на обхвата от портове. След това експлицитно ги отваряме във веригата FORWARD макар че това не е строго необходимо и в последствие ги препращаме чрез DNAT.
- Обхватът от портове 33434:33524 – тези портове трябва да са отворени за да работи traceroute
Рутер който изпълнява баланс на трафика от два или повече доставчика
Тук ще дадем само частта която реално изпълнява балансирането на трафика. Вземаме пример само с два доставчика, но разширяването на примера не е проблем. Задачата е малко по обемиста тъй като за удобство ще използваме iproute. Самият пакет има доста криптичен синтаксис но след като му свикнете едва ли ще ви се разделя с него.
За да можем да балансираме трафик ни трябват следните инструменти:
- iproute2
- поддръжка в кернела за multipath routing
- Компилиран в кернела поне една дисциплина за multipath routing – аз лично препоръчвам wrr
За да можем да използваме имена в конфигурацията е необходимо да ги добавим във файла /etc/iproute2/rt_tables. Индексите им са между 2 и 252. Ако ще балансирате повече от 200 доставчика … не четете на правилното място.
#!/bin/bash
#
# Simple balancing router
# author: vvitkov
# contact: http://www.getoto.net/az/
#
# Licence: CC NC-BY-SA v3
# Disclaimer: i take no responsibility for the consequences of using or not using this.
# It is up to you to decide what to do with this stuff.
# Please if you use this write me a note and don't remove the author info.
### Settings
ISP1_NET="1.2.3.0/24"
ISP1_GW="1.2.3.1"
ISP1_IF="eth1"
ISP1_OUR_HOST="1.2.3.99"
ISP2_NET="9.8.7.0/24"
ISP2_GW="9.8.7.1"
ISP2_IF="eth2"
ISP2_OUR_HOST="9.8.7.99"
INT_NET="10.42.3.0/24"
# Defining routing tables for source routing
if ( ip ru ls | grep main | grep 50 )
then
ip r f t main
else
ip ru a prio 50 t main
fi
if ( ip ru ls | grep isp_rules1 )
then
ip r f t isp_rules1
else
ip ru a from $ISP1_NET prio 201 t isp_rules1
fi
if ( ip ru ls | grep isp_rules2 )
then
ip r f t isp_rules2
else
ip ru a from $ISP2_NET prio 202 t isp_rules2
fi
# Clear all the existing routes
ip r f any
ip r f t default
# Host routes
ip r a $ISP1_NET dev $ISP1_IF src $ISP1_OUR_HOST
ip r a $ISP2_NET dev $ISP2_IF src $ISP2_OUR_HOST
# Local networks
ip r a 127.0.0.0/8 dev lo
ip r a $INT_NET dev eth0
# Default gateways
ip r a 0/0 via $ISP1_GW dev $ISP1_IF table isp_rules1 proto static
ip r a prohibit 0/0 table isp_rules1 metric 1 proto static
ip r a 0/0 via $ISP2_GW dev $ISP2_IF table isp_rules2 proto static
ip r a prohibit 0/0 table isp_rules2 metric 1 proto static
# lets shake it :)
ip r a 0/0 proto static table default nexthop via $ISP1_GW dev $ISP2_IF nexthop via $ISP2_GW dev $ISP2_IF
# Remote networks with static routes
ip r a < NETWORK IN ISP1 > via $ISP1_GW dev $ISP1_IF
ip r a < NETWORK IN ISP2 > via $ISP2_GW dev $ISP2_IF
# flush caches
ip r f c
С това завършват примерите за конфигуриране на рутер. Знам че не са покрити всички възможности, но човек трябва да се потруди малко.
Серията продължава в The Perfect SOHO router – Part 5
The Perfect SOHO router – Part 4
След като вече сме инсталирали нашият рутер и сме пуснали някои услуги е време да конфигурираме самият процес на рутиране. Това се постига чрез стандартни инструменти като route, iptables, arp, iproute2.
В тази част ще покажем следните варианти:
Примерите и конфигурациите ще са доста опростени като ще покажем само скелета на системата, тъй като всеки има различни изисквания. В края на статията ще дам малко връзки с допълнителна информация за четене и помощ.
Прост рутер
При тази ситуация нашият рутер просто развърта тряфика. В общият случай не се прави маскиране или филтрация на трафикатъй като като цяло е решено че не е необходимо. Това решение обикновенно се ползва при големи мрежи просто за да се сегментира мрежата. Постига се особенно елеменарно тъй като изисква включване на една единствена опци в кернела и разрешаването и за изпълнение. Опцията е IP FORWARDING. Може да бъде разрешена по два различни начина:
Тази настройка разрешава препращане на пакети между интерфейсите на рутерът ни и така реално го стартираме. Необходимо е тази настройка да бъде сложена на такова място че при стартирането на нашата машина тя да бъде изпълнена автоматично. Добро място за тази настройка е /etc/rc.local или отделен файл който се изпълнява съвсем в края на процеса на стартиране.
Както забелязвате това е един много опростен рутер който не предлага почти никакви ползи. За да работи правилно всяка от клиентските машини трябва да има собствен адрес, който е разпознаваем в обхвата на мрежата. Този рутер не изпълнява филтрация и не предпазва по никакъв начин машините зад него. Като цяло това решение е удачно за големи мрежи които искат да сегментират адресното си пространство и които имат сериозен рутер и firewall на входа им.
Рутер който изпълнява NAT/masquerade и firewall функции
Това е може би най-често използваното решение. Предимствата му са че зад един адрес могат да се скрият (маскират) доста олям брой машини (теоретично почти неограничен стига да имаме процесорна мощ).
Конфигурацията за този пример ще изградим при следните предпоставки:
Темата за ограничения по TTL изрично ще я пропусна. Реализира се просто и има достатъчно документация по въпроса.
#!/bin/bash # Simple firewalling router # author: vvitkov # contact: http://www.getoto.net/az/ # # Licence: CC NC-BY-SA v3 # Disclaimer: i take no responsibility for the consequences of using or not using this. # It is up to you to decide what to do with this stuff. # Please if you use this write me a note and don't remove the author info. ####### # Settings, vars ####### echo "Setting Up Variables ..." IPT="/sbin/iptables" if [ -x /sbin/sysctl ] ; then SYSCTL="/sbin/sysctl -w" fi # define external interface, ip, mask, broadcast EXT_IF="eth0" EXT_IP="$(/sbin/ifconfig $EXT_IF | grep "addr:" | cut -d":" -f2 | cut -f1 -d" ")" EXT_NM="$(/sbin/ifconfig $EXT_IF | grep "addr:" | cut -d":" -f4 | cut -f1 -d" ")" EXT_BC="$(/sbin/ifconfig $EXT_IF | grep "addr:" | cut -d":" -f3 | cut -f1 -d" ")" # define internal interface, ip, mask, broadcast INT_IF="eth1" INT_IP="$(/sbin/ifconfig $INT_IF | grep "addr:" | cut -d":" -f2 | cut -f1 -d" ")" INT_NM="$(/sbin/ifconfig $INT_IF | grep "addr:" | cut -d":" -f4 | cut -f1 -d" ")" INT_BC="$(/sbin/ifconfig $INT_IF | grep "addr:" | cut -d":" -f3 | cut -f1 -d" ")" INT_NET="$INT_IP"/"$INT_NM" # define the loopback LO_IF="lo" LO_IP="127.0.0.1" # define allowed ports EXT_IN_TCP="22 80" EXT_IN_UDP="33434:33524" INT_IN_TCP="22 53 67 68 80" INT_IN_UDP="53 67 68 33434:33524" ####### # Lets go ####### echo "Tunning ..." if [ -z $SYSCTL ] ; then # stop forwarding $SYSCTL net.ipv4.ip_forward=0 # fix our routing a bit $SYSCTL net.ipv4.conf.default.accept_redirects=0 $SYSCTL net.ipv4.conf.default.accept_source_route=0 $SYSCTL net.ipv4.conf.default.send_redirects=0 $SYSCTL net.ipv4.conf.default.rp_filter=1 # don't log strange packets $SYSCTL net.ipv4.conf.default.log_martians=0 # smurf rpotection $SYSCTL net.ipv4.icmp_echo_ignore_broadcasts=1 $SYSCTL net.ipv4.icmp_ignore_bogus_error_responses=1 $SYSCTL net.ipv4.conf.default.proxy_arp=0 # keep quiet about arp requests/answers $SYSCTL net.ipv4.conf.default.arp_filter=1 $SYSCTL net.ipv4.conf.default.arp_announce=2 $SYSCTL net.ipv4.conf.default.arp_ignore=2 # set the ttl to a windows like box (additional layer of security) $SYSCTL net.ipv4.ip_default_ttl=128 # recycle fast unused buckets for packet infos $SYSCTL net.ipv4.tcp_tw_recycle=1 $SYSCTL net.ipv4.tcp_tw_reuse=1 # do not stamp the packets $SYSCTL net.ipv4.tcp_timestamps=0 else echo "0" > /proc/sys/net/ipv4/ip_forward echo "0" > /proc/sys/net/ipv4/conf/default/accept_redirects echo "0" > /proc/sys/net/ipv4/conf/default/accept_source_route echo "0" > /proc/sys/net/ipv4/conf/default/accept_send_redirects echo "1" > /proc/sys/net/ipv4/conf/default/rp_filter echo "0" > /proc/sys/net/ipv4/conf/default/log_martians echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses echo "0" > /proc/sys/net/ipv4/conf/default/proxy_arp echo "1" > /proc/sys/net/ipv4/conf/default/arp_filter echo "2" > /proc/sys/net/ipv4/conf/default/arp_announce echo "2" > /proc/sys/net/ipv4/conf/default/arp_ignore echo "128" > /proc/sys/net/ipv4/ip_default_ttl echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse echo "0" > /proc/sys/net/ipv4/tcp_timestamps fi # Clear all tables echo "Start on clean ..." $IPT -F $IPT -t nat -F $IPT -t mangle -F $IPT -X $IPT -t nat -X $IPT -t mangle -X $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP echo "Setting custom chains ..." $IPT -N bad_packets $IPT -N bad_tcp_packets $IPT -N icmp_packets $IPT -N tcp_in $IPT -N udp_in $IPT -N tcp_out $IPT -N udp_out echo "Setting some protections ..." echo " General" $IPT -A bad_packets -p ALL -i $EXT_IF -s $INT_NET -j DROP $IPT -A bad_packets -p ALL -m state --state INVALID -j DROP $IPT -A bad_packets -p tcp -j bad_tcp_packets $IPT -A bad_packets -p ALL -j RETURN echo " TCP" $IPT -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL NONE -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL ALL -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,RST SYN,RST -j DROP $IPT -A bad_tcp_packets -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP $IPT -A tcp_in -p TCP -s 0/0 --destination-port 113 -j REJECT $IPT -A bad_tcp_packets -p tcp -j RETURN echo " ICMP" $IPT -A icmp_packets --fragment -p ICMP -j DROP $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -m limit --limit 1/s -j ACCEPT $IPT -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT $IPT -A icmp_packets -p ICMP -j RETURN echo " UDP" $IPT -A udp_in -p UDP -s 0/0 --dport 137 -j DROP $IPT -A udp_in -p UDP -s 0/0 --dport 139 -j DROP $IPT -A udp_in -p UDP -s 0/0 --dport 113 -j REJECT echo "Filling the chains ..." echo " UDP INCOMING" for PORT in $EXT_IN_UDP ; do $IPT -A udp_in -p UDP -i EXT_IF -s 0/0 --dport $PORT -j ACCEPT; done for PORT in $INT_IN_UDP ; do $IPT -A udp_in -p UDP -i INT_IF -s 0/0 --dport $PORT -j ACCEPT; done $IPT -A udp_in -j RETURN echo " UDP OUTGOING" $IPT -A udp_out -p UDP -s 0/0 -j ACCEPT echo " TCP INCOMING" for PORT in $EXT_IN_TCP ; do $IPT -A tcp_in -p TCP -i $EXT_IF -s 0/0 --dport $PORT -j ACCEPT done for PORT in $INT_IN_TCP ; do $IPT -A tcp_in -p TCP -i $INT_IF-s 0/0 --dport $PORT -j ACCEPT done $IPT -A tcp_in -p TCP -j RETURN echo " TCP OUTGOING" $IPT -A tcp_out -p TCP -j ACCEPT echo " INCOMING" $IPT -A INPUT -p ALL -i $LO_IF -j ACCEPT $IPT -A INPUT -p ALL -j bad_packets $IPT -A INPUT -p ALL -d 224.0.0.1 -j DROP $IPT -A INPUT -p ALL -i $INT_IF -s $INT_NET -j ACCEPT $IPT -A INPUT -p ALL -i $INT_IF -d $INT_BC -j ACCEPT $IPT -A INPUT -p UDP -i $INT_IF --sport 68 --dport 67 -j ACCEPT $IPT -A INPUT -p ALL -i $EXT_IF -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A INPUT -p ALL -i ! $EXT_IF -m state --state NEW -j ACCEPT $IPT -A INPUT -p TCP -i $EXT_IF -j tcp_in $IPT -A INPUT -p UDP -i $EXT_IF -j udp_in $IPT -A INPUT -p ICMP -i $EXT_IF -j icmp_packets $IPT -A INPUT -m pkttype --pkt-type broadcast -j DROP echo " FORWARD" $IPT -A FORWARD -p ALL -j bad_packets $IPT -A FORWARD -p tcp -i $INT_IF -j tcp_out $IPT -A FORWARD -p udp -i $INT_IF -j udp_out $IPT -A FORWARD -p ALL -i $INT_IF -j ACCEPT $IPT -A FORWARD -i $EXT_IF -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A FORWARD -p ALL -i $EXT_IF -m state --state NEW -j ACCEPT echo " OUTPUT" $IPT -A OUTPUT -m state -p icmp --state INVALID -j DROP $IPT -A OUTPUT -p ALL -s $LO_IP -j ACCEPT $IPT -A OUTPUT -p ALL -o $LO_IF -j ACCEPT $IPT -A OUTPUT -p ALL -s $INT_IP -j ACCEPT $IPT -A OUTPUT -p ALL -o $INT_IF -j ACCEPT $IPT -A OUTPUT -p ALL -o $EXT_IF -j ACCEPT echo " NAT" echo " PORT FORWARDING" TMP="`echo $INT_IP | cut -d\. -f1-3`" for HOST in `seq 2 254` ; do PORTR=$((10000+HOST*10)):$((10009+HOST*10)) echo " $PORTR for $TMP.$HOST" $IPT -A FORWARD -p udp -i $EXT_IF --dport $PORTR -d $TMP.$HOST -j ACCEPT $IPT -A FORWARD -p tcp -i $EXT_IF --dport $PORTR -d $TMP.$HOST -j ACCEPT $IPT -t nat -A PREROUTING -p udp -i $EXT_IF --dport $PORTR -j DNAT --to $TMP.$HOST $IPT -t nat -A PREROUTING -p tcp -i $EXT_IF --dport $PORTR -j DNAT --to $TMP.$HOST done $IPT -t nat -A POSTROUTING -o $EXT_IF -j SNAT --to $EXT_IP if [ -z $SYSCTL ] ; then $SYSCTL net.ipv4.ip_forward=1 else echo "1" > /proc/sys/net/ipv4/ip_forward fiКато цяло това е един относително добър базов firewall. В него има няколко интересни момента а именно:
Рутер който изпълнява баланс на трафика от два или повече доставчика
Тук ще дадем само частта която реално изпълнява балансирането на трафика. Вземаме пример само с два доставчика, но разширяването на примера не е проблем. Задачата е малко по обемиста тъй като за удобство ще използваме iproute. Самият пакет има доста криптичен синтаксис но след като му свикнете едва ли ще ви се разделя с него.
За да можем да балансираме трафик ни трябват следните инструменти:
За да можем да използваме имена в конфигурацията е необходимо да ги добавим във файла /etc/iproute2/rt_tables. Индексите им са между 2 и 252. Ако ще балансирате повече от 200 доставчика … не четете на правилното място.
#!/bin/bash # # Simple balancing router # author: vvitkov # contact: http://www.getoto.net/az/ # # Licence: CC NC-BY-SA v3 # Disclaimer: i take no responsibility for the consequences of using or not using this. # It is up to you to decide what to do with this stuff. # Please if you use this write me a note and don't remove the author info. ### Settings ISP1_NET="1.2.3.0/24" ISP1_GW="1.2.3.1" ISP1_IF="eth1" ISP1_OUR_HOST="1.2.3.99" ISP2_NET="9.8.7.0/24" ISP2_GW="9.8.7.1" ISP2_IF="eth2" ISP2_OUR_HOST="9.8.7.99" INT_NET="10.42.3.0/24" # Defining routing tables for source routing if ( ip ru ls | grep main | grep 50 ) then ip r f t main else ip ru a prio 50 t main fi if ( ip ru ls | grep isp_rules1 ) then ip r f t isp_rules1 else ip ru a from $ISP1_NET prio 201 t isp_rules1 fi if ( ip ru ls | grep isp_rules2 ) then ip r f t isp_rules2 else ip ru a from $ISP2_NET prio 202 t isp_rules2 fi # Clear all the existing routes ip r f any ip r f t default # Host routes ip r a $ISP1_NET dev $ISP1_IF src $ISP1_OUR_HOST ip r a $ISP2_NET dev $ISP2_IF src $ISP2_OUR_HOST # Local networks ip r a 127.0.0.0/8 dev lo ip r a $INT_NET dev eth0 # Default gateways ip r a 0/0 via $ISP1_GW dev $ISP1_IF table isp_rules1 proto static ip r a prohibit 0/0 table isp_rules1 metric 1 proto static ip r a 0/0 via $ISP2_GW dev $ISP2_IF table isp_rules2 proto static ip r a prohibit 0/0 table isp_rules2 metric 1 proto static # lets shake it :) ip r a 0/0 proto static table default nexthop via $ISP1_GW dev $ISP2_IF nexthop via $ISP2_GW dev $ISP2_IF # Remote networks with static routes ip r a < NETWORK IN ISP1 > via $ISP1_GW dev $ISP1_IF ip r a < NETWORK IN ISP2 > via $ISP2_GW dev $ISP2_IF # flush caches ip r f cС това завършват примерите за конфигуриране на рутер. Знам че не са покрити всички възможности, но човек трябва да се потруди малко.
Серията продължава в The Perfect SOHO router – Part 5