Решено: iproute и 2 интерфеса

Обсуждение настройки и работы сервисов, резервирования, сетевых настроек и вопросов безопасности ОС для молодых и начинающих системных администраторов.

Модераторы: SLEDopit, Модераторы разделов

Enkil
Сообщения: 15

Решено: iproute и 2 интерфеса

Сообщение Enkil »

Извините за создание новой темы, если подобная уже была, но очень хочется решить уже этот вопрос!
Прошу помощи!
В продолжение
http://forum.ubuntu.ru/index.php?topic=60258.30

Постановка задачи

Код: Выделить всё

Имеем сервер с Ubuntu Server 9.04

3 интерфейса:
eth2: xxx.xxx.xxx.xxx - смотрит в локальную сеть
eth0: yyy.yyy.yyy.yyy - сморит в сеть провайдера Futers шлюз: yyy.yyy.yyy.yyy-1
eth3: zzz.zzz.zzz.zzz - смотрит в сеть роутера Dlink, который в свою очередь смотрит в сеть WebPlus(pppoe-соединение от роутера до WebPlus'а) шлюз: zzz.zzz.zzz.zzz-2

Futers провайдер в месте нахождения офиса единственный(кроме WebPlus'а), а посему жутко дорогой(хотя очень стабильный, за несколько лет упал 1 раз и то повине электриков ЖКС).
Телефония в офисе подключена через WebPlus.
Руководством было принято решение об использовании WebPlus также для создания второго канала доступа в и-нет, т.к. по стоимости он заметно дешевле Futers(WebPlus провел нам доплинию для и-нета), есть безлимитные тарифы для юрлиц за адекватные деньги.

На сервере 3 интерфеса - в один воткнут кабель от Futers, второй подключен к роутеру Dlink(тот в свою очередь подключен к WebPlus через pppoe) и третий подключен к хабу, к которому подключены компы локальной сети.

Задача
- Обеспечить выход в и-нет клиентам из локальной сети с распределением трафика как описано ниже
- Пустить трафик по портам 80, 8080, 443, 5190 через eth3(WebPlus), а 110 и 25(а также все что не подходит под eth3) через eth0(Futers).
- Организовать проброс входящих запросов по портам 80,444,443 на интерфейс 1го провайдера(Futers) на сервер с установленным и настроенным SBS(Small Bisness Server)
- Организовать возможность настройки почтовых клиентов не из локальной сети на работу с внутренним почтовым сервером(проброс запросов извне по портам 110 и 25)


Раньше был написан скрипт для одного внешнего интерфейса, теперь, основываясь на ваших работах я попробовал объединить то что было у меня раньше и ваш опыт для моих новых задач.

Сейчас скрипт выглядит так

создание таблиц

Код: Выделить всё

$ cat /etc/iproute2/rt_tables
#
# reserved values
#
255   local
254   main
253   default
0   unspec
#
# local
#
#1   inr.ruhep

10   T1   # это наши таблицы
11   T2   #


Сам скрипт

Код: Выделить всё

$ cat /etc/router

#!/bin/bash

echo "preparing routing tables"

# Описываем переменные, используемые в скрипте

IP_LOCAL1="xxx.xxx.xxx.xxx" # адрес нашего маршрутизатора в локальной сети.
IP_INET1="yyy.yyy.yyy.yyy" # адрес нашего маршрутизатора в сети Futers.
IP_INET2="zzz.zzz.zzz.zzz" # адрес нашего марщрутизатора в сети WebPlus.

IF_LOCAL1="eth2" # имя интерфейса на локальную сеть
IF_INET1="eth0" # имя интерфейса на Futers.
IF_INET2="eth3" # имя интерфейса на WebPlus.

NET_LOCAL1="xxx.xxx.xxx.0/24" # локальная сеть.
NET_INET1="yyy.yyy.yyy.0/30" # адрес сети в которой гейт Futers'а
NET_INET2="zzz.zzz.zzz.0/24" # адрес сети в которой гейт WebPlus'а(а точнее Dlink-роутер).

GW_INET1="yyy.yyy.yyy.yyy-1" # гейт Futers.
GW_INET2="zzz.zzz.zzz.zzz-2" # гейт WebPlus.

UNPRIPORTS="1024:65535" # Номера непривилегированных портов

# Настраиваем таблицы маршрутизации

ip route flush table T1         #обнуляем первую таблицу маршрутов
ip route flush table T2         #обнуляем вторую таблицу маршрутов

ip rule delete table T1      #удаляем наши таблицы, если они присутсвуют в текущей конфигурации (вдруг мы просто перезапускаем скрипт?)
ip rule delete table T2      #аналогично для второй.

ip rule delete table T1      #и делаем это два раза, так как у нас два правила на каждую таблицу.
ip rule delete table T2      #аналогично для второй.

ip route add $NET_LOCAL1 dev $IF_LOCAL1 src $IP_LOCAL1 table T1
ip route add $NET_INET1  dev $IF_INET1  src $IP_INET1  table T1
ip route add $NET_INET2  dev $IF_INET2  src $IP_INET2  table T1
ip route add 127.0.0.0/8 dev lo         table T1
ip route add default     via $GW_INET1  table T1

ip route add $NET_LOCAL1 dev $IF_LOCAL1 src $IP_LOCAL1 table T2
ip route add $NET_INET1  dev $IF_INET1  src $IP_INET1  table T2
ip route add $NET_INET2  dev $IF_INET2  src $IP_INET2  table T2
ip route add 127.0.0.0/8 dev lo   table T2
ip route add default     via $GW_INET2  table T2

ip route add $NET_INET1 dev $IF_INET1 src $IP_INET1      #заполняем основную таблицу адресов. сеть на Futers
ip route add $NET_INET2 dev $IF_INET2 src $IP_INET2      #заполняем основную таблицу адресов. сеть на WebPlus

# А вот это важно для понимания! если понять что происходит в следующих строчках - то можно настраивать любые правила маршрутизации.
ip rule add from $IP_INET1 table T1   #все пакеты от ip адреса первого провайдера маршрутизировать по таблице T1
ip rule add from $IP_INET2 table T2   #все пакеты от ip адреса второго провайдера маршрутизировать по таблице T2

ip rule add fwmark 10 table T1   #все пакеты, которые имеют метку 10 маршрутизировать по таблице T1
ip rule add fwmark 11 table T2   #все пакеты, которые имеют метку 11 маршрутизировать по таблицу T2

ip route del default
ip route add default via $GW_INET1  #заполняем основную таблицу адресов. дефолтный гейт

ip route flush cache      #ну и на последок очистить кеш

# 2 ip в интернете, на которые задаем маршруты вручную. Чтобы проверять работает инет на интерфейсах или нет.
route add -host 212.188.4.10  gw $GW_INET1 $IF_INET1
route add -host 195.34.32.116 gw $GW_INET2 $IF_INET2

echo "preparing iptables firewall"

## Настраиваем iptables(общие правила и параметры)

# Очистка таблиц и цепочек
iptables --flush
iptables --delete-chain
iptables --table nat --flush
iptables --table filter --flush
ptables --table mangle --flush
iptables --table nat --delete-chain
iptables --table filter --delete-chain
iptables --table mangle --delete-chain


# Назначение глобальных политик фаервола
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F INPUT
iptables -F OUTPUT
iptables -F FORWARD

# Загружаем модули, для корректной работы VPN, Active ftp, DCC  которые будут идти через NAT.
modprobe ip_nat_ftp
modprobe ip_nat_pptp
modprobe ip_conntrack_ftp

## Изменение параметров SYSCTL
# Включение форвардинга
echo 1 > /proc/sys/net/ipv4/ip_forward

# Включение форвардинга для VPN
echo 1 > /proc/sys/net/ipv4/ip_dynaddr

# Увеличение размера очередей
echo 32000000 > /proc/sys/net/ipv4/netfilter/ip_conntrack_max

# Время ожидания до закрытия соединения
echo 14400 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_established

# Время ожидания до посылки FIN пакета
echo 60 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_fin_wait

# Время ожидания до посылки FIN пакета
echo 10 > /proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_syn_sent

# Для защиты от syn флуда
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

# Увеличиваем размер backlog очереди
echo 1280 > /proc/sys/net/ipv4/tcp_max_syn_backlog

# Число начальных SYN и SYNACK пересылок для TCP соединения
echo 4 > /proc/sys/net/ipv4/tcp_synack_retries

echo 4 > /proc/sys/net/ipv4/tcp_syn_retries

# Сколько секунд ожидать приема FIN до полного закрытия сокета
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout

# Как часто посылать сообщение о поддержании keep alive соединения
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time

# Сколько пакетов проверки keepalive посылать, прежде чем соединение будет закрыто.
echo 2 > /proc/sys/net/ipv4/tcp_keepalive_probes
# Зaпрещаем TCP window scaling
echo 0 > /proc/sys/net/ipv4/tcp_window_scaling

# Запрещаем selective acknowledgements, RFC2018
#echo 0 > /proc/sys/net/ipv4/tcp_sack

# Запрещаем TCP timestamps, RFC1323
#echo 0 > /proc/sys/net/ipv4/tcp_timestamps

# Уличиваем размер буфера для приема и отправки данных через сокеты.
echo 1048576 > /proc/sys/net/core/rmem_max
echo 1048576 > /proc/sys/net/core/rmem_default
echo 1048576 > /proc/sys/net/core/wmem_max
echo 1048576 > /proc/sys/net/core/wmem_default

# Через какое время убивать соединение закрытое на нашей стороне
echo 1 > /proc/sys/net/ipv4/tcp_orphan_retries

## Настраиваем распределение трафика
## Трафик по 80,8080,443(веб различный) и 5190(аська) метим меткой 11(это на WebPlus)
#iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp -m multiport --dport 80,8080,443,5190  -j MARK --set-mark 11
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 80  -j MARK --set-mark 11
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 80 -j RETURN
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 8080  -j MARK --set-mark 11
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 8080 -j RETURN
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 443  -j MARK --set-mark 11
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 443 -j RETURN
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 5190  -j MARK --set-mark 11
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 5190 -j RETURN

##трафик по 110,25(почта), а также весь, неописанный выше, метим меткой 10(это на Futers)
#iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp -m multiport --dport 110,25  -j MARK --set-mark 11
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 110  -j MARK --set-mark 10
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 110 -j RETURN
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 25  -j MARK --set-mark 10
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -p tcp --dport 25 -j RETURN
iptables -t mangle -A PREROUTING  -s $NET_LOCAL1 -j MARK --set-mark 10


# Порты NETBIOS :
iptables -A INPUT -p tcp --destination-port 445 -j DROP
iptables -A INPUT -p tcp --destination-port 135 -j DROP
iptables -A INPUT -p udp -m multiport  --ports 135,136,137,138,139 -j DROP
iptables -A INPUT -p tcp -m multiport  --ports 135,136,137,138,139 -j DROP
iptables -A FORWARD -p udp -m multiport  --ports 135,136,137,138,139,445 -j ACCEPT # Разрешаем форвард NetBIOS
iptables -A FORWARD -p tcp -m multiport  --ports 135,136,137,138,139,445 -j ACCEPT # чтобы при включенном vpn работали общие папки

# Блокируем входящие пакеты с локальными IP адресами приходящие на внешние интерфейсы
iptables -A INPUT -p tcp -i $IF_INET1 -s $NET_LOCAL1 -j DROP
iptables -A INPUT -p tcp -i $IF_INET2 -s $NET_LOCAL1 -j DROP
# Блокируем входящие пакеты c нелокальными IP на внутреннем интерфейсе
iptables -A INPUT -p tcp -i $IF_LOCAL1 -s ! $NET_LOCAL1 -j DROP


# Защищаемся от Stealth Scans
# Очищаются все биты
iptables -A INPUT -p icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

# SYN and FIN are both set
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP

# SYN and RST are both set
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

# FIN and RST are both set
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP

# FIN is the only bit set, without the expected accompanying ACK
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP

# PSH is the only bit set, without the expected accompanying ACK
iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j DROP

# URG is the only bit set, without the expected accompanying ACK
iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j DROP

# Разрешаем cups
iptables -A INPUT -i $IF_LOCAL1 -p tcp --dport 631 -j ACCEPT

# закрываем APACHE снаружи и открываем изнутри(все сайты(их несколько - и влом на каждом прописывать Allow From) веб-сервера доступены только из локальной

сети)
iptables -A INPUT -p tcp -i $IF_INET1  -m multiport  --ports 80,8080,443 -j DROP
iptables -A INPUT -p tcp -i $IF_INET2  -m multiport  --ports 80,8080,443 -j DROP
iptables -A INPUT -p tcp -i $IF_LOCAL1  -m multiport  --ports 80,8080,443 -j ACCEPT

# Разрешаем все ранее запрошенные/установленные соединения
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -i ! $IF_INET1 -j ACCEPT
iptables -A INPUT -m state --state NEW -i ! $IF_INET2 -j ACCEPT
iptables -A FORWARD -i $IF_INET1 -o $IF_LOCAL1 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i $IF_INET2 -o $IF_LOCAL1 -m state --state ESTABLISHED,RELATED -j ACCEPT

# Разрешаем прохождение пакетов по интерфейсу обратной петли
iptables -A INPUT -i lo -j ACCEPT

# Statistics and auths for customers, ping tests
for net_ips in $NET_LOCAL1; do

iptables -A INPUT -p icmp -i $IF_LOCAL1 --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp -i $IF_INET1 --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp -i $IF_INET2 --icmp-type echo-request -j ACCEPT

done


## Настраиваем iptables(не распределение траффика, а ограничения и опубликовывания серверов)
# Открываем нужные нам порты.

#Траффик на сквид(для интерфейса WebPlus)
#iptables -t nat -A PREROUTING -i $IP_INET2 -d ! $NET_LOCAL1 -p tcp -m multiport --dport 80,8080 -j DNAT --to $IP_LOCAL2:3128

# DNS сервер имен разрешаем.
iptables -A OUTPUT -p udp -m udp -o $IF_INET1 --dport 53 --sport $UNPRIPORTS -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp -o $IF_INET1 --dport 53 --sport $UNPRIPORTS -j ACCEPT
iptables -A INPUT -p udp -m udp -i $IF_INET1 --dport $UNPRIPORTS --sport 53 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -i $IF_INET1 --dport $UNPRIPORTS --sport 53 -j ACCEPT

iptables -A OUTPUT -p udp -m udp -o $IF_INET2 --dport 53 --sport $UNPRIPORTS -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp -o $IF_INET2 --dport 53 --sport $UNPRIPORTS -j ACCEPT
iptables -A INPUT -p udp -m udp -i $IF_INET2 --dport $UNPRIPORTS --sport 53 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -i $IF_INET2 --dport $UNPRIPORTS --sport 53 -j ACCEPT

# FTP
iptables -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT

# PASSIVE FTP
iptables -t filter -A INPUT -p tcp -m tcp --dport 50000:50500 -m state --state NEW -j ACCEPT
iptables -t filter -A INPUT -p udp -m udp --dport 50000:50500 -m state --state NEW -j ACCEPT

# Разрешаем VPN для определенных адресов и запрещаем остальным
iptables -A INPUT -s 93.157.124.11 -i $IF_INET1 -p tcp --dport 1723 -j ACCEPT
iptables -A INPUT -s 91.204.149.84 -i $IF_INET1 -p tcp --dport 1723 -j ACCEPT
iptables -A INPUT -i $IF_INET1 -p tcp --dport 1723 -j DROP

iptables -A INPUT -s 93.157.124.11 -i $IF_INET2 -p tcp --dport 1723 -j ACCEPT
iptables -A INPUT -s 91.204.149.84 -i $IF_INET2 -p tcp --dport 1723 -j ACCEPT
iptables -A INPUT -i $IF_INET2 -p tcp --dport 1723 -j DROP

# Разрешаем доступ к pptp-серверу для всех
#iptables -A INPUT -p tcp --dport 1723 -m state --state NEW -j ACCEPT

# Разрешаем доступ по ssh на внешние интерфейсы только с определенных адресов, с остальных закрываем
iptables -A INPUT -s 93.157.124.11 -i $IF_INET1 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -i $IF_INET1 -p tcp --dport 22 -j DROP

iptables -A INPUT -s 93.157.124.11 -i $IF_INET2 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -i $IF_INET2 -p tcp --dport 22 -j DROP

# Разрешаем работу почтовых клиентов(учитываем, что почтовый траффик идет у нас через Futers, т.е. eth0, IF_INET1)
iptables -A INPUT -i $IF_INET1 -p tcp --dport 110 -j ACCEPT
iptables -A INPUT -i $IF_INET1 -p tcp --dport 25 -j ACCEPT
#iptables -A INPUT -i $IF_INET2 -p tcp --dport 110 -j ACCEPT
#iptables -A INPUT -i $IF_INET2 -p tcp --dport 25 -j ACCEPT
iptables -A INPUT -i $IF_LOCAL1 -p tcp --dport 110 -j ACCEPT
iptables -A INPUT -i $IF_LOCAL1 -p tcp --dport 25 -j ACCEPT

# Форвард 25 порта на MS Exchange 2003(SBS)
iptables -t nat -A PREROUTING -p tcp -d $IP_INET1 --dport 25 -j DNAT --to-destination 192.168.0.110:25
iptables -A FORWARD -i $IF_INET1 -d 192.168.0.110 -p tcp --dport 25 -j ACCEPT
#iptables -A FORWARD -i $IF_INET2 -d 192.168.0.110 -p tcp --dport 25 -j ACCEPT

# Форвард 110 порта на MS Exchange 2003(SBS)

iptables -t nat -A PREROUTING -p tcp -d $IP_INET1 --dport 110 -j DNAT --to-destination 192.168.0.110:110
iptables -t FORWARD -i $IF_INET1 -d 192.168.0.110 -p tcp --dport 110 -j ACCEPT
#iptables -t FORWARD -i $IF_INET2 -d 192.168.0.110 -p tcp --dport 110 -j ACCEPT

# Форвард Рабочего места SBS
iptables -t nat -A PREROUTING -p tcp -d $IP_INET1 --dport 80 -j DNAT --to-destination 192.168.0.110:80
iptables -t nat -A PREROUTING -p tcp -d $IP_INET1 --dport 443 -j DNAT --to-destination 192.168.0.110:443
iptables -t nat -A PREROUTING -p tcp -d $IP_INET1 --dport 444 -j DNAT --to-destination 192.168.0.110:444
iptables -A FORWARD -i $IF_INET1 -d 192.168.0.110 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -i $IF_INET1 -d 192.168.0.110 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -i $IF_INET1 -d 192.168.0.110 -p tcp --dport 444 -j ACCEPT

iptables -t nat -A PREROUTING -p tcp -d $IP_INET2 --dport 80 -j DNAT --to-destination 192.168.0.110:80
iptables -t nat -A PREROUTING -p tcp -d $IP_INET2 --dport 443 -j DNAT --to-destination 192.168.0.110:443
iptables -t nat -A PREROUTING -p tcp -d $IP_INET2 --dport 444 -j DNAT --to-destination 192.168.0.110:444
iptables -A FORWARD -i $IF_INET2 -d 192.168.0.110 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -i $IF_INET2 -d 192.168.0.110 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -i $IF_INET2 -d 192.168.0.110 -p tcp --dport 444 -j ACCEPT


## Включаем маскарадинг(даем доступ в инет клиентам локальной сети)
iptables -A FORWARD -i $IF_INET1 -o $IF_LOCAL1 -s $Net_LOCAL1 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -A FORWARD -i $IF_INET2 -o $IF_LOCAL1 -s $Net_LOCAL1 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

#iptables -t nat -A POSTROUTING -o $IF_INET1 -j MASQUERADE
#iptables -t nat -A POSTROUTING -o $IF_INET2 -j MASQUERADE

iptables -t nat -A POSTROUTING -o $IF_INET1 -s $NET_LOCAL1 -j SNAT --to-source $IP_INET1
iptables -t nat -A POSTROUTING -o $IF_INET2 -s $NET_LOCAL1 -j SNAT --to-source $IP_INET2

# Закрываем известные троянские порты:
iptables -A FORWARD -p udp -m multiport --sport 16355,21111,1349,26274,29891,31337,31338,47262 -j DROP

iptables -A FORWARD -p tcp -m multiport --sport 555,666,1001,1025,1026,1028,1243,2000,5000,6667,6670,6711,6969,7000,12345,123456
,21554,22222,27374,29559,31337,31338 -j DROP

exit 0


Возникли следующие вопросы, просьба помочь по возможности

Код: Выделить всё

- Куда правильно в скрипте воткнуть блок, в котором iptables устанавливает метки пакетам?
- Работоспособен ли скрипт в подобном виде?(ранее этот же скрипт работал без проблем для одного внешнего интерфейса, сейчас кроме добавления настройки маршрутизации и меток пакетов, изменена немного работа iptables, точнее распространена на 2ой внешний интерфейс)
- Как можно оптимизировать данный скрипт?

Заодно может кому нибудь поможет такая реализация как у меня=))))
Буду очень благодарен откликнувшимся, если ктото из тех кто поможет из Питера - с удовольствием обеспечу совместное распитие пива после удачного запуска скрипта))))
Спасибо сказали:
Simamura
Сообщения: 26

Re: Решено: iproute и 2 интерфеса

Сообщение Simamura »

Еси я все правильно понял тебе подойдет ето.
Настройка линукс маршрутизатора через iptables + iproute2 на два (и
больше) внешних интерфейса.

Предполагается:

- то вы уже знакомы с понятием маршрутизации и ната.
- теоретически понимаете как работает нат, что такое маршрутизация и
файрвол, но не знаете как это реализовать на вашей системе.


Имеется:

- две входящие сетевые соски от двух разных провайдеров.
- локальная сеть
- три сетевых интерфейса на маршрутизаторе.


Задача:

Объеденить всех пользователей в одну локальную сеть и пускать одних
пользователей в интернет через одного провайдера, других - через
другого.

В рассматриваемом примере, все пользователи в локальной сети будут
находиться в сети 172.16.0.0/16, при этом пользователей из подсети
172.16.0.0/24 надо пропускать в интернет через первого провайдера, а
пользователей 172.16.1.0/24 - через второго.

Будем использовать iproute2 для таблиц маршуризации и iptables для ната.

Обозначим:

$IP_LOCAL="172.16.0.1" - адрес нашего маршрутизатора в локальной сети.
$IP_INET1="1.1.1.2" - адрес нашего маршрутизатора в сети первого провайдера.
$IP_INET2="2.2.2.2" - адрес нашего марщрутизатора в сети второго провайдера.

$IF_LOCAL="eth0" - имя интерфейса на локальную сеть
$IF_INET1="eth1" - имя интерфейса на первого провайдера.
$IF_INET2="eth2" - имя интерфейса на второго провайдера.

$NET_LOCAL="172.16.0.0/16" - локальная сеть.
$NET_INET1="1.1.1.0/24" - адрес сети в которой гейт нашего первого провайдера.
$NET_INET2="2.2.2.0/24" - адрес сети в которой гейт нашего второго провайдера.
$NET_SUB1="172.16.0.0/24" - подсеть пользователей на первого провайдера
$NET_SUB2="172.16.1.0/24" - подсеть пользователей на второго провайдера

$GW1="1.1.1.1" - гейт первого провайдера.
$GW2="2.2.2.1" - гейт второго провайдера.


Настраиваем статические адреса на сетевые карты.

Debian (ubuntu) хранит настройки в файле

/etc/network/interfaces.


пишем:

auto lo
iface lo inet loopback

#local
auto eth0
iface eth0 inet static
address 172.16.0.1
netmask 255.255.0.0
network 172.15.0.0
broadcast 172.16.255.255

#inet 1
auto eth1
iface eth1 inet static
address 1.1.1.2
netmask 255.255.255.0
gateway 1.1.1.1
network 1.1.1.0
broadcast 1.1.1.255

#inet 2
auto eth2
iface eth2 inet static
#если надо - меняем мак адреса
# pre-up ifconfig eth2 hw ether aa:bb:cc:cc:bb:aa
address 2.2.2.2
netmask 2.2.2.0
# себе я второй гейт не прописываю, в следствии чего сам маршрутизатор ходит в инет через первый инет
# gateway 2.2.2.1
network 2.2.2.0
broadcast 2.2.2.255


тем самым мы сказали, что все сетвые у нас имеют статические адреса, и
указали их.


Настаиваем маршрутизацию с утилитой ip.

Утилита route позволяет нам обратиться к таблице маршртизации.

Сила утилиты ip в том, что она позволяет создать большое количество
таблиц для самых разных потребностей, а так же, способна считывать
флаги, которые расставляет файрвол iptables (об этом ниже) и на их
основе тоже делать какие-то действия.

Основа маршрутизации через разные таблицы - правила (rule)

А сила различных таблиц в том, что мы можем хранить огромное количество
различных таблиц маршрутизации, через которые и будем пропускать пакеты.

Просмотреть список уже имеющихся таблиц можно командой

ip rule list

0: from all lookup 255
32766: from all lookup main
32767: from all lookup default


Мы видим, что у нас есть три правила: таблица 255, main и default.
То, что выдает нам route - хранится в таблице main, что можно увидеть командой

ip route list table main


В качестве номеров таблиц можно использовать цифры, ( пример: 0: from
all lookup 255 ), а можно прописать на эти цифры какие-то более понятные
простым смертным имена ( пример: 32766: from all lookup main ).

Так что обозначим свои таблицы:

Редактируем файл

/etc/iproute2/rt_tables


и добавляем туда записи вида:

#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep

10 T1
20 T2


номер - это то самое число, которое мы можем использовать если не
именовать таблицы, а строковое значение - то, что мы в действительности
будем использовать. (кстати, тут же мы видим и уже встречавшиеся нам в
списке правил таблицы)

Теперь создаем некий скрипт, который в последствии будет все нам
прописывать при старте системы.

Понятное дело, что каждый использует свой любимый редактор =)

/etc/init.d/route


#!/bin/sh

IP_LOCAL="172.16.0.1" # адрес нашего маршрутизатора в локальной сети.
IP_INET1="1.1.1.2" # адрес нашего маршрутизатора в сети первого провайдера.
IP_INET2="2.2.2.2" # адрес нашего марщрутизатора в сети второго провайдера.

IF_LOCAL="eth0" # имя интерфейса на локальную сеть
IF_INET1="eth1" # имя интерфейса на первого провайдера.
IF_INET2="eth2" # имя интерфейса на второго провайдера.

NET_LOCAL="172.16.0.0/16" # локальная сеть.
NET_INET1="1.1.1.0/24" # адрес сети в которой гейт нашего первого провайдера.
NET_INET2="2.2.2.0/24" # адрес сети в которой гейт нашего второго провайдера.

GW1="1.1.1.1" # гейт первого провайдера.
GW2="2.2.2.1" # гейт второго провайдера.

ip route flush table T1 #обнуляем первую таблицу маршрутов
ip route flush table T2 #обнуляем вторую таблицу маршрутов

ip route add $NET_INET1 dev $IF_INET1 src $IP_INET1 table T1 #закидываем в первую таблицу инфу о сети первого провайдера
ip route add $NET_LOCAL dev $IF_LOCAL table T1 #закидываем в первую таблицу инфу о том, что у нас существует локальная сеть
ip route add $NET_INET2 dev $IF_INET2 table T1 #закидываем в первую таблицу инфу о том, что у нас существует еще одна сеть
ip route add 127.0.0.0/8 dev lo table T1 #закидываем в первую таблицу инфу о существовании лупбека
ip route add default via $GW_INET1 table T1 #закидываем в первую таблицу дефолтный гейт на первого провайдера

ip route add $NET_INET2 dev $IF_INET2 src $IP_INET2 table T2 #закидываем во вторую таблицу инфу о сети второго провайдера
ip route add $NET_LOCAL dev $IF_LOCAL table T2 #закидываем во вторую таблицу инфу о том, что у нас существует локальная сеть.
ip route add $NET_INET1 dev $IF_INET1 table T2 #закидываем во вторую таблицу инфу о том, что у нас существует еще одна сеть.
ip route add 127.0.0.0/8 dev lo table T2 #закидываем во вторую таблицу инфу о существовании лупбека.
ip route add default via $GW_INET2 table T2 #закидываем во вторую таблицу дефолтный гейт на второго провайдера

ip route add $NET_INET1 dev $IF_INET1 src $IP_INET1 #заполняем основную таблицу адресов. сеть на первого провайдера
ip route add $NET_INET2 dev $IF_INET2 src $IP_INET2 #заполняем основную таблицу адресов. сеть на второго провайдера

ip route add default via $GW_INET1 #заполняем основную таблицу адресов. дефолтный гейт.

ip rule delete table T1 #удаляем наши таблицы, если они присутсвуют в текущей конфигурации (вдруг мы просто перезапускаем скрипт?)
ip rule delete table T2 #аналогично для второй.
ip rule delete table T1 #и делаем это два раза, так как у нас два правила на каждую таблицу.
ip rule delete table T2 #аналогично для второй.

#а вот это важно для понимая! если понять что происходит в следующих строчках - то можно настраивать любые правила маршрутизации.

ip rule add from $IP_INET1 table T1 #все пакеты от ip адреса первого провайдера маршрутизировать по таблице T1
ip rule add from $IP_INET2 table T2 #все пакеты от ip адреса второго провайдера маршрутизировать по таблице T2

ip rule add fwmark 10 table T1 #все пакеты, которые имеют метку 10 маршрутизировать по таблице T1
ip rule add fwmark 11 table T2 #все пакеты, которые имеют метку 11 маршрутизировать по таблицу T2

ip route flush cache #ну и на последок очистить кеш

exit 0




В целом, понятно все, за исключением одного вопроса - что же это за
метка такая в последних строчках?

Тут мы обращаемся к утилите iptables.

Краткая теория. (полную и на русском языке можно, а вообще-то, даже
нужно, читать тут http://www.opennet.ru/docs/RUS/iptables/ )

Утилита iptables так же основана на таблицах. только таблиц в ней
фиксированно - три.

mangles - таблица используется для изменений заголовков пакетов.
filter - самая наша основаная таблица для файрвола - тут мы производим все блокировки, разрешения.
nat - таблица, как понятно из названия для ната.

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

Когда паркт попадает на интерфейс, и, его ловит iptables, то он проходит
следующие таблицы и цепочки, важные для нас:

1. таблица mangle цепочка PREROUTING
2. обработка маршрутизации.
3. таблица nat цепочка POSTROUTING
(в действительно пакет проходит еще и через другие таблицы и цепочки,
но, для планируемой маршрутизации они нафик не сдались - изучение этого
вопроса уже полностью на вашей совести =) ).

Скрипт для маршрутизации:

/etc/init.d/iptables


#!/bin/sh

IP_LOCAL="172.16.0.1" # адрес нашего маршрутизатора в локальной сети.
IP_INET1="1.1.1.2" # адрес нашего маршрутизатора в сети первого провайдера.
IP_INET2="2.2.2.2" # адрес нашего марщрутизатора в сети второго провайдера.

IF_LOCAL="eth0" # имя интерфейса на локальную сеть
IF_INET1="eth1" # имя интерфейса на первого провайдера.
IF_INET2="eth2" # имя интерфейса на второго провайдера.

NET_LOCAL="172.16.0.0/16" # локальная сеть.
NET_INET1="1.1.1.0/24" # адрес сети в которой гейт нашего первого провайдера.
NET_INET2="2.2.2.0/24" # адрес сети в которой гейт нашего второго провайдера.
NET_SUB1="172.16.0.0/24" # подсеть пользователей на первого провайдера
NET_SUB2="172.16.1.0/24" # подсеть пользователей на второго провайдера

GW1="1.1.1.1" # гейт первого провайдера.
GW2="2.2.2.1" # гейт второго провайдера.

IPT="/sbin/iptables"

$IPT -t nat -F #очищаем таблицу nat
$IPT -t mangle -F #очищаем таблицу mangle

#все пакеты, которые попали в цепочку PREROUTING таблицы mangle обрабатываем по двум правилам:
$IPT -t mangle -A PREROUTING -s $NET_SUB1 -d ! $NET_LOCAL -j MARK --set-mark 10 # все пакеты которые идут от $NET_SUB1 и не в $NET_LOCAL маркируем меткой 10
$IPT -t mangle -A PREROUTING -s $NET_SUB2 -d ! $NET_LOCAL -j MARK --set-mark 11 # все пакеты которые идут от $NET_SUB1 и не в $NET_LOCAL маркируем меткой 10

#все пакеты, которые попали в цепочку POSTROUTING таблицы nat обрабатываем по двум правилам:
$IPT -t nat -A POTROUTING -m mark --mark 10 -j MASQUERADE # натим все пакеты которые имеют метку 10
$IPT -t nat -A POTROUTING -m mark --mark 11 -j MASQUERADE # натим все пакеты которые имеют метку 11

exit 0




И так, что же происходит.

Пусть адрес пользователя 172.16.0.2

У пользователя прописан дефолтный гейт 172.16.0.1 - т.е. все пакеты
которые направлены не в локальную сеть пойдут туда.

На наш маршрутизатор приходит пакет от 172.16.0.2 и на адрес (к примеру) 4.4.4.4

1. пакет попадает в таблицу mangle в цепоку PREROUTING и там по правилу
"все пакеты от $NET_SUB1 и не в $NET_LOCAL" маркируется меткой 10 и
попускается дальше.

2. пакет попадает в правила маршрутизации и обрабатывается по правилу
"все пакеты, которые имеют метку 10 маршрутизировать по таблице T1".
попав в эту таблицу маршрутизатор отправляет пакет в дефолтный гейт для
этой таблицы, т.к. адрес 4.4.4.4 не подходит ни под одну сеть, которые
есть в этой таблице.

3. пакет попадает в таблицу nat в цепочку POSTROUTING и там по правилу
"натим все пакеты которые имеют метку 10" натится наружу.

Важный момент: метка пакета существует только внутри нашего
марщрутизатора. выходящий пакет уже не имеет меток.

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

В целом, все =)

Осталось только сделать наши скрипты исполняемыми и закинуть их на
автозагрузку.

Важно обратить внимание, что данный маршрутизатор будет маршрутизировать
пакеты в обе стороны, так что если кто-то из внешних сетей пропишет себе
ip нашей локальной сети, и укажет в качестве маршрутизатора ip нашего
маршрутизатора - он спокойно попадет к нам.
Спасибо сказали:
Enkil
Сообщения: 15

Re: Решено: iproute и 2 интерфеса

Сообщение Enkil »

вы правильно поняли, по этой инструкции и настраивал.
но нет уверенности в работоспособности скрипта, поэтому прошу более опытных посмотреть=))
просто кроме распределения траффика стоят и иные задачи и вот надо понять будет ли все это в связке работать и надо ли чтото менять в текущем виде скрипта.
к сожалению нет тестового сервера для проверки, а на боевом запускать стремно))
Спасибо сказали:
IMB
Сообщения: 2567
ОС: Debian

Re: Решено: iproute и 2 интерфеса

Сообщение IMB »

Enkil писал(а):
12.11.2009 19:00
к сожалению нет тестового сервера для проверки, а на боевом запускать стремно))

А Вы выполнение команд замените их отображением, вот и отследите логику, также не помешает заменить #!/bin/sh на #!/bin/sh -x. А запустить всё равно придётся, ошибки синтаксиса подчас только так и можно отловить.
Спасибо сказали:
Enkil
Сообщения: 15

Re: Решено: iproute и 2 интерфеса

Сообщение Enkil »

#!/bin/sh -x.

это для просмотра отработки каждой отдельно взятой команды?
Спасибо сказали:
Enkil
Сообщения: 15

Re: Решено: iproute и 2 интерфеса

Сообщение Enkil »

может кто нибудь в общем сказать работоспособен ли скрипт по поставленным задачам?
ошибки синтаксиса естественно будут выявлены при запуске, интересует общая картина
Спасибо сказали:
ALexhha
Сообщения: 109

Re: Решено: iproute и 2 интерфеса

Сообщение ALexhha »

На виртуалках тренируйся
Спасибо сказали:
Enkil
Сообщения: 15

Re: Решено: iproute и 2 интерфеса

Сообщение Enkil »

Спасибо за дельный совет=)))
ног лучше бы по теме.
на виртуалках что б ренироваться придется кучу времени потратить на подготовку самой виртуальной сети, а времени нет.
в общем все уже проверено, все работает
Спасибо сказали: