Когда-то давно когда я впервые поставил dd-wrt на свой роутер (Dlink dir-615), я просто подумал что этопрошивка ну как бы просто «еще одна прошивка» для тех кто недоволен стандартной от производителя роутера, однако подключившись по telnet к роутеру я увидел самый что не на есть Linux.
В статье ни будет ни слова о том как прошить роутер. Это делается весьма индивидуально для каждой модели роутера. Зато будет то как настроить на нем 2 точки доступа и в целом оптимизировать, а также создавать туннели между такими роутерами.
Просто Linux
Сходив по телнету на роутер можно увидеть самый обычный Linux. Ну так как в комплекте Linux то наверняка есть:
— Фаервол Iptables
— поддержка ip_conntrack
— утилиты из iproute2.
Также наверняка есть дополнительные утилиты:
— brctl (для управления мостами)
— ping, telnet, ssh, mount и все что полагается иметь обычному сетевому маршрутизатору на Linux
Две точки доступа или как осчастливить соседей
Когда я увидел что в настройках Wi-Fi есть возможность создать еще одну точку доступа, я как бы удивился. Оказывается почти все чипы Wi-Fi это умеют, только добрые дяди из $vendor обычно такой функционал считают лишним для домохозяек (а много ли домохозяек настраивают роутеры).
Постепенно разбираясь во всем я решил обеспечить всей улице (у роутера 2 антенны и очень неплохая мощьность) бесплатный интернет, передо мной стало 2 проблемы (решение которых я и опишу далее):
1. Как обеспечить моей домашней сети безопасность путем отрезания доступа в нее с бесплатной точки доступа.
2. Как порезать скорость, чтобы добрые соседи не поедали мой канал.
Ну решение первого прозрачно, фаервол. Но как, что и где не понятно. Второе же тоже понятно, раз есть iproute2 есть и tc, а он может… да чего он только не может.
Создаем точку (Конфигурация интерфейса)
создаем вторую точку доступа и называем ее как нибудь
Открываем дополнительные параметры, и устанавливаем «Конфигурация Сети: Не в мосте», «Многоадресные потоки: Отключить», «Masquerade/NAT: Отключить». И вибираем ip адрес для этого виртуального интерфейса, я выбрал маленькую сеть на 16 ip адресов.
Далее надо убедиться что отключено шифрование на этой точке.
Комманды
Переходим к командному блоку.
Настройка sysctl
Сначала предлагаю настроить sysctl, так как самой утилиты sysctl нет в комплекте, то настроим через proc
echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
echo "1" > /proc/sys/net/ipv4/tcp_abort_on_overflow
echo "0" > /proc/sys/net/ipv4/tcp_ecn
echo "600" > /proc/sys/net/ipv4/tcp_fin_timeout
echo "750" > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo "9" > /proc/sys/net/ipv4/tcp_keepalive_probes
echo "7200" > /proc/sys/net/ipv4/tcp_keepalive_time
echo "65536" > /proc/sys/net/ipv4/tcp_max_orphans
echo "1024" > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo "180000" > /proc/sys/net/ipv4/tcp_max_tw_buckets
echo "1" > /proc/sys/net/ipv4/tcp_orphan_retries
echo "3" > /proc/sys/net/ipv4/tcp_reordering
echo "1" > /proc/sys/net/ipv4/tcp_retrans_collapse
echo "3" > /proc/sys/net/ipv4/tcp_retries1
echo "15" > /proc/sys/net/ipv4/tcp_retries2
echo "0" > /proc/sys/net/ipv4/tcp_rfc1337
echo "4096 87380 4194304" > /proc/sys/net/ipv4/tcp_rmem
echo "1" > /proc/sys/net/ipv4/tcp_sack
echo "5" > /proc/sys/net/ipv4/tcp_syn_retries
echo "5" > /proc/sys/net/ipv4/tcp_synack_retries
echo "1" > /proc/sys/net/ipv4/tcp_timestamps
echo "1" > /proc/sys/net/ipv4/tcp_window_scaling
echo "196608 262144 393216" > /proc/sys/net/ipv4/tcp_mem
echo "4096 16384 4194304" > /proc/sys/net/ipv4/tcp_wmem
echo "65535" > /proc/sys/net/ipv4/ip_conntrack_max
echo "65535" > /proc/sys/net/netfilter/nf_conntrack_max
echo "65535" > /proc/sys/net/ipv4/netfilter/ip_conntrack_max
echo "65535" > /proc/sys/net/nf_conntrack_max
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo "6168" > /proc/sys/net/ipv4/icmp_ratemask
echo "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
echo "1" > /proc/sys/net/ipv4/conf/all/arp_filter
echo "0" > /proc/sys/net/ipv4/conf/all/log_martians
echo "0" > /proc/sys/net/ipv4/conf/all/mc_forwarding
echo "0" > /proc/sys/net/ipv4/conf/all/proxy_arp
echo "1" > /proc/sys/net/ipv4/conf/all/secure_redirects
echo "1" > /proc/sys/net/ipv4/conf/all/send_redirects
echo "1" > /proc/sys/net/ipv4/conf/all/shared_media
echo "500" > /proc/sys/net/ipv4/route/error_cost
echo "262144" > /proc/sys/net/ipv4/ipfrag_high_thresh
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo "1024 4999" > /proc/sys/net/ipv4/ip_local_port_range
echo "1" > /proc/sys/net/ipv4/ip_no_pmtu_disc
echo "0" > /proc/sys/net/ipv4/ip_nonlocal_bind
echo "30" > /proc/sys/net/ipv4/ipfrag_time
echo "120" > /proc/sys/net/ipv4/inet_peer_gc_maxtime
echo "10" > /proc/sys/net/ipv4/inet_peer_gc_mintime
echo "600" > /proc/sys/net/ipv4/inet_peer_maxttl
echo "120" > /proc/sys/net/ipv4/inet_peer_minttl
echo "65664" > /proc/sys/net/ipv4/inet_peer_threshold
echo "2" > /proc/sys/net/ipv4/tcp_adv_win_scale
echo "31" > /proc/sys/net/ipv4/tcp_app_win
echo "1" > /proc/sys/net/ipv4/tcp_dsack
echo "0" > /proc/sys/net/ipv4/tcp_ecn
echo "1" > /proc/sys/net/ipv4/tcp_fack
echo "20" > /proc/sys/net/ipv4/igmp_max_memberships
echo "0" > /proc/sys/net/ipv4/conf/all/bootp_relay
вставляем код в textarea в блоке Команды, и нажимаем «Сохранить параметры запуска» (Save startup)
фаервол iptables
Ниже приведу команды своего фаервола, думаю кому-то будет интересно что зачем, поэтому команды комментируются.
#####################################
# Назначаем дисциплиной обработки очереди htb
tc qdisc add dev `nvram get wan_ifnames` root handle 1: htb default 2
# создаем класс в 100 мегабит, и дисциплину sfq для равномерного распределения трафика между клиентами
tc class add dev `nvram get wan_ifnames` parent 1: classid 1:1 htb rate 100mbit
tc qdisc add dev `nvram get wan_ifnames` parent 1:1 handle 2: sfq perturb 10
# Режем скорость на интерфейсе ath0.1 наша точка для гостей и соседей
tc class add dev `nvram get wan_ifnames` parent 1: classid 1:3 htb rate 1024kbit
tc qdisc add dev `nvram get wan_ifnames` parent 1:3 handle 3: sfq perturb 10
# все пакеты помеченные флагом 0x2ff будут попадать в эту дисциплину
tc filter add dev `nvram get wan_ifnames` parent 1:0 protocol ip prio 1 handle 0x2ff fw classid 1:3
# а вот правило фаервола.
# если пакеты вылетают в wan порт, а прилетают с интерфейса ath0.1 тогда поставить им метку 0x2ff
iptables -t mangle -A FORWARD -o `nvram get wan_ifnames` -i ath0.1 -j MARK --set-mark 0x2ff
# С ath0.1 исходящий трафик порезан, теперь надо порезать трафик приходящий на ath0.1
# добавляем дисциплину
tc qdisc add dev ath0.1 root handle 1: htb default 1
# все что вылетает на ath0.1 летит в очередь 1:1 с указанной скоростью
tc class add dev ath0.1 parent 1: classid 1:1 htb rate 1024kbit
# Теперь правило которое отбрасывает все пакеты которые направляются с ath0.1 и НЕ во внешний мир
iptables -t nat -I POSTROUTING -j SNAT -s `nvram get ath0.1_ipaddr`/`nvram get ath0.1_netmask` -o `nvram get wan_ifnames` --to-source `nvram get wan_ipaddr`
iptables -I FORWARD -i ath0.1 ! -o `nvram get wan_ifnames` -j DROP
#####################################
# Далее я удаляю какое-то магическое правило с роутера, зачем оно нужно ума не приложу, ну и не нужно оно
iptables -t nat -D POSTROUTING -o br0 -j MASQUERADE -s `nvram get lan_ipaddr`/`nvram get lan_netmask` -d `nvram get lan_ipaddr`/`nvram get lan_netmask`
# Стандартный SNAT направляет все пакеты со всех подсетей и со всех интерфейсов кроме WAN
# в интернет натируя трафик, мне это неподходит, да и вам не подходит, ведь на очереди тунели.
# удаляем это правило
iptables -t nat -D POSTROUTING -j SNAT -o `nvram get wan_ifnames` --to `nvram get wan_ipaddr`
# и добавляем правило которое натирует только подсеть на портах LAN
iptables -t nat -I POSTROUTING -j SNAT -s `nvram get lan_ipaddr`/`nvram get lan_netmask` -o `nvram get wan_ifnames` --to-source `nvram get wan_ipaddr`
# некоторые простые защиты
# Игнор всего фрагментированного
iptables -A INPUT -f -j DROP
# Ограничение колличества syn пакетов (Anty SYN Flood)
iptables -A INPUT -p tcp --syn -m limit --limit 100/second --limit-burst 150 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
# игнор пакетов с "неправильными" флагами
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# Так как проц не резиновый а телнет демон, чтобы не зафлудили по telnet
iptables -A INPUT -i `nvram get wan_ifnames` -p tcp --dport 23 -m state --state NEW -m recent --set --name TELNET
iptables -A INPUT -i `nvram get wan_ifnames` -p tcp --dport 23 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name TELNET -j DROP
# И наконец корректная обработка tcp при разных MTU
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o tun0 -j TCPMSS --clamp-mss-to-pmtu
################################################
# Далее я пишу 2 скрипта, которые в дальнейшем организуют туннели
# про это далее
################################################
insmod etherip
mount -t tmpfs none /opt
echo '#!/bin/sh' > /opt/etherip.sh
echo 'ip tunnel del $1 2>&1 > /dev/null' >> /opt/etherip.sh
echo 'ip tunnel add $1 mode etherip remote $2 local `nvram get wan_ipaddr`' >> /opt/etherip.sh
echo 'ip addr add $3 dev $1' >> /opt/etherip.sh
echo 'ip link set $1 up' >> /opt/etherip.sh
chmod a+x /opt/etherip.sh
# /opt/etherip.sh tun-name remote IFace
echo '#!/bin/sh' > /opt/gre.sh
echo 'ip tunnel del $1 2>&1 > /dev/null' >> /opt/gre.sh
echo 'ip tunnel add $1 mode gre remote $2 key $3 ttl 255' >> /opt/gre.sh
echo 'ip addr add $4 peer $5 dev $1' >> /opt/gre.sh
echo 'ip link set $1 up' >> /opt/gre.sh
chmod a+x /opt/gre.sh
# /opt/gre.sh tun-name remote KEY localIP remoteIP
Так, вроде все готово, теперь о том как клиенты свободной точки будут получать IP. DHCP конечно, только вот нужен второй DHCP сервер, и он есть из коробки.
Туннели
Итак теперь представьте ситуацию. У вас есть 2 офиса, в них… стоп. Все проще, у вас есть друг с dd-wrt, также у вас есть банальное желание поиграть с ним… ну скажем в queke II coop. У друга один провайдер а у вас другой. Ну казалось бы ответ очевиден, Hamachi или всякое-там разное проприетарное. Отличное решение обычной проблемы. а теперь представим что всетаки есть 2 офиса, и коннект должен быть
24*7*365 и мало того там есть всякие принтеры, пусть даже корпоративный прокси. Cisco, скажете вы, дороговато, скажу я.
Обратим внимание на 2 скрипта приведенные в файерволе, да это туннелирование gre или ethernet over ip (протокол etherip поддерживаемый freebsd cisco но почему-то не поддерживаемый в Linux). Логика создания туннеля такова.
Есть 2 устройства
alpha и
beta, на устройстве
alpha lan подсеть
192.168.2.0/24, на устройстве
beta192.168.3.0/24. На устройстве
alpha wan IP al.p.h.a на
beta b.e.t.a. На
alpha создается интерфейс
10.0.0.1/30 на beta
10.0.0.2/30 и 2 маршрута.
ALPHA/opt/etherip.sh beta b.e.t.a 10.0.0.1/30
route add -net 192.168.3.0/24 gw 10.0.0.2
BETA/opt/etherip.sh alpha al.p.h.a 10.0.0.2/30
route add -net 192.168.2.0/24 gw 10.0.0.1
Общая логика такова. Так к чему я про друга с quake II, лучше попробуйте с ним. Не надо экспериментов в production.
Что дальше?
К сожалению у меня сейчас потерян коннект с роутером dir-320 в который были воткнуты 3 провайдра. Дело в том, что на dir-320 мало того что есть usb и туда можно поставить какой нибудь nginx+postgresql+python+django, так у него внутри умный свитч, а это значит что там создается 3 интерфейса в портах lan, а порт wan включается в конторский свитч. В итоге балансировка, отказоустойчивость, wi-fi, firewall, банилка «xxxxклассников».
Эта контора звонила мне год назад, сказали что к ним пришел специалист и что он спрашивает пароль на роутер, утверждая что я перепутал порты WAN и LAN, я спросил «А у вас все работает?», они ответили утвердительно, тогда я спросил зачем от туда лезет и они внятно мне не объяснили, я сказал «Я дам вам пароль но если этот мастер что нибудь сломает, то я к вам не поеду, а если и поеду то проделаю все работу заново, а это стоит столько же», в общем пароль им не пригодился, год уже не звонят. Бог знает может уже развалились, а может ip сменился, но доступа сейчас нет.
Вообще возможности dd-wrt мне напоминают cisco. В том смысле что если уж reboot не помог, то что-то сломалось не в этой железке.
Все команды я попытался завязать на nwram роутеров, чтобы разные модели работали одинаково. Единственная разница это имя wi-fi адаптера может быть другим. Ну тогда заменяем все ath на имя вашего адаптера в командах.