Добрый день коллеги!
Хотелось поговорить на тему маршрутизации в Linux, с применением маркировки пакетов "Mangle"! Так как наткнулся на некоторые сложности. Вопрос! Раз в 1-2 дня интерфейс eth0 перестает работать в таком типе маршрутизации.
В качестве ОС: Centos 6.9 (выбрана по строгой просьбе разработчиков для их спец. софта)
eth0 - этот интерфейс смотрит в WAN, имеет внешний IP адрес, он настроен статически, должен отправлять ответы на входящие пакеты по какому пришли запросы т.е. через eth0 (на шлюз этого интерфейса XX.XX.XX.49/28).
eth1 - этот интерфейс смотрит в LAN, получает локальный адрес по DHCP, через этот интерфейс будет ходить специальный трафик веб-приложения и другой (обновления ОС, скачивание программ и т.п.).
Проще говоря: нам нужно избавиться от лишнего трафика на интерфейсе eth0 и разрешить только веб трафик.
Схема прилагается:
Показать
Посмотрим конфигурацию сети: ifconfig
Показать
[root@XX-XX-XX-52 ~]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:32:35:0A
inet addr:XX.XX.XX.52 Bcast:176.112.66.63 Mask:255.255.255.240
inet6 addr: fe80::20c:29ff:fe32:350a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:23971 errors:0 dropped:0 overruns:0 frame:0
TX packets:1123 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2348758 (2.2 MiB) TX bytes:47470 (46.3 KiB)
eth1 Link encap:Ethernet HWaddr 00:0C:29:32:35:14
inet addr:192.168.1.23 Bcast:10.100.100.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe32:3514/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:82819 errors:0 dropped:0 overruns:0 frame:0
TX packets:37082 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:26540606 (25.3 MiB) TX bytes:13099073 (12.4 MiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:51 errors:0 dropped:0 overruns:0 frame:0
TX packets:51 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:4488 (4.3 KiB) TX bytes:4488 (4.3 KiB)
Ближе к делу
Для решения этой задачи я решил воспользоваться фунцией маркировки пакетов "mangle", т.е. маркировать все что приходит с eth0 и запихивать обратно в eth0, а по умолчанию шлюз сделать eth1 с локальным адресом 192.168.1.1
Шаг 1
Добавляю новую таблицу для запросов из интернета (для интерфейса eth0) в конец документа: /etc/iproute2/rt_tables
Выполняю в командной строке Linux:
echo 200 inet_zapros >> /etc/iproute2/rt_tablesПосмотрим что получилось: cat /etc/iproute2/rt_tables
Показать
cat /etc/iproute2/rt_tables
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
200 inet_zapros
Шаг 2
Чтобы ответы на пакеты уходили по тому же интерфейсу по какому пришёл запрос! Для начала нам нужно выполнить маркировку, т.е. пометить входящий трафик на eth0. Включаю маркировку пакетов INPUT:
iptables -t mangle -I INPUT -i eth0 -j CONNMARK --set-mark 0x1А на исходящий трафик восстановить метку пакету, из метки всего соединения, заданного CONNMARK (но я честно немного сомневаюсь в правильности этого хода).
iptables -t mangle -I OUTPUT -j CONNMARK --restore-markШаг 3
Запихиваю ответы обратно в eth0 -> т.е. назначаю таблицу маршрутизации (с именем inet_zapros упомянутая в Шаге 1 /etc/iproute2/rt_tables) с меткой 0x1:
ip route add default dev eth0 table inet_zapros
ip rule add fwmark 0x1 lookup inet_zaprosКак упоминают в некоторых статьях, о возможной необходимости сбросить кеш, сбросим:
ip route flush cacheИ ребутнем сеть:
service network restartШаг 4
Отключаю Forwarding и rp_filter в sysctl.conf
Показать
# Controls IP packet forwarding
net.ipv4.ip_forward = 0
# Controls source route verification
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.eth0.rp_filter = 0
net.ipv4.conf.eth1.rp_filter = 0
net.ipv4.conf.all.rp_filter=0Чтобы изменения вступили в силу, выполняю:
sysctl -pВидим нолики, все Ок!
Показать
[root@ХХ-ХХ-ХХ-52 ~]# sysctl -p
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.eth0.rp_filter = 0
net.ipv4.conf.eth1.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296Проверка на корректное отключение Forwarding и rp_filter:
[root@ХХ-ХХ-ХХ-52 ~]# cat /proc/sys/net/ipv4/conf/default/forwarding
0
[root@ХХ-ХХ-ХХ-52 ~]# cat /proc/sys/net/ipv4/conf/eth0/rp_filter
0Шаг 5
Добавим правило FireWall:
iptables -t mangle -A OUTPUT -m mark ! --mark 0x1 -j ACCEPT
service iptables save
service iptables restartШаг 6
Посмотрим на нашу маршуртизацию:
Показать
[root@ХХ-ХХ-ХХ-52~]# ip ro
ХХ.ХХ.ХХ.48/28 dev eth0 proto kernel scope link src ХХ.ХХ.ХХ.52
192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.23
169.254.0.0/16 dev eth0 scope link metric 1002
169.254.0.0/16 dev eth1 scope link metric 1003
default via 192.168.1.1 dev eth1Гип-гип, Ура!
И во истину, кажется все работает так как нужно! eth0 отвечает на пакеты из интернета! По дефолту весь трафик с виртуальной машины идет через локальный шлюз интерфейса eth1
Рано радуемся! Ибо неведомые грабли Внимание вопрос :)
На интерфейсе eth0 раз в 1-2 дня отваливается сеть, проблема решается ребутом виртуальной машинки (программная перезагрузка сетевых интерфейсов service network restart проблему не решает):
Показать
[root@XX-XX-XX-52 ~]# service network restart
Shutting down interface eth0: [ OK ]
Shutting down interface eth1: [ OK ]
Shutting down loopback interface: [ OK ]
Bringing up loopback interface: [ OK ]
Bringing up interface eth0: Determining if ip address XX.XX.XX.52 is already in use for device eth0...
[ OK ]
Bringing up interface eth1:
Determining IP information for eth1... done.
[ OK ]