Вопрос или проблема
Я создаю 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-пары и обеспечивая работоспособность встраиваемых приложений без необходимости ручного вмешательства.
Не забывайте тестировать каждый шаг настройки, чтобы убедиться, что пакеты проходят через нужный интерфейс и корректно обрабатываются на всех уровнях.