А пинги здесь тихие…

Думаю, что у каждого в жизни, если конечно он бывал в роли системного администратора, появлялась проблема — как через один IP адрес дать выход в интернет всем узлам подсети? Решений — море, тут и NAT и разные PROXY, не перечесть. Но у QNX 6.xx есть свои прекрасные возможности решить данную задачу еще одним способом. В классическом варианте подключение нескольких QNX (да и не только) машин в общую сетку с доступом к WAN выглядит так:

На HOST1 установлено специальное ПО, выполняющее роль посредника между внутренней и WAN сетями. В любом случае машины внутренней сети чем то да обделены, если NAT, то окажется что какой то протокол транслируется неверно т.к. адреса находятся в теле сообщения, если PROXY типа HTTP (squid или подобные), то клиент должен быть наделен способностями уметь работать с таким proxy, много разных «но». И вообще с точки зрения QNX может показаться не естественным иметь на каждом узле свой собственный стек TCP/IP, ведь мы сетевая OS до мозга костей! Помнится в QNX 4.xx можно было задать переменную окружения SOCKET с номером узла на котором собственно и работает стек TCP/IP. Как это было на деле, не скажу, потому что не пробовал, но это заставило призадуматься над аналогичной способностью QNX 6.xx. Бегло посмотрев help я не нашел упоминаний о переменных окружения как либо влияющих на выбор узла со стеком TCP/IP кроме как локального. Но это не беда, раз TCP/IP такой же менеджер ресурсов как и все остальное, то почему бы не подменить его на локальной машине ресурсом другого узла. Сказано — сделано. Теперь моя сеть выглядела уже так:

На всех узлах кроме одного (HOST1) присутствовал только протокол QNET (или FLEET, как угодно). HOST1 имел в своем составе помимо QNET еще и TCP/IP. Если в деталях, то на HOST1 было выполнено:

#slay io-net
#io-net -drtl -ptcpip -pqnet -ppppmgr
и установлена связь с удаленной системой по PPP. На всех же остальных узлах io-net был запущен следующим образом.

#slay io-net
#io-net -drtl -pqnet
Убедившись в том что команда sin net отображает всех участников, можно приступить к переносу стека TCP/IP на другие узлы. Так например на HOST2 я ввел команду

#ln -Ps /net/host1/dev/socket/ /dev/socket
Которая заставила создать в дереве process manager ссылку /dev/socket на /net/host1/dev/socket/. С замиранием сердца я набрал

# ping mail.ru
Надежды мои полностью оправдались! Я получил нужный пинг, что означало полную работоспособность всей цепочки. Проделав аналогичную операцию на HOST3 я и оттуда посетил отдельные Web узлы, что уже казалось совершенно естественным. Выполняя ifconfig с любого узла можно конфигурировать TCP/IP на HOST1, route тоже работает, но вот netstat категорически отказался показывать состояние TCP/IP с удаленных узлов. Даже аналогичный трюк с подменой «устройств» типа en0_ip … ppp из /net/host1/dev/io-net не исправлял ситуацию с netstat к лучшему, так что остается только думать и соображать почему, но в любом случае, даже если netstat и получиться заставить работать, то он будет показывать «картинку» по всем соединениям, включая HOST1,HOST2,HOST3. Частной картины, например только для HOST1, получить не удастся IMHO никак, т.к. разделение между «клиентами» идет не на уровне TCP/IP а на уровне QNET, что просто непостижимо для netstat в его нынешнем обличии.

Но что мне больше всего понравилось, так это ping с HOST2 или HOST3 на loopback:

#ping 127.0.0.1
Что вы думаете я увидел?

PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=4 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=255 time=3 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=255 time=2 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=255 time=3 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=255 time=2 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=255 time=3 ms
— 127.0.0.1 ping statistics —
6 packets transmitted, 6 packets received, 0% packet loss
И это было именно то, чего ожидал. Думаю всем понятно почему время отклика достаточно большое для «локальной петли» :). Потому что сама петля располагается на HOST1 а ping засекает время на свое машине (то есть HOST2) и получается что по QNET пакет идет на HOST1 там закругляется обратно и по QNET ответ приходит клиенту ping что в общей сложности и составляет несколько миллисекунд. Таким образом, используя сетевые возможности QNX 6.xx можно с легкостью подключить всех внутренних QNX клиентов к WAN и предоставить им полный пакет услуг TCP/IP без каких либо ограничений (вот это конечно минус, но иногда это и не нужно). В качестве еще одного минуса такого варианта следует отметить, что все порты делятся узлами в равной степени (стек то один на всех), и если на HOST2 запущен WEB сервер, то этот порт уже занят и HOST3 не сможет запустить свой WEB сервер на том же номере порта, что и HOST2. В принципе, такой же минус но немного в другом ракурсе, всплывает и в варианте с NAT, но это уже совсем другая история.

Аналогичным образом можно подменять не только стек TCP/IP но и любое другое устройство, если таковое не предусмотрено заранее.

P.S. Вот написал я «если таковое не предусмотрено заранее» и думал, неужели QSSL не предусмотрела? Тем более что в QNX 4.xx это было! Пошел искать и смотреть исходники libsocket, и нашел! Действительно, как была переменная окружения SOCK, так она и осталась. И достаточчно написать:

$export SOCK=/net/host1
чтобы использовался TCP/IP стек удаленной машины. В этом случае и netstat начинает работать 🙂 Век живи, век учись….. Обидно только то, что встроенный help закрывает глаза на такие замечательные возможности, остается надеятся, что это одно из немногих белых пятен.