Как заставить пакет проходить через определенный физический интерфейс, зная только MAC-адрес назначения?

Вопрос или проблема

Я создаю L3-Коммутатор, который модифицирует пакеты, перенаправляя некоторые из них на локальное приложение. Моя цель – отправлять их дальше на тот же MAC-адрес, что и раньше.

Краткий “зачем”: устройство с нулевой конфигурацией для подключения к любой Ethernet-сети, портативное, выполняет проксирование.

Коммутатор организован как Ethernet-мост (br-lan) между eth0 и eth1. По умолчанию предполагается, что шлюз для клиентов br-lan проходит через eth0.

Вопрос: Допустим, пакет приходит с eth1 на пути к eth0 и перенаправляется на локальное приложение. После этого у приложения есть вывод, и IP-адрес назначения оригинального пакета изменился. L3 пытается маршрутизировать пакет на новый адрес назначения, но не имеет никаких стандартных шлюзов (и не должен, потому что это коммутатор!). Предполагая, что я знаю MAC-адрес стандартного шлюза, как мне заставить пакет выйти через eth0 на конкретный MAC-адрес?

Технически я не пытаюсь сделать что-то “незаконное” с точки зрения сети. Я хочу вытолкнуть пакет из eth0, и все, чего мне “не хватает” – это MAC-адрес назначения, но я могу извлечь его из оригинального пакета. Я точно знаю, что IP-адрес назначения не является локальным, следовательно, он будет отправлен на стандартный шлюз, используя его MAC-адрес. Так что это вопрос реализации.

Я пытался изменить MAC-адрес назначения на мосту -t NAT OUTPUT, делая это:

ebtables -t nat -A OUTPUT -p ipv4 –ip-proto tcp –ip-src 192.168.1.251 -j dnat –to-dst 04:61:e7:d2:e2:09

Но это не помогло. (Предполагая, что 04:61:e7:d2:e2:09 – это MAC-адрес стандартного шлюза, а 192.168.1.251 – один из клиентов, просто чтобы протестировать эту теорию)

Фактическая реализация осуществляется на OpenWRT, поэтому доступные пакеты могут быть ограничены.

Как я пришел к этой проблеме:

Больше информации о локальном приложении: это ss-redir отсюда, привязывается к 0.0.0.0:port => https://github.com/shadowsocks/shadowsocks-libev

Добавлены варианты использования к [Устройству]:

Ожидание: У нас есть 3 ПК-клиента, подключенные к обычному коммутатору. После подключения [Устройства] к обычному коммутатору и переподключения ПК-клиентов к [Устройству], ПК-клиенты получают [Результат] без настройки устройства.

[Результат]:

1) С “наружи” (другие узлы сети, кроме 3 наших и всего прочего) должно выглядеть так, что каждый пользователь сохраняет свою пару IP/MAC, чтобы администратор был доволен. DHCP статически настроен в офисе, поэтому пара IP/MAC, вероятно, не изменится, но администратор может изменить любое из этих значений. И устройство должно обрабатывать любые изменения без ручной перенастройки. Новые IP/MAC не должны появляться в сети (не будучи зарегистрированными администратором).

2) С “наружи” каждый ПК-клиент должен быть доступен для всех протоколов в сети, какими бы они ни были (RDP, NetBIOS для разрешения имен, файловый обмен или что угодно, что решит локальный администратор).

3) Они должны иметь доступ к интернету через стандартный шлюз, как всегда, кроме проксирования TCP через SS для конкретного набора IP-адресов (что всегда через тот же шлюз)

При предположении, что эти варианты использования требуют, чтобы устройство не имело никаких знаний о существующей сети в начале (потому что офисные пользователи ничего не будут настраивать сами), я пытаюсь сделать “проксирующий мост”, который работает как коммутатор, перехватывая пакеты и отправляя их на eth0 (WAN) после перенаправления локального приложения. Проблема в том, что после перенаправления пакет нужно отправить в его путь. Я изучаю идею “автонастройки на лету” с использованием MAC-snat/dnat, но застрял с проблемой, что пакет не пойдет на eth0 после его локальной генерации, даже если я могу указать MAC-адрес стандартного шлюза в ebtables как адрес назначения.

Позвольте мне угадать некоторые “оригинальные задачи X”. Эти задачи, возможно, не совпадают с вашей оригинальной задачей X, но могут дать вам представление, какая информация необходима.

1) Устройство – это обычный доступный домашний маршрутизатор, с четырьмя LAN-портами за внешним коммутатором на eth0 и одним WAN-портом на eth1. WAN-порт подключен к шлюзу вашей локальной сети. Все хосты, которые должны использовать прозрачный прокси, подключены к LAN-портам, возможно, с дополнительными коммутаторами. Ни один другой хост не подключен к LAN-портам. Другой SOCKS-конец находится на стороне WAN.

В этом случае забудьте о уровне 2, используйте правила iptables, как описано в man ss-redir, адаптированные только для NAT на eth0. Маршрутизация отправит проксированный SOCKS-запрос через eth1. NAT позаботится о том, чтобы любые ответы возвращались по eth0, к устройству с правильным IP-адресом. ARP позаботится о том, чтобы MAC-адрес для этого IP использовался.

2) Вариация вышеуказанного: Некоторые хосты, подключенные к LAN-портам, должны использовать прокси, а некоторые – нет. В этом случае обратите внимание на оборудование, у него, вероятно, есть чип-коммутатор, который вы можете настроить с помощью sw-conf. Перенастройте его так, чтобы два LAN-порта были подключены к eth0, а остальные два – к eth2. Затем продолжайте, как выше. Подключите хосты к соответствующим LAN-портам по мере необходимости.

3) Устройство используется как простой мост в более сложной конфигурации сети, где другой SOCKS-эндпоинт находится в том же внутреннем LAN-сегменте, что и хосты, которые должны использовать прокси. В этом случае мне нужно описание сети.

И так далее, и так далее.

Редактировать

Если я правильно читаю ваш вариант использования, ваша главная проблема в том, что вы должны связать WAN-порт (eth0) с LAN-портами (eth1), потому что DHCP-сервер находится за WAN-портом, и он должен правильно управлять статическим назначением IP через DHCP.

В этом случае я бы настроил мост как “brouter”: все пакеты будут моститься, кроме пакетов, приходящих на LAN (eth1), которые должны быть проксированы (TCP и в желаемом диапазоне IP-адресов). Эти пакеты будут выходить из внутреннего порта br-lan моста. Там обработка уровня 3 может обрабатывать их, как описано выше. В частности, трекер соединений может отслеживать их по IP и порту и может отправлять ответы от сокс-прокси обратно к правильному устройству.

Не требуется MAC NAT, не требуется отслеживание соединений на основе MAC, которое сотрудничает с L5 и т.д.

Мне бы хотелось попробовать это с несколькими пространствами сетей, чтобы я мог предоставить весь рецепт, но, к сожалению, у меня не будет времени на это сегодня или в следующие дни.

Я нашел грязное решение.

Если забыть контекст X и углубиться в проблему Y, то мы обнаружим следующее.

Идея в том, что перед перенаправлением пакета на локальное приложение я могу его зарегистрировать, а затем разобрать. Процесс прохождения пакета от eth1 к eth0 к стандартному шлюзу выглядит так:

(CLIENT1_SRC_IP, CLIENT1_SRC_MAC, DEST_IP_ADDR_TO_PROXY, DF_GW_MAC)

Но после того, как локальное приложение обработает его, пакет попадает в это состояние:

((!)CLIENT1_SRC_IP, (!)CLIENT1_SRC_MAC, SS_SERVER) и DF_GW_MAC должен быть ARPed (и провалится, потому что нет соседа SS_SERVER, как и самого стандартного шлюза, так что пакет никуда не уходит).

Таким образом, я решил воспользоваться тем фактом, что SS_SERVER – это постоянный IP-адрес. DF_GW_MAC из лога можно проанализировать, а затем использовать для добавления статического маршрута ARP для IP-адреса SS_SERVER.

Пара деталей для пользователей OpenWRT:

Чтобы сделать ip neigh работающим:

opkg update

opkg install ip-full

А затем:

ip neigh add 123.123.123.123 dev eth0 lladdr 11:22:33:44:55:66

ip route add default dev eth0

Таким образом, проблема Y здесь решена. X не решена полностью, потому что выше, где я указал (!), это не правда, потому что локальное приложение делает MASQUERADE за вас, используя IP интерфейса, так что вам нужно SNAT его обратно на оригинальный IP-адрес источника, что тоже грязно. Я не вижу никаких других вариантов на данный момент.

Ответ или решение

Для решения проблемы перенаправления пакетов через конкретный физический интерфейс по известному MAC-адресу отправителя в ситуации, когда ваш маршрутизатор или свитч работают в качестве прозрачного прокси, необходимо учесть несколько важных аспектов. Ваша задача заключается в том, чтобы заставить пакеты, поступающие с одного интерфейса (например, eth1), продолжать свой путь через другой интерфейс (eth0), используя конкретный MAC-адрес.

1. Понимание маршрутизации и ARP

Для начала важно помнить, что ваши пакеты направляются к IP-адресу, который должен быть доступен через MAC-адрес соответствующего шлюза (например, 04:61:e7:d2:e2:09). Если ваш пакеты были изменены локальным приложением (как ss-redir), но при этом вы получили новый IP-адрес назначения, вам необходимо обязательно убедиться, что ваше устройство знает, как сопоставить этот IP-адрес с MAC-адресом.

2. Использование ebtables

Вы уже пробовали использовать ebtables, чтобы изменить MAC-адрес назначения пакетов, что является допустимой стратегией. Однако стоит отметить, что ebtables работает на уровне канального протокола и не имеет дело с IP-адресами напрямую. Возможно, вам нужно дополнительно настроить настройки NAT и маршрутизации. Например:

ebtables -t nat -A OUTPUT -p ipv4 --ip-proto tcp --ip-src 192.168.1.251 -j dnat --to-dst 04:61:e7:d2:e2:09

Этот подход подходит, если ваш пакет всё ещё имеет соответствующий исходный MAC-адрес. Однако если он меняется, это может привести к проблемам.

3. Настройка маршрутизации

Если ваше устройство не имеет собственного IP- или MAC-адреса для направления трафика, вы можете попробовать использовать следующие команды для статической настройки ARP и маршрутизации:

ip neigh add <новый_IP_адрес_SOCKS_сервера> dev eth0 lladdr 04:61:e7:d2:e2:09
ip route add default dev eth0

Это позволяет вашему устройству "знать", что соответствующий MAC-адрес соединён с новым IP-адресом.

4. Использование SNAT

Вы упомянули, что ваше локальное приложение выполняет MASQUERADE, изменяя исходный IP-адрес. Это может создавать дополнительные сложности. Один из вариантов решения этой проблемы — использование Source NAT (SNAT) для возвращения к оригинальному исходному IP-адресу перед тем, как пакет будет отправлен.

Например, если вы хотите обратно изменить IP-адрес на исходный, используйте следующие команды в iptables:

iptables -t nat -A POSTROUTING -p tcp --dport <порт_SOCKS> -j SNAT --to-source <исходный_IP>

5. Заключение

Используя указанные выше методы, вы можете решить задачу перенаправления пакетов в нужном направлении, сохраняя при этом MAC-адрес отправителя на уровне канала. Ваша система будет иметь возможность работать как мост, сохраняя MAC-пары и обеспечивая работоспособность встраиваемых приложений без необходимости ручного вмешательства.

Не забывайте тестировать каждый шаг настройки, чтобы убедиться, что пакеты проходят через нужный интерфейс и корректно обрабатываются на всех уровнях.

Оцените материал
Добавить комментарий

Капча загружается...