Я прочитал в группе 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).
Я постоянно добавляю в него новые языки программирования, дающие пример.
На момент написания этой записи в блоге я написал примеры со следующими языками программирования:
- Рубин
- Голанг
- питон
- Перл
- Javascript (узел)
- PHP
PR для дополнительных примеров более чем приветствуется :)