
🖖 Быстрый, современный, удобный сетевой сканер
sx — это сетевой сканер командной строки, разработанный в соответствии с философией UNIX.
Цель этого проекта — создать самый быстрый сетевой сканер с чистым и простым кодом.
Самый простой способ — скачать из GitHub Releases и поместить исполняемый файл в ваш PATH.
Требования:
На macOS сначала установите Xcode Command Line Tools, чтобы CGO мог ссылаться на системную libpcap:
xcode-select --install
Из корня дерева исходников выполните:
go build
Вот краткие примеры, показывающие, как можно сканировать сети с помощью sx.
Сканируйте локальную сеть и отобразите IP-адрес, MAC-адрес и связанного производителя оборудования подключённых устройств:
sx arp 192.168.0.1/24
пример вывода:
192.168.0.1 b0:be:76:40:05:8d TP-LINK TECHNOLOGIES CO.,LTD.
192.168.0.111 80:c5:f2:0b:02:e3 AzureWave Technology Inc.
192.168.0.171 88:53:95:2d:3c:af Apple, Inc.
с выводом в JSON:
sx arp --json 192.168.0.1/24
пример вывода:
{"ip":"192.168.0.1","mac":"b0:be:76:40:05:8d","vendor":"TP-LINK TECHNOLOGIES CO.,LTD."}
{"ip":"192.168.0.111","mac":"80:c5:f2:0b:02:e3","vendor":"AzureWave Technology Inc."}
{"ip":"192.168.0.171","mac":"88:53:95:2d:3c:af","vendor":"Apple, Inc."}
подождать 5 секунд перед выходом, чтобы получить задержанные ответные пакеты (по умолчанию sx ждёт 300 миллисекунд):
sx arp --exit-delay 5s 192.168.0.1/24
Режим постоянного сканирования, который пересканирует сеть каждые 10 секунд:
sx arp 192.168.0.1/24 --live 10s
В отличие от nmap и других сканеров, которые неявно выполняют ARP-запросы для разрешения IP-адресов в MAC-адреса перед фактическим сканированием, sx явно использует концепцию ARP-кэша. Файл ARP-кэша — это простой текстовый файл, содержащий строку JSON на каждой строке (файл JSONL), который имеет те же поля JSON, что и описанный выше вывод ARP-сканирования в JSON. Сканирования протоколов более высокого уровня, таких как TCP и UDP, читают файл ARP-кэша из stdin, а затем начинают фактическое сканирование.
Это не только упрощает дизайн программы, но и ускоряет процесс сканирования, поскольку не нужно каждый раз выполнять ARP-сканирование.
Предположим, что фактический ARP-кэш находится в файле arp.cache. Мы можем создать его вручную или использовать ARP-сканирование, как показано ниже:
sx arp 192.168.0.1/24 --json | tee arp.cache
После того как у нас есть файл ARP-кэша, мы можем запускать сканирования протоколов более высокого уровня, такие как TCP SYN-сканирование:
cat arp.cache | sx tcp -p 1-65535 192.168.0.171
пример вывода:
192.168.0.171 22
192.168.0.171 443
В этом случае мы обнаруживаем, что порты 22 и 443 открыты.
Если во время больших сканирований вы видите send: No buffer space available, это обычно означает, что отправитель переполняет буферы ядра/raw-сокетов. Первое решение — добавить --rate и уменьшить скорость отправки, например -r 100000/s или меньше, если необходимо. В некоторых системах настройка лимитов буферов сокетов ОС также может помочь, но ограничение скорости является основным исправлением.
сканирование с выводом в JSON:
cat arp.cache | sx tcp --json -p 1-65535 192.168.0.171
пример вывода:
{"scan":"tcpsyn","ip":"192.168.0.171","port":22}
{"scan":"tcpsyn","ip":"192.168.0.171","port":443}
сканирование нескольких диапазонов портов:
cat arp.cache | sx tcp -p 1-23,25-443 192.168.0.171
или отдельных портов:
cat arp.cache | sx tcp -p 22,443 192.168.0.171
или используйте опцию --ports-file, чтобы указать файл с портами или диапазонами портов для сканирования, по одному на строку.
сканирование пар IP/порт из файла с выводом в JSON:
cat arp.cache | sx tcp --json -f ip_ports_file.jsonl
Каждая строка входного файла представляет собой строку JSON, которая должна содержать поля ip и port.
пример входного файла:
{"ip":"10.0.1.1","port":1080}
{"ip":"10.0.2.2","port":1081}
Можно указать файл ARP-кэша с помощью опций -a или --arp-cache:
sx tcp -a arp.cache -p 22,443 192.168.0.171
или перенаправление stdin:
sx tcp -p 22,443 192.168.0.171 < arp.cache
Вы также можете использовать подкоманду tcp syn вместо tcp:
cat arp.cache | sx tcp syn -p 22 192.168.0.171
Подкоманда tcp — это просто сокращение для подкоманды tcp syn, если не передана опция --flags (см. ниже).
sx поддерживает сканирование через виртуальные сетевые интерфейсы (wireguard, openvpn и т.д.), и в этом случае не обязательно использовать ARP-кэш, поскольку эти интерфейсы требуют ввода сырых IP-пакетов вместо Ethernet-кадров. Например, сканирование IP-адреса в VPN-сети:
sx tcp 10.1.27.1 -p 80 --json
Большинство сетевых сканеров пытаются интерпретировать результаты сканирования. Например, они говорят «этот порт закрыт» вместо «я получил RST». Иногда они правы. Иногда нет. Это проще для новичков, но когда вы знаете, что делаете, вы продолжаете пытаться понять, что на самом деле произошло, из интерпретации программы, особенно для более продвинутых методов сканирования.
sx пытается преодолеть эти проблемы. Он возвращает информацию обо всех ответных пакетах для TCP FIN, NULL, Xmas и пользовательских TCP-сканирований. Информация содержит IP-адрес, TCP-порт и все TCP-флаги, установленные в ответном пакете.
TCP FIN-сканирование и его другие вариации (NULL и Xmas) используют раздел 3.9 RFC793:
ПОЛУЧЕНИЕ СЕГМЕНТА
Если состояние CLOSED (т.е. TCB не существует), то
все данные во входящем сегменте отбрасываются. Входящий сегмент, содержащий RST, отбрасывается. Входящий сегмент, не содержащий RST, вызывает отправку RST в ответ. Значения полей подтверждения и последовательности выбираются так, чтобы сбросная последовательность была приемлемой для TCP, отправившего вызвавший нарушение сегмент.
поэтому закрытый порт должен возвращать пакет с флагом RST.
В этом же разделе сказано:
Если состояние LISTEN, то
...
Любой другой управляющий или несущий данные сегмент (не содержащий SYN) должен иметь ACK и, следовательно, будет отброшен обработкой ACK. Входящий сегмент RST не может быть действительным, так как он не мог быть отправлен в ответ на что-либо, отправленное этим воплощением соединения. Так что вы вряд ли попадёте сюда, но если попадёте, отбросьте сегмент и вернитесь.
ключевая фраза здесь: отбросьте сегмент и вернитесь. Таким образом, открытый порт в большинстве операционных систем отбрасывает TCP-пакет, содержащий любые флаги, кроме SYN, ACK и RST.
Давайте просканируем какой-нибудь закрытый порт с помощью TCP FIN-сканирования:
cat arp.cache | sx tcp fin --json -p 23 192.168.0.171
пример вывода:
{"scan":"tcpfin","ip":"192.168.0.171","port":23,"flags":"ar"}
Поле flags содержит все TCP-флаги в ответном пакете, где каждая буква обозначает один из TCP-флагов:
s - SYNa - ACKf - FINr - RSTp - PSHu - URGe - ECEc - CWRn - NSВ этом случае мы обнаруживаем, что порт 23 отправил ответный пакет с установленными флагами ACK и RST (типичный ответ для закрытого порта согласно rfc793).
Если мы сканируем открытый порт, ответа не будет (если только межсетевой экран не подделывает ответы).
Другие типы TCP-сканирования можно выполнять по аналогии.
TCP NULL-сканирование:
cat arp.cache | sx tcp null --json -p 23 192.168.0.171
TCP Xmas-сканирование:
cat arp.cache | sx tcp xmas --json -p 23 192.168.0.171
Можно отправлять TCP-пакеты с произвольными TCP-флагами с помощью опции --flags.
Давайте отправим TCP-пакет с флагами SYN, FIN и ACK для идентификации удалённой ОС:
cat arp.cache | sx tcp --flags syn,fin,ack --json -p 23 192.168.0.171
Windows и MacOS не ответят на этот пакет, но Linux отправит ответный пакет с флагом RST.
Возможные значения для опции --flags:
syn - SYNack - ACKfin - FINrst - RSTpsh - PSHurg - URGece - ECEcwr - CWRns - NSsx может помочь в исследовании открытых UDP-портов. UDP-сканирование использует раздел 4.1.3.1 RFC1122:
Если датаграмма прибывает по адресу UDP-порта, для которого нет ожидающего вызова LISTEN, UDP ДОЛЖНА отправить ICMP-сообщение «Порт недоступен».
Подобно TCP-сканированию, sx возвращает информацию обо всех ответных ICMP-пакетах для UDP-сканирования. Информация содержит IP-адрес, тип ICMP-пакета и код, установленный в ответном пакете.
Например, для обнаружения DNS-сервера на хосте выполните:
cat arp.cache | sx udp --json -p 53 192.168.0.171
пример вывода:
{"scan":"udp","ip":"192.168.0.171","icmp":{"type":3,"code":3}}
В этом случае мы обнаруживаем, что хост отправил ICMP-пакет с типом Destination Unreachable и кодом Port Unreachable (типичный ответ для закрытого порта согласно rfc1122).
Межсетевые экраны обычно устанавливают код ICMP, отличный от Port Unreachable, и поэтому могут быть легко обнаружены.
Иногда требуется ограничить скорость отправки генерируемых пакетов. Это можно сделать с помощью опции --rate.
Например, ограничить скорость до 1 пакета в 5 секунд:
cat arp.cache | sx tcp --rate 1/5s --json -p 22,80,443 192.168.0.171
Иногда требуется исключить некоторые IP-адреса и подсети из сканирования. Это можно сделать с помощью опции --exclude. Она указывает файл с IP-адресами или подсетями в нотации CIDR для исключения, по одному на строку.
Например, чтобы исключить адреса RFC 1918, создайте файл ips.txt со следующим содержимым:
10.0.0.0/8
172.16.0.0/16
192.168.0.0/16
Вы также можете вставлять комментарии и пустые строки:
# исключить адреса RFC 1918
10.0.0.0/8 # комментарий 1
172.16.0.0/12 # комментарий 2
192.168.0.0/16 # комментарий 3
0.0.0.0/8 # используется в процедурах инициализации (RFC 6890)
# исключить адреса RFC 5735
127.0.0.0/8 # адрес loopback
192.0.0.0/24 # зарезервированный блок для назначений протоколов IETF
224.0.0.0/4 # выделено для использования в назначениях IPv4 multicast-адресов
240.0.0.0/4 # зарезервировано для будущего использования
# исключить сеть Amazon
3.0.0.0/8
# IP-адреса также допустимы
1.1.1.1
и выполните сканирование с опцией --exclude ips.txt.
В качестве примера композиции сканирования вы можете объединить ARP и TCP SYN-сканирования для создания живого TCP-сканера портов, который периодически сканирует всю локальную сеть.
Запустите живое ARP-сканирование и сохраните результаты в файл arp.cache:
sx arp 192.168.0.1/24 --live 10s --json | tee arp.cache
В другом терминале запустите TCP SYN-сканирование:
while true; do sx tcp -p 1-65535 -a arp.cache -f arp.cache; sleep 30; done
sx может обнаруживать активные SOCKS5-прокси. Для сканирования необходимо указать диапазон IP-адресов или файл JSONL с парами IP/порт.
Например, сканирование диапазона IP-адресов:
sx socks -p 1080 10.0.0.1/16
сканирование пар IP/порт из файла с выводом в JSON:
sx socks --json -f ip_ports_file.jsonl
Каждая строка входного файла представляет собой строку JSON, которая должна содержать поля ip и port.
пример входного файла:
{"ip":"10.0.1.1","port":1080}
{"ip":"10.0.2.2","port":1081}
Вы также можете указать диапазон сканируемых портов:
sx socks -p 1080-4567 -f ips_file.jsonl
В этом случае из файла будут взяты только IP-адреса, и поле port больше не требуется.
sx help
Приветствуются вклады, вопросы и запросы на добавление новых функций.
Логотип разработан mikhailtsoy.com
Этот проект распространяется под лицензией MIT. Полный текст лицензии см. в файле LICENSE.