FAQ FreeBSD - Сеть и протоколы. Часть 5
ОГЛАВЛЕНИЕ
10.23. Процесс, вызвавший прозвонку в режиме auto, никогда не получает затребованного соединения
Эта проблема проявлялась, когда ppp в режиме auto был настроен на динамическое
согласование локального IP-адреса с противоположной стороной. Это исправлено в
последней версии - поищите на странице справочника слово iface.
Причиной было то, что когда эта программа использует системный вызов connect(2)
, для сокета назначается IP-адрес tun-интерфейса. Ядро создаёт первый исходящий
пакет и записывает его в устройство tun. Затем ppp читает пакет и устанавливает
соединение. Если в результате согласования ppp динамического IP-адреса, адрес
интерфейса изменется, сокет будет работать некорректно. Любые IP-пакеты, переда
ваемые через сокет, будут отброшены. Если даже этого не произойдёт, ответные
данные не будут достигать отправителя, так как этот адрес больше ему не
принадлежит.
Теоретически есть несколько способов решить эту проблему. Лучше всего, если
противоположная сторона назначит интерфейсу тот же самый IP-адрес :-) Текущая в
ерсия ppp именно так и поступает, более ранние реализации этого не делали.
Самым простым решением будет просто никогда не менять IP-адрес tun-интерфейса,
а вместо этого изменять на лету все исходящие пакеты так, чтобы IP-адрес
источника менялся с IP-адреса интерфейса на соответствующий с противоположной
стороны. Это, в сущности, то же самое, что делает опция iface-alias в последней
версии ppp (с помощью библиотеки libalias(3) и ключа -nat для ppp) - она
отслеживает все назначенные ранее интерфейсу адреса и замещает их на последний
из назначенных.
Другой возможный (и, наверное, самый надёжный) способ - это создать системный в
ызов, меняющий IP-адреса всем уже связанным сокетам. Ppp использовал бы этот в
ызов для модификации сокетов всех работающих программ после согласования нового
IP-адреса. Этот же самый системный вызов могли бы использовать клиенты DHCP,
когда они осуществляют повторную привязку к сокету.
Ещё одной возможностью является разрешение интерфейсу становиться активным без
IP-адреса. Исходящим пакетам будет даваться IP адрес 255.255.255.255 до тех
пор, пока не будет дан ioctl-запрос SIOCAIFADDR. приводящий к полной привязке
сокета. Ppp нужно будет изменять IP-адрес источника и контрольную сумму пакета,
только если он установлен в 255.255.255.255. Это, однако, является некоторым
хаком, так как ядро будет посылать некорректные пакеты на не полностью
сконфигурированный интерфейс, в предположении, что существует механизм исправ
ления этих пакетов.
10.24. Почему большинство игр не работает с опцией -nat?
Причиной, по которой игры и подобные программы не работают с библиотекой
libalias заключается в том, что внешняя машина будет пытаться открыть
соединение или посылать (нежданные) UDP пакеты на машину внутренней сети.
Программное обеспечение, обеспечивающее опцию -nat, не знает о том, что она
должна пересылать эти пакеты машине внутренней сети.
Чтобы это всё же заработало, удостоверьтесь, что единственной запущенной
программой является программное обеспечение, с которым вы испытываете проблемы,
затем напустите tcpdump на tun-интерфейс маршрутизатора либо включите
протоколирование tcp/ip в ppp (set log +tcp/ip) на маршрутизаторе.
Когда вы запустите некорректно работающее программное обеспечение, вы должны ув
идеть пакеты, проходящие через маршрутизатор. Когда что-то начнёт приходить изв
не, оно будет отброшено (в этом-то и проблема). Заметьте номер порта получателя
этих пакетов, затем завершите работу вашего программного обеспечения. Выполните
эту процедуру несколько раз для того, чтобы убедиться, что номер порта
постоянен. Если это так, то следующая строчка в соответствующем разделе /etc/
ppp/ppp.conf заставит программное обеспечение функционировать нормально:
nat port proto internalmachine:port port
Здесь proto - это tcp либо udp, internalmachine - это машина, которой вы хотите
перенаправлять пакеты, и port - это номер порта получателя пакетов.
Несомненно, вы не сможете использовать программное обеспечение на других
машинах, не изменяя указанную выше команду, а также запускать программное
обеспечение на двух машинах внутри сети одновременно - в конце концов, внешний
мир видит всю вашу сеть как единственную машину.
Если номера портов непостоянны, есть ещё три варианта:
1) Настройте поддержку этого в libalias. Примеры "особых случаев" можно найти в
/usr/src/lib/libalias/alias_*.c (alias_ftp.c - хорошее начало). Это означает,
что вам нужно будет использовать чтение некоторых распознаваемых исходящих
пакетов, обнаруживать команды для установления внешней машиной обратной связи
на внутреннюю машину на конкретный (случайный) порт и настраивать "маршрут" в
таблице соответствий так, чтобы последующие пакеты проходили нормально.
Это самое трудоёмкое решение, но оно наилучшее и позволит программному
обеспечению работать на нескольких машинах.
2) Используйте прокси-сервера. Приложение может поддерживать, например, socks5
или (как в случае "cvsup") может иметь режим "passive", обходящийся без запросо
в к противоположной стороне на открытие обратного соединения.
3) Переназначьте всё на внутреннюю машину с помощью команды nat addr. Это
решение в лоб.
10.25. Кто-нибудь ведёт список полезных номеров портов?
Пока нет, но ниже находится список, могущий таковым стать (если к этому будет
проявлен какой-либо интерес). В каждом примере internal нужно заменить на
IP-адрес машины, участвующей в игре.
* Asheron's Call
nat port udp internal:65000 65000
Находясь в игре, вручную смените номер порта на 65000. Если у вас есть
несколько машин, на которых вы хотите играть, назначьте каждой машине
уникальный номер порта (то есть 65001, 65002 и так далее), и добавьте по
строчке nat port для каждой машины.
* Half Life
nat port udp internal:27005 27015
* PCAnywhere 8.0
nat port udp internal:5632 5632
nat port tcp internal:5631 5631
* Quake
nat port udp internal:6112 6112
Альтернативное решение, обеспечивающее поддержку прокси для Quake, можно
найти на сервере www.battle.net.
* Quake 2
nat port udp internal:27901 27910
* Red Alert
nat port udp internal:8675 8675
nat port udp internal:5009 5009