суббота, 15 января 2011 г.

Gentoo и две сетевые карты с выходом в интернет. Маршрутизация.

___Наш gentoo сервер был подключен к локальной сети и ко внешнему миру через один канал. Но вот появилась возможность, а затем и необходимость подключить его еще по одному каналу. Для этого была воткнута сетевая карта, пересобрано ядро с её поддержккой, воткнут сетевой кабель и тут началось самое интересное.
___Итак исходная ситуация. Компьютер имеет 2 сетевых интерфейса, у каждого сетевого интерфейса свой шлюз, через который есть доступ в интернет. На каждом шлюзе, переброшен порт 80, на наш компьютер, и хочется, что бы все работало, не зависимо, к какому шлюзу извне идет обращение. Все бы хорошо, но: доступ из вне работал только с того шлюза, который указан в системе по умолчанию, с другого же доступа не было — пакеты, которые должны лететь на запрос, улетали через другой шлюз — тот, который по умолчанию.
___А хотелость то простого: что бы пакеты, прилетевшие через один интерфейс, летели обратно через тот же интерфейс, и через шлюз, который прописан для данного интерфейса. Товарищи подсказали направление «раскопок» - iproute2. Пакет был установлен, и на протяжении нескольких дней было активное разбирательство с проблемой.
___Итак, итоговый конфиг выглядит следующим образом:
/etc/conf.d/net
# This blank configuration will automatically use DHCP for any net.*
# scripts in /etc/init.d. To create a more complete configuration,
# please review /etc/conf.d/net.example and save your configuration
# in /etc/conf.d/net (this file :]!).
modules=("iproute2" "!ifconfig")
dns_domain_lo=("dc2")
#eth1 - internal ethernet adapter
#dns_domain_eth1=("dc2")
config_eth1=("10.168.159.2 netmask 255.255.255.0")
config_eth2=("192.168.0.2 netmask 255.255.255.0")
routes_eth2=("192.168.0.1 dev eth2 src 192.168.0.2 table mgn-unlim"
"default via 192.168.0.1 table mgn-unlim"
)
#routes_eth2=("default via 192.168.0.1 table mgn-unlim")
rules_eth2=("from 192.168.0.2 table mgn-unlim")
routes_eth1=("10.168.159.4 dev eth1 src 10.168.159.2 table not-unlim"
"default via 10.168.159.4 table not-unlim"
"77.91.226.69 via 192.168.0.1"
)
#routes_eth1=("default via 10.168.159.4 table not-unlim")
rules_eth1=("from 10.168.159.2 table not-unlim")
#routes_eth2=("77.91.226.69 via 192.168.0.1")
#eth2 - external ethernet adapter
dns_servers_eth2=("192.168.0.1")
dns_servers_eth1=("10.168.159.6")
#Функция ниже, взята из /etc/conf.d/net.example — она нужна для того, что бы при после #запуска интерфейса применялись правила
postup(){
# This function could be used, for example, to register with a
# dynamic DNS service. Another possibility would be to
# send/receive mail once the interface is brought up.
# Here is an example that allows the use of iproute rules
# which have been configured using the rules_eth0 variable.
#rules_eth0=(
# "from 24.80.102.112/32 to 192.168.1.0/24 table localnet priority 100"
# "from 216.113.223.51/32 to 192.168.1.0/24 table localnet priority 100"
#)
local x="rules_${IFVAR}[@]"
local -a rules=( "${!x}" )
if [[ -n ${rules} ]] ; then
einfo "Adding IP policy routing rules"
eindent
# Ensure that the kernel supports policy routing
if ! ip rule list | grep -q "^" ; then
eerror "You need to enable IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES)"
eerror "in your kernel to use ip rules"
else
for x in "${rules[@]}" ; do
ebegin "${x}"
ip rule add ${x}
eend $?
done
fi
eoutdent
# Flush the cache
ip route flush cache dev "${IFACE}"
fi
}
___Сами же таблицы, описаны в 
/etc/iproute2/rt_tables:
# cat /etc/iproute2/rt_tables
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#added by maxt
201 mgn-unlim
202 not-unlim
#
# local
#
#1 inr.ruhep

Отдельное спасибо пользователю izbushka с gentoo-ru на freenode за помощь в выявлении ошибок в процессе настройки данной конфигурации.

1 коммент.:

maxt комментирует...

Что интересно.В правилах явно указано: если пакет пришел с такого то интерфейса, то ответ отправлять через такой то шлюз.
Но вот ведь неучтено было, что правило будет работать для всех пакетов, в том числе и тех, которые пришли из внутренней сети. То есть, ответ компу, который находится в той же под сети что и один из интерфейсов сервера - будет отправлен через шлюз. Тонкий нюанс, обнаружен эксперементально - баном мака сервера на шлюзе. Вывод - нужно добавлять правило для пакетов из той же подсети, что бы они летели напрямую.