Существует спецификация IGD-PCP IWF, которая пытается решить аналогичную проблему, хотя предполагает поддержку PCP на твой "Роутер 1", а не UPnP. Итак, давайте попробуем подойти к этому вопросу с чисто теоретической точки зрения с двумя простыми маршрутизаторами UPnP / NAT.
Существует несколько различных шагов связи UPnP согласно Архитектура устройства UPnP версии 2.0:
- обращаясь
- открытие
- описание
- контроль
- событие
- презентация
Адресация нас мало интересует, давайте предположим, что DHCP везде работает, и покончим с этим. Событие и презентация в нашем случае также почти бесполезны. Итак, в первую очередь следует позаботиться о обнаружении, описании и управлении.
Обнаружение работает через обмен сообщениями SSDP. SSDP использует UDP для своего транспорта с номером порта 1900 (по умолчанию) и хорошо известным многоадресным адресом.
Описание начинается с URL-адреса, предоставленного устройством на этапе обнаружения, контрольной точке (то есть ПК в нашем случае) необходимо отправить HTTP-запрос GET на этот URL-адрес, а это означает, что он использует TCP в качестве транспортного протокола с IP-адресом устройства (одноадресная передача). .
Управление начинается с URL-адреса, предоставленного устройством в его описании, и он использует SOAP поверх HTTP поверх TCP, что, в свою очередь, также означает для нас одноадресный IP.
Итак, что все это означает для двойного NAT, так это то, что в описании и этапах управления взаимодействием UPnP у нас нет проблем с обменом данными от ПК к маршрутизатору 1, поскольку все это просто стандартный TCP с одноадресными IP-адресами. Но чтобы перейти к этапу описания, нам нужен URL-адрес маршрутизатора 1, поэтому давайте подробнее рассмотрим, как этот URL-адрес получается обычным способом.
Существует два основных механизма для рекламы обнаружения (когда устройство периодически рассылает некоторую информацию о нем в многоадресной рассылке) и поиска (когда контрольная точка отправляет многоадресное поисковое сообщение, а устройство отвечает на это одноадресным ответом). Очевидно, что по умолчанию наш компьютер за маршрутизатором 2 не может получать многоадресные рекламные объявления от маршрутизатора 1, а маршрутизатор 1 не может получать сообщения многоадресного поиска с ПК, поэтому у нас есть проблема, и теперь вопрос заключается в том, существует ли возможность для связь без многоадресной рассылки.
К счастью, в том же архитектурном документе говорится:
Кроме того, контрольной точке разрешено одноадресное сообщение об обнаружении на определенный IP-адрес на порт 1900 или на порт, указанный в необязательном поле заголовка SEARCHPORT.UPNP.ORG (которое заменяет порт 1900 для этого использования), ища UPnP устройство или служба на этом конкретном IP-адресе.
...
Все устройства должны прослушивать входящие одноадресные поисковые сообщения через порт 1900 или, если он предоставлен, номер порта, указанный в поле заголовка SEARCHPORT.UPNP.ORG, и должны отвечать, если какое-либо из их корневых устройств, встроенных устройств или служб соответствует критериям поиска в сообщение об обнаружении.
А это означает, что если вы знаете IP-адрес маршрутизатора 1 (со стороны маршрутизатора 2, конечно), вы можете (и, что наиболее важно, разрешено спецификацией) связываться с ним с помощью одноадресных сообщений UDP, и это также является дружественным к NAT, поэтому это не проблема, которую можно сделать с ПК за маршрутизатором 2.
Осталось только получить IP-адрес маршрутизатора 1. К сожалению, нет простого стандартного способа сделать это, но у вас есть как минимум два варианта: трассировка (любым способом) и сканирование IP методом грубой силы (скорее всего, потенциальный набор IP-адресов для маршрутизатора 1 ограничен).
Теперь вы можете общаться с маршрутизатором 1, но есть еще одна незначительная вещь, которую вы всегда должны помнить при общении с ним в любых внутренних сообщениях UPnP: вы должны использовать IP-адрес маршрутизатора 2 (как видно со стороны маршрутизатора 1) и его порты. Как и в параметре NewInternalClient
действия AddPortMapping
на маршрутизаторе 1, вы должны использовать IP маршрутизатора 2. Это, кстати, поднимает вопрос об IP-адресе маршрутизатора 2, но вы можете получить его через переменную UPnP ExternalIPAddress
маршрутизатора 2 _ 4_ служба (эта служба является требуется для реализации IGD).
Итак, подведем итог:
- технически это можно сделать, хотя я сомневаюсь, что любая стандартная библиотека сделает это за вас
- two things you need are:
- Router 2 "external" IP and you get that via
ExternalIPAddress
variable of WANIPConnection
UPnP service
- Маршрутизатор 1 "внутренний" IP (со стороны Маршрутизатора 2), требующий трассировки или сканирования
- учитывая IP-адрес маршрутизатора 1, вам просто нужно использовать одноадресный обмен сообщениями на этапе обнаружения вместо многоадресной рассылки
- все остальное должно работать, только с оговоркой об использовании «внешнего» IP-адреса маршрутизатора 2 вместо IP-адреса ПК в сообщениях UPnP.
person
Roman Khimov
schedule
14.08.2016