🙆

IO.selectを使ったrubyによるポートスキャン

2024/11/06に公開

IO.selectを使ったrubyによるポートスキャン

複数Socketと同時にやりとりすることで接続を多重化し、特定のSocketでブロックされるのを防ぐためにノンブロッキングIOを利用する。
また、IO.selectは同期呼び出しで、今回だと接続が完了してIO書き込み完了になったものを順次取り出すようにする。

以下にコードを記載。

require "socket"

PORT_RANGE=1...128
TIME_TO_WAIT = 5
HOST = "google.com"

# 100数個のSocketを一度に初期化する。
sockets = PORT_RANGE.map do |port|
  socket = Socket.new(:INET6, :STREAM)
  remote_addr = Socket.sockaddr_in(port, HOST)
  begin
    socket.connect_nonblock(remote_addr)
  rescue Errno::EINPROGRESS
  end
 socket
end

loop do
  # 非同期で書き込み可能になったSocketを取り出す
  _, writable = IO.select(nil, sockets, nil, TIME_TO_WAIT)
  # 書き込み可能なsocketが取り出せなくなるとポートスキャン終了
  break unless writable

  writable.each do |socket|
    begin
      socket.connect_nonblock(socket.remote_address)
    rescue Errno::EISCONN
       # 接続成功
       puts "#{HOST}:#{socket.remote_address.ip_port} accepts connections ...."
       sockets.delete(socket)
    rescue Errno::EINVAL
       # 接続失敗
       puts socket
       sockets.delete(socket)
    end
  end
end
出力結果
google.com:80 accepts connections ....

Discussion