Проброс портов на точке доступа Android: три точки входа
Телефон, путь оператора и выход VPN задают разные границы. Прежде чем открывать порт, определите, какой машине принадлежит слушающий сокет.
Вы включили точку доступа, подключили VPN, открыли порт в приложении, а другое устройство всё равно не подключается. Недостающий элемент почти никогда не сам порт. Вопрос в том, какой машине принадлежит слушающий сокет и до какого адреса должно доходить другое устройство. Я разбираю это от телефона наружу, потому что экран, на котором вы находитесь, подсказывает, какую из трёх точек входа вы на самом деле проверяете.
Начните с того места, где служба действительно работает
Откройте приложение, которое должно принимать подключение, и прочитайте его страницу состояния. Если там сказано, что оно слушает, запишите адрес привязки, потому что эта одна деталь решает большинство случаев ниже. Приложение, привязанное к 127.0.0.1, доступно только с самого телефона, и ни клиент точки доступа, ни преобразование у оператора, ни выход VPN этого не изменят.
Затем определите, какое устройство выполняет службу. Это либо телефон, и тогда сокет принадлежит приложению, либо ноутбук за точкой доступа, и тогда слушатель и его межсетевой экран принадлежат ноутбуку, а телефон лишь пересылает пакеты. Это разные схемы с разными владельцами, и их смешение — причина того, что порт, открытый в одном месте, ничего не делает в другом.
В отладочной сборке adb shell может перечислить сокеты через /proc/net/tcp, но для большинства людей честный источник — статус самого приложения. Это ещё и избавляет от ловушки проверять сокет, который приложение открыло на неожиданном для вас адресе.
Первая точка входа: другое устройство в точке доступа
Это локальный случай, и его проще всего сделать правильно. Другое устройство доходит до телефона по адресу, который видит как свой шлюз, на порт, который слушает приложение, и ничего за пределами точки доступа участвовать не должно. Преобразование у оператора не нужно, и ни одна функция провайдера не требуется, потому что трафик никогда не покидает локальный сегмент.
Ломают это две вещи. Приложение привязано к loopback, либо клиентская политика на телефоне не разрешает локальное подключение. Если приложение выполняет аутентификацию, проверяйте протоколом самого приложения, а не голым TCP-подключением: слушатель, который принимает, а затем отклоняет, издалека выглядит так же, как закрытый порт.
Если служба работает на ноутбуке, подключённом к телефону, адрес точки доступа телефона вовсе не является адресом назначения. Нужен адрес ноутбука на интерфейсе точки доступа и слушатель на ноутбуке, и телефон больше ничем, кроме пересылки, не владеет.
Вторая точка входа: путь оператора
Дойти до телефона из мобильной сети — другая задача, и чаще всего для IPv4 она просто не работает. Операторы держат аппараты за общим преобразованием, поэтому RFC 6598 выделил общий диапазон адресов именно для такой схемы. У нежелательного входящего подключения нет преобразования, через которое можно прийти, и никакая локальная настройка его не создаёт, ведь преобразователь — не ваше устройство.
Root-доступ этого тоже не меняет. Он даёт контроль над стеком телефона, а не над преобразователем оператора, а рецепты, обещающие обратное, обычно предполагают публичный адрес, который оператор никогда не выдавал. Там, где оператор предлагает публичный префикс IPv6, входящий путь может существовать, но слушателю и межсетевому экрану телефона всё равно нужно осознанное разрешение, прежде чем что-то ответит.
Третья точка входа: выход VPN
Адрес, который сообщает сайт, пока туннель поднят, — это адрес выхода для покрытого исходящего трафика. Это не то же самое, что адрес, принимающий входящие подключения от вашего имени. Чтобы использовать его для входящих, нужна функция, которую провайдер действительно предлагает, например проброшенный порт или входящее преобразование, привязанное к вашей учётной записи, а также рабочий путь от выхода до клиента.
Локальное правило разрешения не может создать такое преобразование. Оно может изменить, каким путём идут ответы приложения, и это важно, когда приложение исключено из туннеля: запрос и ответ могут оказаться в разных сетевых контекстах, и соединение падает так, что это выглядит как проблема межсетевого экрана.
Проверьте один путь от начала до конца, затем назовите владельца
Запишите кортеж до проверки: предполагаемый источник, адрес назначения, транспорт, порт и машина, которой принадлежит слушающий сокет. Если какой-то элемент — догадка, проверка ничего полезного не скажет, и в итоге вы измените второй уровень, чтобы объяснить первый.
Затем проверьте этот единственный разрешённый путь, не трогая аутентификацию приложения. Не публикуйте широкий слушатель и не отключайте посторонние механизмы только ради того, чтобы неоднозначная проверка публичного адреса дала ответ: оба изменения переживут проверку, и ни одно не доказывает, что схема работает.
Подсистема tethering в Android пересылает нисходящий трафик своим путём, отдельно от обычного перехвата VPN приложениями, поэтому работающий браузер на подключённом ноутбуке ничего не говорит о входящем доступе к службе на телефоне. Прежде чем называть это работающим:
- Слушающий сокет находится на адресе, доступном нужному партнёру, а не на loopback.
- Партнёр использует адрес, относящийся к этой точке входа, а не адрес выхода со страницы состояния.
- Любое преобразование на стороне оператора или провайдера — поддерживаемая функция, а не добавленное вами локальное правило.
- Запрос и ответ идут через один и тот же сетевой контекст, и аутентификация приложения всё ещё проходит.