У меня есть сервер Ubuntu 12.04 (последняя бета, последняя версия) с двумя настроенными сетевыми интерфейсами:
root@mac:/home/sysadm# ifconfig
eth0 Link encap:Ethernet HWaddr 00:1e:4f:28:fd:7b
inet addr:172.18.8.10 Bcast:172.18.8.255 Mask:255.255.255.0
inet6 addr: fe80::21e:4fff:fe28:fd7b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3362 errors:0 dropped:0 overruns:0 frame:0
TX packets:8561 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:273506 (273.5 KB) TX bytes:3174766 (3.1 MB)
Interrupt:38 Memory:dc000000-dc012800
eth4 Link encap:Ethernet HWaddr 00:02:c9:09:a4:c8
inet addr:xxx.yy.4.235 Bcast:xxx.yy.5.255 Mask:255.255.254.0
inet6 addr: fe80::202:c9ff:fe09:a4c8/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:59277 errors:0 dropped:52 overruns:0 frame:0
TX packets:34 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5138237 (5.1 MB) TX bytes:6462 (6.4 KB)
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:16436 Metric:1
RX packets:1412 errors:0 dropped:0 overruns:0 frame:0
TX packets:1412 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:107356 (107.3 KB) TX bytes:107356 (107.3 KB)
root@mac:/home/sysadm# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.18.8.254 0.0.0.0 UG 100 0 0 eth0
xxx.yy.4.0 0.0.0.0 255.255.254.0 U 0 0 0 eth4
172.18.8.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
Как видите, eth0 находится в сети 172.18.8.0/24 («8-net»), а eth4 - в сети xxx.yy.4.0 / 23 («4-net»). Обе эти сети связаны через маршрутизатор. Многие машины находятся в обеих сетях (по одной) и могут без проблем обмениваться данными. Когда вторая машина в 4-сети пытается связаться с 172.18.8.10, пакеты кажутся отброшенными. Tcpdump попытки SSH ниже:
root@mac:/home/sysadm# ufw allow from any to any port 1022
Rule added
Rule added (v6)
root@mac:/home/sysadm# sshd -de -p 1022
sshd re-exec requires execution with an absolute path
root@mac:/home/sysadm# which sshd
/usr/sbin/sshd
root@mac:/home/sysadm# /usr/sbin/sshd -de -p 1022
debug1: sshd version OpenSSH_5.9p1 Debian-5ubuntu1
debug1: read PEM private key done: type RSA
debug1: Checking blacklist file /usr/share/ssh/blacklist.RSA-2048
debug1: Checking blacklist file /etc/ssh/blacklist.RSA-2048
debug1: private host key: #0 type 1 RSA
debug1: read PEM private key done: type DSA
debug1: Checking blacklist file /usr/share/ssh/blacklist.DSA-1024
debug1: Checking blacklist file /etc/ssh/blacklist.DSA-1024
debug1: private host key: #1 type 2 DSA
debug1: read PEM private key done: type ECDSA
debug1: Checking blacklist file /usr/share/ssh/blacklist.ECDSA-256
debug1: Checking blacklist file /etc/ssh/blacklist.ECDSA-256
debug1: private host key: #2 type 3 ECDSA
debug1: rexec_argv[0]='/usr/sbin/sshd'
debug1: rexec_argv[1]='-de'
debug1: rexec_argv[2]='-p'
debug1: rexec_argv[3]='1022'
Set /proc/self/oom_score_adj from 0 to -1000
debug1: Bind to port 1022 on 0.0.0.0.
Server listening on 0.0.0.0 port 1022.
debug1: Bind to port 1022 on ::.
Server listening on :: port 1022.
^Z
[1]+ Stopped /usr/sbin/sshd -de -p 1022
root@mac:/home/sysadm# bg
[1]+ /usr/sbin/sshd -de -p 1022 &
root@mac:/home/sysadm# tcpdump -nvlli eth0 'host xxx.yy.4.29'
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
18:16:33.370081 IP (tos 0x0, ttl 63, id 29087, offset 0, flags [DF], proto TCP (6), length 60)
xxx.yy.4.29.42667 > 172.18.8.10.1022: Flags [S], cksum 0xdc29 (correct), seq 107513294, win 14600, options [mss 1460,sackOK,TS val 3473994833 ecr 0,nop,wscale 7], length 0
18:16:36.369860 IP (tos 0x0, ttl 63, id 29088, offset 0, flags [DF], proto TCP (6), length 60)
xxx.yy.4.29.42667 > 172.18.8.10.1022: Flags [S], cksum 0xd071 (correct), seq 107513294, win 14600, options [mss 1460,sackOK,TS val 3473997833 ecr 0,nop,wscale 7], length 0
18:16:42.369300 IP (tos 0x0, ttl 63, id 29089, offset 0, flags [DF], proto TCP (6), length 60)
xxx.yy.4.29.42667 > 172.18.8.10.1022: Flags [S], cksum 0xb901 (correct), seq 107513294, win 14600, options [mss 1460,sackOK,TS val 3474003833 ecr 0,nop,wscale 7], length 0
Для полноты:
root@mac:/home/sysadm# ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
1022 ALLOW Anywhere
22 ALLOW Anywhere (v6)
1022 ALLOW Anywhere (v6)
У узла, устанавливающего соединение, истекло время ожидания. Другие протоколы также затронуты. Время ожидания эхо-запросов истекло. Однако узлы в 8-сети и всех других сетях, не являющихся 4-сетью, могут безупречно обмениваться данными. Логи ничего не показывают. Другие записи «UFW BLOCK» существуют в / var / log / syslog, но не имеют подходящих.
Короче говоря, машина имеет два интерфейса: eth0 в сети 8 и eth4 в сети 4. Другие узлы из сети 4 не могут связываться с eth0, но узлы из всех других сетей могут. Также применима логическая противоположность: узлы сети 8 пытаются поговорить с тайм-аутом опыта eth4. Это особенность или ошибка? Должен ли я просто не ожидать, что смогу поговорить с логически неверно интерфейс на машине с двумя интерфейсами?
Если это важно, это Dell PowerEdge R900. eth0 - это интегрированный порт NetXtreme II BCM5708 Gigabit Ethernet, а eth4 - один из двух портов на плате расширения «MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT / s]» от Mellanox Technologies.
РЕДАКТИРОВАТЬ: Проблема сохраняется, когда брандмауэр отключен. tcpdump по-прежнему показывает входящие пакеты (эхо-запросы) без отправки ответов.
РЕДАКТИРОВАТЬ: Дополнительные выходные данные: это дамп трафика eth4 с участием удаленного хоста xxx.yy.4.29. С xxx.yy.4.29 я пропинговал 172.18.8.10 и xxx.yy.4.235. Это результат.
root@mac:/home/sysadm# tcpdump -nvlli eth4 'host xxx.yy.4.29'
tcpdump: listening on eth4, link-type EN10MB (Ethernet), capture size 65535 bytes
20:25:04.401449 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has xxx.yy.4.235 tell xxx.yy.4.29, length 46
20:25:04.401492 ARP, Ethernet (len 6), IPv4 (len 4), Reply xxx.yy.4.235 is-at 00:02:c9:09:a4:c8, length 28
20:25:04.401647 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
xxx.yy.4.29 > xxx.yy.4.235: ICMP echo request, id 32312, seq 1, length 64
20:25:04.401706 IP (tos 0x0, ttl 64, id 42264, offset 0, flags [none], proto ICMP (1), length 84)
xxx.yy.4.235 > xxx.yy.4.29: ICMP echo reply, id 32312, seq 1, length 64
20:25:05.401200 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
xxx.yy.4.29 > xxx.yy.4.235: ICMP echo request, id 32312, seq 2, length 64
20:25:05.401211 IP (tos 0x0, ttl 64, id 42265, offset 0, flags [none], proto ICMP (1), length 84)
xxx.yy.4.235 > xxx.yy.4.29: ICMP echo reply, id 32312, seq 2, length 64
20:25:09.402234 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has xxx.yy.4.29 tell xxx.yy.4.235, length 28
20:25:09.402383 ARP, Ethernet (len 6), IPv4 (len 4), Reply xxx.yy.4.29 is-at 78:2b:cb:90:95:98, length 46
20:25:09.402747 ARP, Ethernet (len 6), IPv4 (len 4), Reply xxx.yy.4.29 is-at 78:2b:cb:90:95:98, length 46
РЕДАКТИРОВАТЬ: Это просто тестовая машина. Я не могу представить себе реальный сценарий, в котором мне нужно было бы маршрутизировать 8-сетевое соединение через 4-сетевой интерфейс. Я понимаю, что это была бы известная проблема, когда выгода от решения не стоит усилий по ее решению.
Вы, вероятно, видите здесь фильтрация обратного пути. Ядро отбрасывает пакеты, потому что кажется, что они пришли из «неправильного» интерфейса. Чтобы проверить, включен ли RPF, запустите cat /proc/sys/net/ipv4/conf/eth0/rp_filter
(и аналогично для eth4). Чтобы отключить его, введите 0 в файлы thoses.
Даже с отключенным RPF ваша маршрутизация будет немного странной, как сказал @NathanG (ответные пакеты будут выходить с другого интерфейса, чем они пришли). Если ваши маршрутизаторы не слишком умны (то есть не имеют RPF или другой защиты от спуфинга), это все равно должно работать.
Что вам нужно для правильной настройки, так это несколько политика маршрутизации на основе адреса источника (т.е. указать ядру, что пакеты должны маршрутизироваться по-разному в зависимости от адреса источника). Мы делаем это, настраивая несколько таблиц маршрутизации, а затем добавляя некоторые правила для выбора, какую таблицу использовать.
Сначала назовите несколько таблиц (это нужно сделать только один раз).
echo "14 net4" >> /etc/iproute2/rt_tables
echo "18 net8" >> /etc/iproute2/rt_tables
Затем добавьте маршруты в эти новые таблицы (я предполагаю, что эта машина может получить доступ к Интернету через маршрутизаторы на eth0 или eth4).
ip route add xx.yy.4.0/23 dev eth4 table net4
ip route add default via xx.yy.4.1 table net4
ip route add 172.18.8.0/24 dev eth0 table net8
ip route add default via 172.18.8.254 table net8
И, наконец, добавьте несколько правил для выбора соответствующей таблицы на основе адреса источника пакета.
ip rule add from xx.yy.4.0/23 lookup net4
ip rule add from 172.18.8.0/24 lookup net8
Это похоже на проблему с маршрутизацией. Если на eth0 есть входящий пакет от 4-net, ваша система хочет ответить. Единственный маршрут, который он имеет для 4-net, - это eth4, но он должен отвечать с исходного IP-адреса - на eth0. Попробуйте добавить маршрут, чтобы трафик выходил с eth0 на 4-net:
route add -net xx.yy.4.0 netmask 255.255.254.0 metric 100 dev eth0
Метрическая линия делает так, что это не будет предпочтительным маршрутом к 4-net (если что-то не случится с eth4)