Являясь владельцем маршрутизатора ASUS WL500-g и после огромного количества попыток использовать весь потенциал данной поделки китайского радиопрома, я остановился на прошивке со скромным названием
OpenWRT. Как и все открытые продукты данная прошивка была основана на ядре линукс, бизибоксе, аше и прочей дребедени. После множества интересных приключений связанных с юсб, беспроводной сетью, совместимостью версий ядер и модулей к проприетарному железу установленному в эту коробку все наконец заработало. Но возник интересный прецедент. Я использую собственный DNS сервер как примари для обслуживания зоны fomichi.ru. И когда компьютеры внутри сети пытаются правильно разрезолвить адрес сервера фомичей они получают его внешний IP. При попытке обратиться к нему пакет выбирается наружу через роутер, проходит NAT и возвращается обратно в маршрутизатор через внешний интерфейс, который его занатил. При попытки вернуться обратно с правилами по умолчанию пакет теряется и пользователь внутренней сети получает шиш с маслом, а не веб ресурс фомичей, хотя пинги идут исправно. Перекопав километры интернета и исправно и качественно покурив гугль был обнаружен скрипт который достаточно просто реализует так называемый NAT Loopback. Собственно вот он:
Устанавливаем iptables-utils (без этого пакета ничего работать не будет)
Потом создаем скрипт на роутере в любой папке с правами на исполнение. Например 777 😉
#!/bin/sh
#File: natloopback.sh
#Requires iptables-utils package
local WANZONE
local LANZONE
local lan_addr
local lan_net
local CHECKDIFF
local CHKCHAIN
local execute
local DNATS
local MINIUPNPD
. /etc/functions.sh
syntax() {
echo «Syntax: ‘natloopback.sh <wan zone> <lan zone>'»
exit
}
if [ -z $2 ]; then
syntax
fi
WANZONE=$1
LANZONE=$2
config_load «network»
config_get if_wan ${WANZONE:-wan} ifname
config_get wan_ip ${WANZONE:-wan} ipaddr
config_get lan_ip ${LANZONE:-wan} ipaddr
config_get lan_mask ${LANZONE:-wan} netmask
lan_addr=`echo $lan_ip | awk -F «.» ‘{print $1″.»$2″.»$3″.0″}’`
lan_net=$(echo $lan_addr/$lan_mask)
if [ -z «$if_wan» -o -z «$lan_ip» -o -z «$lan_mask» ]; then
syntax
fi
iptables-save -t nat | grep DNAT | grep -v nlb > /tmp/.natloopback.$WANZONE.current
if [ -e «/tmp/.natloopback.${WANZONE}.lastupdate» ]; then
CHECKDIFF=`diff -q /tmp/.natloopback.${WANZONE}.lastupdate /tmp/.natloopback.${WANZONE}.current 2>&1`
else
CHECKDIFF=1
fi
CHKCHAIN=`iptables -L prerouting_rule -t nat | grep nlb_${WANZONE}_pre`
if [ ! -z «$CHECKDIFF» -o -z «$CHKCHAIN» ];
then
if [ -z «$CHKCHAIN» ]; then
iptables -N nlb_${WANZONE}_pre -t nat > /dev/null 2>&1
iptables -A prerouting_rule -t nat -j nlb_${WANZONE}_pre
iptables -N nlb_${WANZONE}_for > /dev/null 2>&1
iptables -A forwarding_rule -j nlb_${WANZONE}_for
iptables -N nlb_${WANZONE}_post -t nat > /dev/null 2>&1
iptables -A postrouting_rule -t nat -j nlb_${WANZONE}_post
fi
iptables -F nlb_${WANZONE}_pre -t nat > /dev/null 2>&1
iptables -F nlb_${WANZONE}_for > /dev/null 2>&1
iptables -F nlb_${WANZONE}_post -t nat > /dev/null 2>&1
DNATS=`cat /tmp/.natloopback.${WANZONE}.current | grep zone_${WANZONE}_prerouting`
MINIUPNPD=`cat /tmp/.natloopback.${WANZONE}.current | grep MINIUPNPD`
nat_loopback() {
iptables -t nat -A nlb_${WANZONE}_pre -d $wan_ip -p $1 —dport $2 -j DNAT —to-destination $3
iptables -A nlb_${WANZONE}_for -p $1 —dport $2 -d $(echo $3 | awk -F «:» ‘{print $1}’) -j ACCEPT
iptables -t nat -A nlb_${WANZONE}_post -s $lan_net -p $1 —dport $2 -d $(echo $3 | awk -F «:» ‘{print $1}’) -j SNAT —to-source $wan_ip
}
if [ ! -z «$DNATS» ]; then
echo «$DNATS» | while read execute
do
SCAN=$(echo ${execute} | awk -F » » ‘{print $4 » » $8 » » $12}’)
nat_loopback $SCAN
done
fi
if [ ! -z «$MINIUPNPD» ]; then
echo «$MINIUPNPD» | while read execute
do
SCAN=$(echo ${execute} | awk -F » » ‘{print $4 » » $8 » » $12}’)
nat_loopback $SCAN
done
fi
mv /tmp/.natloopback.${WANZONE}.current /tmp/.natloopback.${WANZONE}.lastupdate
fi
Запускаем с значениями зоны лан и ван (обычно это lan и wan по умолчанию), то есть если мы назвали скрипт natloop.sh и положили его в etc, то строка запуска будет /etc/natloop.sh lan wan
дописываем в /etc/firewall.user
sh /где_лежит_скрипт/имя_скрипта.sh lan wan
После этого перезапускаем фаервол при помощи скрипта /etc/init.d/firewall restart и если не появилост ошибок, то проверяем как все работает. Обычно все работает.
За скрипт огромное спасибо неизвестному автору с неизвестного форума.
Скрипт писан только под OpenWRT, с другими системами без адаптации скорее всего не заработает.