Rubyでポートスキャナーを作成する方法
なぜポートスキャナーを作成したいのですか?
ポートスキャナーを作成することは、トランスポート層であるTCPプロトコルの基本を学ぶための優れた方法です。 ほとんどのインターネットプロトコル(HTTPおよびSSHを含む)で使用されます。
Rubyネットワークプログラミングがどのように機能するかを学ぶのも良い練習です。
ポートについて話すことから始めましょう!
ポートとは何ですか?
ポートについて話すとき、私たちは本当に何について話しているのですか? O.S.の港(オペレーティングシステム)レベルは、プロセスに関連付けられた単なる「ファイル記述子」です。
ファイル記述子 stdout
のように、開いているI/Oチャネルを参照するために使用される単なる数値です。 (標準出力)、ネットワークソケットまたはファイル。
OSはTCP/IPパケットを受信すると、宛先ポートを調べて、このポートでリッスンしているプロセスを見つけようとします。
次に、リスニングプロセスがある場合、パケットはそれに配信されます。
ポート範囲
合計で65.535のポートが利用可能ですが、実際にはすべてが定期的に使用されているわけではありません。
ポートは3つのグループに分けることができます:
1-1023 | 22(SSH)、80(HTTP)、443(HTTPS) |
1024-49151 | 3306(MySQL)、5432(PostgreSQL) |
49152-65535 | Chrome、Firefox |
2番目の範囲のポートは、IANA(Internet Assigned Numbers Authority)によって割り当てられます。
また、3番目の範囲は「動的」または「エフェメラル」ポートに使用されます。これらは、接続のクライアント側がサーバーからデータを受信するために使用するポートです。
TCP通信の基本
これで、ポートについて詳しく知ることができますが、ポートスキャナーを作成する準備はまだできていません。
まず、ポートが開いていることの意味について説明する必要があります。次に、ネットワークレベルで開いているポートと閉じているポートの両方の動作を調べて、それらを区別できるようにします。
ポートが開いているかどうかをどのように知ることができますか?
ポートが開いているということは、もう一方の端でリッスンしているアプリケーションがあり、それにアクセスできる(ファイアウォールによってブロックされていない)ことを意味します。
新しいTCP接続がどのように開始されるかを見てみましょう。
新しいTCP接続はSYN
で開始されます パケット。このパケットは、新しい接続の開始を象徴しています。
考えられる結果は3つあります :
- サーバーは
SYN/ACK
で応答します –これは、接続を確立する準備ができていることを意味します - サーバーは
RST
で応答します パケット–これは接続が拒否されることを意味します - サーバーはまったく応答しません(一部のファイアウォールはこれをDROPポリシーとして実装しています)
クライアントがSYN/ACK
を受信した場合 パケットを送信すると、ACK
を送信して接続の確立を完了できます。 パケット。
これは「スリーウェイハンドシェイク」と呼ばれます 「。
注 :これを監視するための優れた方法は、tcpdumpやwiresharkなどのネットワークツールを使用することです。これらのツールを使用すると、システムに出入りするすべてのパケットを確認できます。
これがtsharkからの接続例です (wiresharkのコマンドラインインターフェイス):
TCP接続がどのように確立されるかについての基本的な理解ができたので、簡単なポートスキャナーを作成できます。
ポートスキャナーを書きましょう!
スキャナーを作成する最も簡単な方法は、TCPSocket
を使用して新しいTCP接続を開くことです。 &次に、拒否された接続によってErrno::ECONNREFUSED
が発生するという事実に依存します 例外。
ここにコードがあります :
require 'socket' PORT = ARGV[0] || 22 HOST = ARGV[1] || 'localhost' begin socket = TCPSocket.new(HOST, PORT) status = "open" rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT status = "closed" end puts "Port #{PORT} is #{status}."
このコードにはいくつかの制限があります:
一度にスキャンできるポートは1つだけです。多くの場合、特定のホストで公開されているサービスをより正確に把握するために、さまざまなポートをスキャンする必要があります。
このコードのもう1つの制限は、応答しないポート(前述の結果の3分の1)では、接続がタイムアウトするまで約20秒待機することです。
これは、connect_nonblock
の組み合わせで解決できます。 、IO.select
&Socket
(TCPSocket
の代わりに 、オブジェクトを作成するとすぐに接続を開始します。
例 :
require 'socket' TIMEOUT = 2 def scan_port(port) socket = Socket.new(:INET, :STREAM) remote_addr = Socket.sockaddr_in(port, 'www.example.com') begin socket.connect_nonblock(remote_addr) rescue Errno::EINPROGRESS end _, sockets, _ = IO.select(nil, [socket], nil, TIMEOUT) if sockets p "Port #{port} is open" else # Port is closed end end PORT_LIST = [21,22,23,25,53,80,443,3306,8080] threads = [] PORT_LIST.each { |i| threads << Thread.new { scan_port(i) } } threads.each(&:join)
IO.select
呼び出しは、ソケットがデータを受信する準備ができるまで(つまり、ソケットが開いているまで)、またはTIMEOUT
まで待機します。 時間が経過した後、ポートが閉じているか、接続要求を無視していると見なすことができます。
したがって、これはすべて学習演習としては優れていますが、適切なポートスキャナーが必要な場合は、nmapなどを使用する必要があります。
Nmapはオープンソースであり、15年以上にわたって活発に開発されています。
nmap出力は次のようになります:
たくさんの情報があることを知っているので、この投稿から学んだ2つの新しいことを覚えておくためにコメントを書いてください🙂
概要
この投稿では、ポートとは何か、使用可能なさまざまなポート範囲、TCP接続の開始方法(3ウェイハンドシェイク)、およびRubyを使用した基本的なポートスキャナーの作成方法について学習しました。
この投稿を楽しんだら、もっと多くの人が楽しめるように共有することを忘れないでください🙂
-
RubyでStructとOpenStructを使用する方法
Rubyの構造体とは何ですか? 構造体は組み込みのRubyクラスであり、値オブジェクトを生成する新しいクラスを作成するために使用されます。値オブジェクトは、関連する属性を一緒に格納するために使用されます。 ここに例があります : Point 2つの座標(x &y 。 このデータはさまざまな方法で表すことができます。 いいね : 配列[10, 20] ハッシュ{ x: 10, y: 10 } オブジェクトPoint.new(10, 20) 複数のPointを使用する場合 、オブジェクトアプローチを使用することをお勧めします。 しかし… これら2つの値を一緒に格納するた
-
Rubyでファイルを読み書きする方法(例付き)
今日は、Rubyでファイルを読み書きして、コンテンツを抽出し、新しいファイルを作成し、必要な情報を見つける方法を学びます。 これから説明します : コンテンツ 1Rubyでファイルを読み取る方法 2Rubyでファイルに書き込む方法 3つのRubyファイルメソッド 4つのディレクトリ操作 5FileUtilsモジュールの使用方法 6まとめ 6.1関連 やってみましょう! Rubyでファイルを読み取る方法 次のようにRubyでファイルを読み取ることができます: ファイルを開く 、open メソッド。 ファイルを読む 、ファイル全体、行ごと、または特定のバイト数。 ファイルを