Короче, поломался тут у меня интернет. Ну, традиционно запустил ping, tracert: короче, шлюз "Сибирских сетей", к которому подключен мой роутер, иногда пропадает на несколько десятков минут, хотя физически соединение до коммутатора провайдера живое.
Пишу в тех. поддержку, понятное дело. И тут выясняю, что я отстал от жизни: ни ping, ни tracert нонче у сетевиков не котируются, им нужно специальную программку поставить и её логи выслать в тех. поддержку, что бы они могли проблему решить.
Программка PingPlotter называется. В принципе, хорошая программка, есть у нее только один недостаток: она платная. Хоть и стоит недорого, но все же, особенно в условиях санкций, имеет значение. Да и нужна-то она раз в пять лет, если не реже.
Ну и кстати, логи трассировки, полученные с помощью этой программки никак не помогли решить мою проблему: видимо, надо менять провайдера. Уже больше месяца "Сибирские сети" возятся, вроде на прошлой неделе ушла проблема, но на этой неделе снова вернулась. Хоть и не так критично, как раньше, но все же пару раз в день интернет на несколько минут пропадает.
В общем, в процессе всей этой катавасии, уже традиционно, захотелось и мне какую-то подобную программку замутить. А, думаю, это же просто, сейчас возьму готовый компонентик, да и сделаю.
В Delphi для подобных задач есть набор компонентов Indy, вроде десятой версии они у меня. Да вот незадача: компонентик для отправки ICMP запросов как-то странно работает. То есть просто пинг вроде норм, но как только ставишь маленький TTL, что бы сэмулировать трассировку маршрута, он вываливается со странной ошибкой: маленький размер буфера приема.
Проверил компонент Indy для трассировки, а не для пинга: та же шняга. Все же половина этих компонентов явно не доделана.
Порылся по интернету, нашел готовый модуль, который умеет отправлять ICMP-пинг безо всяких компонентов, используя лишь API Windows: Winsock и специальную библиотеку в довесок. Вполне себе рабочий, но вот только на Win64 он выдает ту же ошибку, что и Indy, а на Win32 норм.
Короче, фишка тут вот в чем. Windows, если в ответ вернулся ICMP-ответ с ошибкой, в буфер приема еще кладет дополнительно к обычной информации первые 8 байт из сообщения об ошибке принятого пакета. Поэтому если ICMP дошел до адресата без ошибки, то компонент Indy работает нормально, а вот если вернулась ошибка, например, "Время жизни (TTL) истекло в пути", то длины приемного буфера не хватает для помещения стандартного ответа ICMP плюс еще и сообщения об ошибки. К сожалению, видимо, разработчики компонентов Indy, видимо, не знали о такой особенности и дополнительно 8 байт в приемный буфер не выделили на случай возврата ошибочного пакета.
Но, удивительно, Win64 пишет в приемный буфер не 8, а 16 байт из сообщения об ошибке. Уж не знаю, почему. Поэтому найденный мною код и не работал в 64-битном режиме.
В общем, исходный файлик маленько подшаманил, добавил условную компиляцию, так что теперь он может работать и в 32-битном и в 64-битном режиме. Выложу здесь, может, кому пригодиться.
По хорошему, его немного надо доработать. Дело в том, что выполнения подобных ICMP задач в Windows добавлена специальная библиотека. Без нее, на голом WinSock, требуется, что бы приложение было запущено с привилегиями администратора, а с такой библиотекой можно пинговать и обычному пользователю.
Вот только на разных версиях Windows библиотека называется по разному: где-то Iphlpapi.dll, а где-то Icmp.dll. Так что по-хорошему, надо грузить библиотеки динамически, определяя, какой из вариантов на данной машине подходит.
Еще один любопытный момент связан с использованием указателей при вызове ICMP запросов. И для 32-битных, и для 64-битных систем используется одна и та же структура данных для вызовов функций, при этом все указатели, остаются, естественно 32-битными.
Как же это работает в 64-битной Windows, где указатели 64-битные? Оказывается, очень просто: 32-битный указатель расширяется (беззнаково) до 64-битного. Используется здесь тот факт, что Windows вроде всегда выделяет память под данные приложения с начала адресного пространства.
Вывод из этого безобразия: пока ваша программа вместе с данными влезает в 4 ГиБ, то все гарантированно будет работать, но как только станет больше - уже не факт ).
Ну, и кстати, в процессе узнал много интересного. Раньше думал, что, как и на Windows, на других операционках пользуются ICMP запросом Echo для пинга и трассировки маршрута. Но, оказывается, на Unix-подобных системах предпочитают отправлять UDP-запросы на неиспользуемый порт, ловя обратно ICMP-ответы по мере прохождения маршрута. Завершение маршрута определяет по ошибке о недоступности порта. В принципе, годный метод, но как быть, если порт на удаленной машине для чего-то используется? Ведь пингуя таким образом удаленную машину, мы не можем знать, какие порты на ней используются, а какие нет.
А еще бывают и более экзотические варианты пинга, на основе TCP. Но в эту сторону особо не смотрел.
> им нужно специальную программку поставить и её логи выслать в тех. поддержку,
ОтветитьУдалитьКак все сурово, а если клиент не особо технически подкованный и не хочет разные программки ставить? :)
> но как быть, если порт на удаленной машине для чего-то используется?
Игнорировать и пробовать следующий порт :))) Из https://linux.die.net/man/8/traceroute
Probe packets are udp datagrams with so-called "unlikely" destination ports. The "unlikely" port of the first probe is 33434, then for each next probe it is incremented by one. Since the ports are expected to be unused, the destination host normally returns "icmp unreach port" as a final response. (Nobody knows what happens when some application listens for such ports, though).
С TCP кстати все проще и надежнее: тестируют без полноценной установки tcp соединения. Отправляют syn, в ответ приходит или reset (порт закрыт), или syn+ack (в таком случае отвечаем reset), или тишина...
> Как все сурово...
УдалитьВидимо, они считают, наоборот. Их логика такая: по инструкции скачать программу с визуальным интерфейсом и подробным описанием шагом доступно любому пользователю с минимальным уровнем компьютерной грамотности. А вот для использования пинг или трейс роут требуется как бы больше понимания...
> Игнорировать и пробовать...
Ну так они сами же и пишут: "Nobody knows what happens when some application listens for such ports, though". То есть если мы в ответ ничего не получили от конечного хоста, то непонятно, то ли он не отвечает, то ли на порту висит программка, которая просто игнорит левые пакеты. Конечно, в этом случае мы можем взять случайно какой-то другой порт, в надежде, что он не используется, но можем ведь и второй раз попасть в подобную ситуацию. В результате остается впечатление какой-то ненадежности метода.
А вот насчет TCP-IP не понятно. Например, TCP/IP порты могут просто быть закрыты фаерволлом еще на входе во внутреннюю сеть, что бы не долбили понапрасну куда не попадя. Тогда пингануть таким образом сервер не получиться. Так что, кмк, самый достоверный способ - чистый ICMP.
Удалить> Видимо, они считают, наоборот
УдалитьПо мне так и программка, и просьба запустить ping/traceroute - это сурово, это как если электрик по телефону попросит мультиметром померить напряжение в розетки :))) Раз не могут диагностировать проблему удаленно сами (скажем пингуя со свитча перед последней мили), то пусть приезжают в удобное для клиента время, подключают что угодно вместо домашнего роутера и диагностируют. Помню в Новосибе провайдеров в доме было 3 штуки, менять можно было как перчатки. В Штатах с этим сложнее, выбирать часто особо не из чего.
> в этом случае мы можем взять случайно какой-то другой порт
Ага, именно так, только traceroute просто пытается следующий порт вместо случайного.
> В результате остается впечатление какой-то ненадежности метода
Согласен, основное, и возможно единственное, преимущество перед ICMP - это то что отправка ICMP в Unix требует прав суперпользователя, а UDP - нет. Думаю изначально именно поэтому эту утилиту кто-то написал для себя на UDP, ну а дальше она разошлась, добавился ICMP, TCP, но UDP так и остался дефолтным.
> Например, TCP/IP порты могут просто быть закрыты фаерволлом еще на входе во внутреннюю сеть
Да, но TCP traceroute обычно используют когда нужно именно убедится что есть маршрут на определенный порт и что порт никто не режет. Тот же traceroute в linux по дефолту использует 80 порт для TCP как наиболее часто открытый и проверяемый.
> самый достоверный способ - чистый ICMP.
Если нужно проверить доступность хоста - то думаю да, но вот когда нужно еще убедится что и порт не закрыт, то TCP может выручить.
> По мне так и программка, и просьба запустить ping/traceroute - это сурово, это как если электрик по телефону
Удалить> попросит мультиметром померить напряжение в розетки :)))
Ага, типа того. Я вижу тут три момент: нет спецов, которые могли бы провести диагностику удаленно или их очень мало, а провайдер достаточно большой. Второе: на доме стоит неуправляемое оборудование, так что смотреть нечего. Ну и третье, может быть самое важное: проблема плавающая, возникает в случайный момент времени, поэтому: а как? Сидеть мониторить круглосуточно невозможно. Я бы на их месте логи писал со своего оборудования, а потом бы смотрел. Но, может у них возможности или умений.
> ...пусть приезжают в удобное для клиента время
Да приезжал, нормальный вроде, вменяемый парень, да что он может сделать, если в тот момент, когда он приехал, всё работало? Побегал по проводу, проверил его, переткнул в другой порт на домовом коммутаторе. На следующий день все тоже самое. Зря, короче, парня гоняли, тут все же админ с ихней стороны должен был логи вести и диагностировать проблему.