Переадресация портов Python
Я занимаюсь разработкой клиент-серверной игры на python и хочу узнать больше о переадресации портов.
Например, то, что я делаю, идет на мой маршрутизатор (192.168.0.1)
и настройте его так, чтобы запрос на перенаправление моего реального IP-адреса на мой локальный адрес 192.168.0.X.
Это работает очень хорошо. Но мне интересно, смогу ли я сделать это путем автоматического кодирования чего-либо?
Я думаю, что скайп работает как своего рода p2p
и я вижу в своем маршрутизаторе, что Skype автоматически перенаправляет порт на мой адрес компьютера. Могу ли я сделать это на Python тоже?
4 ответа
Здесь есть разные решения, но большинство из них не тривиальны, и вам придется немного почитать, и вам понадобится некоторый запасной вариант.
UPnP / IGD является самым простым. Если ваш маршрутизатор поддерживает его и настроен на его разрешение, и вы знаете, как писать либо низкоуровневый сетевой код, либо устаревший код веб-службы SOAP, вы можете попросить маршрутизатор назначить вам порт. Если он отвечает успешно, начните использовать этот порт, и вы в основном сделали.
Если вы можете запустить сервер (с очень низкой пропускной способностью) с публичным адресом для всех ваших пользователей, пробивка отверстий может решить проблему.
Подумайте о том, как заурядный клиент общается с публичным сервером. Вы делаете запрос на некоторый IP и порт, но сервер видит IP вашего роутера, а не ваш (что хорошо, потому что ваш недоступен). Когда он отвечает, ваш маршрутизатор должен знать, чтобы переслать его вам - что он делает, просто помня, что вы клиент за пределами NAT, который только что отправил запрос на этот сервер.
Что если вместо общедоступного сервера вы общаетесь с каким-то другим пэром за его собственным отдельным NAT? Ну, ваш роутер не знает разницы; пока вы получите ответ из того же места, оно пройдет. Но как вы получите ответ, когда ваше сообщение не пройдет через его NAT? Он делает то же самое, конечно. Одно из сообщений может быть потеряно, но другое пройдет, и тогда вы оба настроены и сможете общаться. Вам нужно будет регулярно отправлять сообщения активности, чтобы маршрутизатор не забыл, что вы общались, но, кроме этого, в этом нет ничего сложного.
Единственная проблема заключается в том, что вам нужно знать общедоступный IP-адрес другого партнера, а также порт, с которого он ожидает вашего прихода, и он должен знать то же самое о вас. Вот почему вам нужен сервер - чтобы выступать в качестве представителя между партнерами.
Пробивание отверстий будет работать с UDP из большинства домашних сетей. Он не будет работать с TCP из многих домашних сетей или с UDP или TCP из многих корпоративных сетей. (Кроме того, в корпоративных сетях у вас может быть несколько уровней NAT, что означает, что вам нужны вводчики на каждом интерфейсе, а не только один в Интернете, или симметричные NAT, которые нельзя пробивать.)
Вы можете использовать STUN (или аналогичные) услуги, такие как ICE или TURN. Это работает только в том случае, если необходимо использовать службу ICE, TURN и т. Д., Что, как правило, не относится к двум одноранговым узлам на разных домашних NAT, если только вы не развернете свой собственный сервер и не создадите интродьюсер, чтобы помочь, и если вы собираясь сделать это, вы можете просто использовать дырокол. Но в корпоративной среде это может быть лучшим способом обеспечения подключения для приложений P2P.
Наконец, вы можете вручную настроить переадресацию портов и ввести номер переадресованного порта в вашу проблему. Это не идеально, но вы всегда должны предоставлять его как запасной вариант (за исключением, может быть, приложений, предназначенных только для корпоративного развертывания), потому что больше ничего не будет работать для всех ваших пользователей.
Я считаю, что Skype использует все это. Если вы включите UPnP, он попытается IGD вашего маршрутизатора. Или вы можете настроить его на использование сервера TURN. Или вы можете просто ввести определенный порт, который вы перенаправили вручную. Если вы не сделаете ничего из вышеперечисленного, он попытается использовать дырокол UDP, с представителем, который запускает Skype.
Поэтому, если я правильно понимаю, ваше приложение должно работать в сети TCP/UDP. Это означает, что по крайней мере одному из подключающихся клиентов нужен правильно открытый порт, и если оба они находятся за NAT (маршрутизатором) и не имеют настроенных открытых портов, ваши клиенты не смогут подключиться.
Для этого есть несколько возможных решений, но не все они являются надежными: UPnP, как предлагается здесь, может открывать порты по требованию, но не поддерживается (или не включен) на всех маршрутизаторах (и это является угрозой безопасности), а решения P2P сложный и все еще требует открытых портов на некоторых клиентах.
Единственное надежное решение - иметь выделенный сервер, к которому могут подключиться все клиенты, который будет согласовывать соединения, и, возможно, прокси между ними.
Вы можете посмотреть на что-то вроде этого (при условии, что ваш маршрутизатор поддерживает это): http://en.wikipedia.org/wiki/Universal_Plug_and_Play
Для реализации переадресации портов с использованием python существует фантастический рецепт ActriveState, который выполняет асинхронный сервер переадресации портов, используя только стандартную библиотеку Python (socket, syncope). смотреть на
http://code.activestate.com/recipes/483732-asynchronous-port-forwarding/