У меня есть два интерфейса на серверной машине. Вывод ip route
следующий:
default via 192.168.100.1 dev enp1s0 proto static metric 100
10.8.0.0/24 dev tap0 proto kernel scope link src 10.8.0.1
192.168.100.0/24 dev enp1s0 proto kernel scope link src 192.168.100.201 metric 100
и ip address
далее (MAC-адреса скрыты):
...
1: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff
inet 192.168.100.201/24 brd 192.168.100.255 scope global noprefixroute enp1s0
valid_lft forever preferred_lft forever
inet6 fe80::1409:66c6:eb0d:22a1/64 scope link noprefixroute
valid_lft forever preferred_lft forever
2: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff
inet 10.8.0.1/24 brd 10.8.0.255 scope global tap0
valid_lft forever preferred_lft forever
inet6 fe80::85:5fff:fe98:6cb7/64 scope link
valid_lft forever preferred_lft forever
Значение /proc/sys/net/ipv4/ip_forward
равно 1; брандмауэр отключен.
Я хочу получить доступ192.168.100.1от10.8.0.100. Доступ к веб-серверу (который прослушивает все порты на этой машине) curl --interface 10.8.0.100 http://10.8.0.1
работает нормально. Но curl --interface 10.8.0.100 http://192.168.100.201
вывод Network unreachable
.
Curl инициирует TCP-рукопожатие и отправляет пакет10.8.0.100Интерфейс. Затем пакет достигает серверной машины на10.8.0.1. Сервер просматривает пакет dest и видит, что это192.168.100.201. Затем он смотрит в таблицу маршрутизации и видит, что192.168.100.201локальный. Теперь ответ возвращается. Отправитель был10.8.0.100. Глядя на таблицу маршрутизации, мы можем обнаружить, что он доступен через tap0
, который является локальным. Так что теперь он проникает tap0
и достигает 10.8.0.100.
Но на самом деле -это не так. Это потому, что мой ход мыслей неверный? Я думал, что информации, предоставленной описанной таблицей, достаточно, чтобы определить, как пересылать пакеты. Это на самом деле неполно?
решение1
Прежде всего, предоставление IP-адреса и интерфейса с параметром -I ping
не является синонимами. Первый указывает, что source IP
выбрать. Он направит его в соответствии с сетевым потоком, включая локальные адреса и таблицы маршрутизации. Второй указывает напрямую выбрать интерфейс для отправки пакета (и он выберет первый назначенный IP в качестве источника).
Далее то, что вы делаете, не имеет ничего общего с пересылкой пакетов. Пересылка означает, что пакет должен фактически прибыть «извне». Поскольку вы генерируете пакет с этого хоста, пересылка не производится. Это локально сгенерированный пакет. Поскольку ваш целевой IP-адрес является одним из локально назначенных адресов, когда вы не заставляете ping отправлять пакет на определенный интерфейс «снаружи» (с -I interface
опцией), ядро будет обрабатывать этот поток пакетов внутренне. Оно просто не будет пытаться вывести его на реальный интерфейс, поскольку его пункт назначения «уже здесь». Вот что происходит и почему это работает в одном случае и не работает в другом.
PS: Также проверьте -r
опцию инструмента ping
, если вы знаете, что делаете, и оба интерфейса подключены к одному и тому же широковещательному домену (сомневаюсь в этом с интерфейсом TAP).
решение2
Проблема была в непонимании разницы между --interface IP
и --interface dev
. Первый использует таблицу маршрутизации:
с --interface 10.8.0.100
пакетом не будет отправлен на tap0
интерфейс (которому принадлежит этот ip). Вместо этого, согласно таблице маршрутизации, он будет отправлен на 192.168.100.58
(интерфейс lan). Таким образом, маршрут 10.8.0.100 -> 192.168.100.58 -> 192.168.100.201
. Даже тот факт, что SYN был доставлен, сервер странным образом не отвечает SYN-ACK - вот причина сбоя curl.
Используя --interface tap0
адрес канального уровня, он будет работать так, как задумано: 10.8.0.100 -> 10.8.0.1 -> 192.168.100.201
SYN-ACK будет доставлен обратно по тому же маршруту.