Я прочитал в группе Python вопрос «Как узнать, открыт TCP-порт или нет на удаленном сервере».

Мой ответ, который был проигнорирован, звучал так: «Проверить очень просто, просто откройте соединение и найдите ответ».

Ответ, который был принят, был «создать канал для nmap». Кажется, это единственный ответ, который все (кроме меня) дали и приняли.

Поэтому я спросил себя: «Почему так многие боятся программирования сокетов?!».

Как проверить, открыт ли порт TCP?

Давайте начнем и разберемся, как работает TCP.

3-стороннее рукопожатие

При чтении сетевых спецификаций участвуют как минимум два персонажа, и я не собираюсь прекращать это делать, так что познакомьтесь с Алисой и Бобом :-)

Алиса хочет связаться с Бобом по заданному каналу (порту), поэтому Алиса отправляет SYN. Боб, если хотите, ответьте Алисе SYN-ACK. Затем Алиса отправляет ACK, и между ними происходит рукопожатие, получившее название 3-стороннего рукопожатия.

TCP против UDP

Трехстороннее рукопожатие существует для TCP, но не для UDP. UDP не отправляет рукопожатие, и если сервер отвечает правильной полезной нагрузкой, вы знаете, что сервер жив. Если сервер не отправляет никакого ответа, невозможно узнать, есть ли доступ к серверу или нет.

Моя реализация

Моя реализация проста и наивна.

Наивный путь

Чтобы узнать, открыт ли порт, нужно открыть соединение для :-)

Однако текущая реализация, которую я создал, заключается в том, чтобы сначала разрешить IP-адрес из записей DNS, а затем использовать timeout для соединения. Когда инициированное соединение не имеет надлежащего 3-стороннего рукопожатия, оно может не восстановиться в течение длительного времени (почти навсегда), поэтому срабатывает timeout, и мы «знаем», что соединение closed.

Когда открытый запрос возвращается, что-то фильтрует запрос (брандмауэр?).

«Наивный» способ — угадывать значение каждого типа «ошибки» и переводить его в статус запроса.

Исходный код

Мой исходник находится на github (https://github.com/ik5/port_scanner).
Я постоянно добавляю в него новые языки программирования, дающие пример.

На момент написания этой записи в блоге я написал примеры со следующими языками программирования:

  1. Рубин
  2. Голанг
  3. питон
  4. Перл
  5. Javascript (узел)
  6. PHP

PR для дополнительных примеров более чем приветствуется :)