Работа одновременно с двумя выделенными линиями. Часть 2. Локальные сети и интернет

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

<a href="http://www.linuxetc.ru/?p=13" class="forlinuxetc">(Оригинал написан для linuxetc.ru)</a> В <a href="http://www.linuxetc.ru/?p=12">первой части</a> речь шла о первичной настройке одновременной работы с двумя локальными сетями, к которым присоединен ваш компьютер. Несмотря на достаточно сырое изложение материала, рекомендую прочитать сначала её -- там как минимум описаны нюансы конфигурирования ядра Linux, которые надо учесть при работе с утилитами расширенного роутинга пакета iproute2.

Сейчас речь пойдёт об одновременной работе как двух локальных сетей, так и двух шлюзов в интернет, предоставляемых этими двумя сетями.

<!--break-->

<h3>Построение маршрутов в локальные сети</h3>

Для начала сконфигурируем dhcp клиентов для обоих интерфейсов, запретив им перезаписывать /etc/resolv.conf и устанавливать маршруты по умолчанию.

<a href="#net2" name="net1">Первая</a> выдержка из /etc/conf.d/net:

<blockquote>

modules=("iproute2")

config_eth0=( "dhcp" )
dhcp_eth0="nodns nogateway"

config_eth1=( "dhcp" )
dhcp_eth1="nodns nogateway"

</blockquote>

Убедитесь, что оба интерфейса запускаются при старте системы:

<blockquote>
testcomp # rc-status
Runlevel: default
...
net.eth0 [ started ]
net.eth1 [ started ]
...
</blockquote>

Я переписал скрипт /etc/conf.d/local.start, отрабатывающий при старте системы после всех остальных сервисов. Основную часть кода, строящую статические маршруты в обе локальные сети, я обобщил на случай произвольного числа локальных сетей, присоединенных к сетевым интерфейсам eth0, eth1, ..., ethN. Первоначальную версию можно найти в <a href="http://www.linuxetc.ru/?p=12">первой части</a> данной статьи.

Подразумевается, что все сетевые интерфейсы получают свои ip по dhcp и сети не пересекаются по диапазонам ip.

Рекомендуется внимательно прочесть и изменить необходимые параметры под свои нужды.

Выдержка из /etc/conf.d/local.start:

<blockquote>
<pre>
# Функция build_local_routing строит статические роутинги в заданную локальную сеть и
# доступные через неё сети.

# Входные параметры:
# interface -- имя сетевого интерфейса, к которому присоединена
# локальная сеть.
# routing_table -- имя или номер таблицы маршрутизации. К моменту запуска
# скрипта должны быть прописаны в /etc/iproute2/rt_tables.
# local_nets -- локальная сеть/сети, доступные через интерфейс $interface.
# Перечисляются списком через пробел, например
# "10.72.0.0/16 85.21.0.0/16"

# Для работы функции необходимо наличие:
# dhcp -- интерфейс $interface должен получать адрес по DHCP,
# а информация об адресах и прочем иметься в файле
# /var/lib/dhcpcd/dhcpcd-$interface.info, создаваемом
# клиентом dhcp.
# iproute2 -- маршруты прописываются только в ту таблицу маршрутизации,
# что отвечает за связь с локальной сетью. Также определяются
# правила использования этой таблицы маршрутизации.
# Обычная команда route ничего не знает ни про раздельные
# таблицы маршрутизации, ни про правила их использования.
# ipcalc -- эта утилита применяется для вычисления сегмента сети,
# выданного по DHCP.

function build_local_routing()
{
interface=$1
routing_table=$2
local_nets=$3

. /var/lib/dhcpcd/dhcpcd-$interface.info
network=`ipcalc $IPADDR/$NETMASK | grep Network | awk '{print $2}'`
ip route flush table $routing_table >/dev/null 2>&1

# Прописываем правила маршрутизации для DNS
for DNS in $DNSSERVERS; do
ip rule add to $DNS lookup $routing_table
done;

ip rule add from $IPADDR lookup $routing_table
ip rule add to $network lookup $routing_table

# Определяем статические маршруты в таблице маршрутизации $routing_table
# и правила их выбора
ip route add $network dev $interface src $IPADDR table $routing_table
for net in $local_nets; do
[ "$net" != "$network" ] && ip route add $net via $GATEWAYS table $routing_table
[ "$net" != "$network" ] && ip rule add to $net lookup $routing_table
done
ip route add default via $GATEWAYS table $routing_table
ip route add 127.0.0.0/8 dev lo table $routing_table
}

# Функция write_resolv_conf определяет порядок использования DNS серверов,
# доступныых через локальные сетевые интерфейсы.

# Входные параметры:
# interfaces -- локальные интерфейсы. Перечисляются списком через пробел, например
# "eth1 eth0" или "eth0 eth1". Записи о DNS заносятся
# в /etc/resolv.conf в порядке перечисления интерфейсов.

function write_resolv_conf()
{
interfaces=$*
rm -f /etc/resolv.conf
for int in $interfaces; do
. /var/lib/dhcpcd/dhcpcd-$int.info
for i in $DNSSERVERS; do
echo "nameserver $i" >> /etc/resolv.conf
done;
done;
}

build_local_routing "eth0" "local_golnet" "192.168.0.0/16"

build_local_routing "eth1" "local_corbina" "10.72.0.0/16 85.21.0.0/16"

# Прописываем нужный порядок DNS серверов в /etc/resolv.conf
write_resolv_conf "eth1 eth0"

# Обращения к VPN Корбины маршрутизировать согласно local_corbina
. /var/lib/dhcpcd/dhcpcd-eth1.info
HOST_CMD="hostx"
VPN_SERVER="vpn.corbina.net"
IP_LIST="`${HOST_CMD} ${VPN_SERVER} | awk '{print $3}' `"
for ADDRESS in `echo "${IP_LIST}"`
do
ip rule add to $ADDRESS table local_corbina
done

ip route flush cache

</pre>
</blockquote>

После сохранения всех изменений в скриптах стартапа перезагрузим систему (редкая для Linux операция в данном случае совершенно оправдана). Если всё нормально (см. <a href="http://www.linuxetc.ru/?p=12">первую часть статьи</a>), можно приступить к настройке интерфейсов интернета.

<h3>Конфигурация интерфейсов интернета</h3>

Интернет как от GolNet, так и от Corbina я получаю посредством pptp.

<a href="#net1" name="net2">Вторая</a> выдержка из /etc/conf.d/net:

<blockquote>

config_ppp0=( "ppp" )
mtu_ppp0="1400"
link_ppp0="pty 'pptp 192.168.0.3 --nobuffer --loglevel 0 --nolaunchpppd'"
username_ppp0='user1'
password_ppp0='passwd1'
pppd_ppp0=(
"lock"
"asyncmap 0"
"crtscts"
"nodefaultroute"
"persist"
"noauth"
"nobsdcomp"
"nodeflate"
"require-mppe"
"lcp-echo-failure 10"
"lcp-echo-interval 10"
<strong>":172.1.1.1"</strong>
)

config_ppp1=( "ppp" )
mtu_ppp1="1400"
link_ppp1="pty 'pptp vpn.corbina.net --nobuffer --loglevel 0 --nolaunchpppd'"
username_ppp1='user2'
password_ppp1='passwd2'
pppd_ppp1=(
"noauth"
"persist"
"refuse-eap"
"refuse-pap"
"refuse-chap"
"refuse-mschap"
"nodefaultroute"
"nobsdcomp"
"nodeflate"
<strong>":172.1.1.2"</strong>
)

</blockquote>

Обратите особое внимание на две <strong>выделенные</strong> строчки. Я указываю для обоих интерфейсов установить заданный ip-адрес шлюза на другом конце ppp туннеля. Значения выбраны так, чтобы не пересекаться ни с одной из имеющихся у меня на машине сетей.

<h4>Подъём ppp-соединения</h4>
Сразу после подъёма любого ppp соединения у меня на машине отрабатываются скрипты /etc/ppp/ip-up.d/*, в частности, /etc/ppp/ip-up.d/90-local.sh, задающие таблицы маршрутизации, правила их выбора и маршрут по умолчанию. На других системах аналогичную роль выполняет скрипт /etc/ppp/ip-up.local. Обратитесь к документации на pptp, чтобы узнать, где находится подобный скрипт на вашей машине.

Выдержка из /etc/ppp/ip-up.d/90-local.sh:

<blockquote>
<pre>
#!/bin/sh

# This script is run by pppd after the link is established.
# It executes all the scripts available in /etc/ppp/ip-up.d directory,
# with the following parameters:
# $1 = interface name (e.g. ppp0)
# $2 = tty device
# $3 = speed
# $4 = local IP address
# $5 = remote IP address
# $6 = ipparam (user specified parameter, see man pppd)

if [ "$1" == "ppp0" ]; then
ip rule add from $4 lookup internet_golnet
ip route add 192.168.5.0/24 via 192.168.5.7 dev eth0 table internet_golnet
ip route add 192.168.0.0/16 via 192.168.5.7 dev eth0 table internet_golnet
ip route add 127.0.0.0/8 dev lo table internet_golnet
ip route add default via $5 dev ppp0 table internet_golnet
fi;
if [ "$1" == "ppp1" ]; then
ip rule add from $4 lookup internet_corbina
ip route add 10.72.0.0/16 via 10.72.0.17 dev eth1 table internet_corbina
ip route add 85.21.0.0/16 via 10.72.0.17 dev eth1 table internet_corbina
ip route add 127.0.0.0/8 dev lo table internet_corbina
ip route add default via $5 dev ppp1 table internet_corbina
fi

ip route del default
ip route add default via $5
</pre>
</blockquote>

Как видим, скрипт заполняет соответствующие каждому из провайдеров таблицы маршрутизации и добавляет правило его выбора. Правило обеспечивает ответ с того же интернетного ip-адреса, на какой пришёл запрос "извне", из интернета.

Таблицы маршрутизации internet_golnet и internet_corbina, естественно, должны быть прописаны в /etc/iproute2/rt_tables.

Параметр $5, упоминающийся в скрипте, как раз и есть тот ip-адрес шлюза на другом конце туннеля, что был в конфигурации ppp интерфейсов установлен в удобные на моей системе значения. Значение ip-адреса шлюза, не принадлежащее ни к одной из доступных на данной машине сетей, избавляет от хлопот по разведению траффика разных интерфейсов ppp и локальных сетей. В случае же автоматического назначения адресов шлюза подобное разведение траффика может являться весьма нетривиальной задачей, что хорошо известно пользователям Корбины, работающим в Linux.

<h4>Опускание ppp-соединения</h4>
При опускании любого ppp соединения у меня на машине отрабатываются скрипты /etc/ppp/ip-down.d/*, в частности, /etc/ppp/ip-down.d/90-local.sh:

<blockquote>
<pre>
#!/bin/bash

ip route del default

if [ $1 == "ppp0" ]; then
ip rule del from $4 lookup internet_golnet
ip route flush table internet_golnet
ip rule flush table internet_golnet
fi;

if [ $1 == "ppp1" ]; then
ip rule del from $4 lookup internet_corbina
ip route flush table internet_corbina
ip rule flush table internet_corbina
fi
</pre>
</blockquote>

Как видим, здесь, в зависимости от того, какой интерфейс опущен, чистится соответствующая таблица маршрутизации и удаляется правило её выбора.

<h4>Проверка обоих ppp соединений</h4>

Поднимем оба ppp-интерфейса:

<blockquote>
/etc/init.d/net.ppp0 start
/etc/init.d/net.ppp1 start
</blockquote>

Секунд через десять убедимся в их наличии и функционировании:

<blockquote>
<pre>
testcomp # ip address show up
17: ppp0: &lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&gt; mtu 1400 qdisc pfifo_fast qlen 3
link/ppp
inet 11.22.33.44 peer 172.1.1.1/32 scope global ppp0
18: ppp1: &lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&gt; mtu 1400 qdisc pfifo_fast qlen 3
link/ppp
inet 55.66.77.88 peer 172.1.1.2/32 scope global ppp1
</pre>
</blockquote>

Убедимся, что ya.ru (к примеру) пингуется с обоих интерфейсов:

<blockquote>
<pre>

testcomp # ping -c2 -I ppp0 ya.ru
PING ya.ru (213.180.204.8) from 11.22.33.44 ppp0: 56(84) bytes of data.
64 bytes from ya.ru (213.180.204.8): icmp_seq=1 ttl=60 time=20.6 ms
64 bytes from ya.ru (213.180.204.8): icmp_seq=2 ttl=60 time=11.5 ms

--- ya.ru ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 11.588/16.103/20.618/4.515 ms

testcomp # ping -c2 -I ppp1 ya.ru
PING ya.ru (213.180.204.8) from 55.66.77.88 ppp1: 56(84) bytes of data.
64 bytes from ya.ru (213.180.204.8): icmp_seq=1 ttl=58 time=2.68 ms
64 bytes from ya.ru (213.180.204.8): icmp_seq=2 ttl=58 time=2.81 ms

--- ya.ru ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 2.682/2.747/2.812/0.065 ms

</pre>
</blockquote>

Пропингуем с какого-либо компа, где у вас есть доступ в шелл, оба ваших ip:

<blockquote>
<pre>
guest $ ping -c2 11.22.33.44
PING 11.22.33.44 (11.22.33.44) 56(84) bytes of data.
64 bytes from 11.22.33.44: icmp_seq=0 ttl=38 time=209 ms
64 bytes from 11.22.33.44: icmp_seq=1 ttl=38 time=209 ms

--- 11.22.33.44 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 209.514/209.553/209.592/0.039 ms, pipe 2

guest $ ping -c2 55.66.77.88
PING 55.66.77.88 (55.66.77.88) 56(84) bytes of data.
64 bytes from 55.66.77.88: icmp_seq=0 ttl=53 time=205 ms
64 bytes from 55.66.77.88: icmp_seq=1 ttl=53 time=200 ms

--- 55.66.77.88 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 200.857/203.083/205.309/2.226 ms, pipe 2
</pre>
</blockquote>

<h4>Версии использованного программного обеспечения и ссылки</h4>

При отладке использовалось:

<ul>
<li>Операционная система GNU/Linux Gentoo
<li>Версия ядра 2.6.17
<li>iproute2 2.6.22.20070710
<li>ipcalc 0.41
<li>ppp 2.4.4-r13
<li>pptp 1.7.1
<li>dhcpcd 3.1.5
</ul>

Неоценимую помощь в поиске глюков pptp оказала ссылка на
<a href="http://pptpclient.sourceforge.net/howto-diagnosis.phtml">PPTP Client: Diagnosis HOWTO</a>.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.