🙆
IO.selectを使ったrubyによるポートスキャン
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