
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など、実際のスキャンの前にIPアドレスをMACアドレスに解決するために暗黙的にARP要求を実行する他のスキャナとは異なり、sxは明示的にARPキャッシュの概念を使用します。ARPキャッシュファイルは各行にJSON文字列を含む単純なテキストファイル(JSONLファイル)であり、上記のARPスキャンJSON出力と同じJSONフィールドを持ちます。TCPやUDPなどの上位プロトコルのスキャンは、ARPキャッシュファイルを標準入力から読み取り、その後実際のスキャンを開始します。
これによりプログラムの設計が簡素化されるだけでなく、毎回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、必要に応じてさらに下げます。一部のシステムでは、OSのソケット/バッファ制限を調整することも役立ちますが、レート制限が主な修正方法です。
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オプションを使用して、スキャンするポートまたはポート範囲を1行に1つずつ指定したファイルを指定します。
ファイルから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
または標準入力リダイレクト:
sx tcp -p 22,443 192.168.0.171 < arp.cache
tcpの代わりにtcp synサブコマンドを使用することもできます:
cat arp.cache | sx tcp syn -p 22 192.168.0.171
tcpサブコマンドは、後述の--flagsオプションが渡されない限り、tcp synサブコマンドの省略形です。
sxは仮想ネットワークインターフェース(wireguard、openvpnなど)でのスキャンをサポートしており、この場合、これらのインターフェースはイーサネットフレームではなく生のIPパケットを入力として必要とするため、ARPキャッシュを使用する必要はありません。例えば、vpnネットワーク上のIPアドレスをスキャンする場合:
sx tcp 10.1.27.1 -p 80 --json
ほとんどのネットワークスキャナはスキャン結果を解釈しようとします。例えば、「このポートは閉じています」と「RSTを受信しました」ではなく言います。正しい場合もありますが、そうでない場合もあります。初心者には簡単ですが、自分が何をしているか分かっている場合、プログラムの解釈から実際に何が起こったのかを推測しようとし続けます。特に高度なスキャン手法ではそれが顕著です。
sxはこれらの問題を克服しようとしています。TCP FIN、NULL、Xmas、カスタムTCPスキャンに対して、すべての応答パケットに関する情報を返します。情報にはIPアドレス、TCPポート、応答パケットに設定されているすべてのTCPフラグが含まれます。
TCP FINスキャンとその他のバリエーション(NULLおよびXmas)は、RFC793 セクション3.9を悪用します:
SEGMENT ARRIVES
If the state is CLOSED (i.e., TCB does not exist) then
all data in the incoming segment is discarded. An incoming segment containing a RST is discarded. An incoming segment not containing a RST causes a RST to be sent in response. The acknowledgment and sequence field values are selected to make the reset sequence acceptable to the TCP that sent the offending segment.
そのため、閉じたポートはRSTフラグを持つパケットを返すはずです。
このセクションはまた次のように述べています:
If the state is LISTEN then
...
Any other control or text-bearing segment (not containing SYN) must have an ACK and thus would be discarded by the ACK processing. An incoming RST segment could not be valid, since it could not have been sent in response to anything sent by this incarnation of the connection. So you are unlikely to get here, but if you do, drop the segment, and return.
ここで重要なのは: セグメントをドロップして返す です。したがって、ほとんどのオペレーティングシステムの開いているポートは、SYN、ACK、RST以外のフラグを含むTCPパケットをドロップします。
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 - SYNフラグa - ACKフラグf - FINフラグr - RSTフラグp - PSHフラグu - URGフラグe - ECEフラグc - CWRフラグn - 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
--flagsオプションを使用して、カスタムTCPフラグを持つTCPパケットを送信することが可能です。
リモートOSのフィンガープリントを取得するために、SYN、FIN、ACKフラグを設定したTCPパケットを送信してみましょう:
cat arp.cache | sx tcp --flags syn,fin,ack --json -p 23 192.168.0.171
WindowsとMacOSはこのパケットに応答しませんが、LinuxはRSTフラグを持つ応答パケットを送信します。
--flagsオプションに指定可能な引数:
syn - SYNフラグack - ACKフラグfin - FINフラグrst - RSTフラグpsh - PSHフラグurg - URGフラグece - ECEフラグcwr - CWRフラグns - NSフラグsxは開いているUDPポートの調査に役立ちます。UDPスキャンはRFC1122 セクション4.1.3.1を悪用します:
If a datagram arrives addressed to a UDP port for which there is no pending LISTEN call, UDP SHOULD send an ICMP Port Unreachable message.
TCPスキャンと同様に、sxはUDPスキャンに対するすべての応答ICMPパケットに関する情報を返します。情報には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}}
この場合、ホストがDestination UnreachableタイプとPort Unreachableコードを持つICMP応答パケットを送信したことがわかります(rfc1122によると閉じたポートの典型的な応答)。
通常、ファイアウォールはPort Unreachableとは異なるICMPコードを設定するため、簡単に検出できます。
生成されたパケットの送信速度を制限する必要がある場合があります。これは--rateオプションで行えます。
例えば、速度を5秒間に1パケットに制限するには:
cat arp.cache | sx tcp --rate 1/5s --json -p 22,80,443 192.168.0.171
スキャンから一部のIPアドレスやサブネットを除外する必要がある場合があります。これは--excludeオプションで行えます。CIDR表記のIPまたはサブネットを除外するファイルを指定します。1行に1つずつです。
例えば、RFC 1918アドレスを除外するには、次の内容のips.txtファイルを作成します:
10.0.0.0/8
172.16.0.0/16
192.168.0.0/16
コメントや空行も挿入できます:
# exclude RFC 1918 addresses
10.0.0.0/8 # comment 1
172.16.0.0/12 # comment 2
192.168.0.0/16 # comment 3
0.0.0.0/8 # used in initialization procedures (RFC 6890)
# exclude RFC 5735 addresses
127.0.0.0/8 # loopback address
192.0.0.0/24 # reserved block for IETF protocol assignments
224.0.0.0/4 # allocated for use in IPv4 multicast address assignments
240.0.0.0/4 # reserved for future use
# exclude Amazon network
3.0.0.0/8
# ip addresses are valid as well
1.1.1.1
そして、--exclude ips.txtオプションを指定してスキャンを実行します。
スキャン合成の例として、ARPスキャンとTCP SYNスキャンを組み合わせて、LANネットワーク全体を定期的にスキャンするライブ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範囲またはIP/ポートペアを含むJSONLファイルを指定する必要があります。
例えば、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ファイルを参照してください。