Пишем простой и быстрый сканер IP адресов и открытых портов на Ruby (с использованием потоков)

от автора


Здравствуйте друзья!
Сегодня я попробую написать свою первую программу на замечательном, по моему мнению, языке программирования Ruby.
Эксперимент буду проводить на Debian 8.

Сканируем сеть

Итак, для начала давайте просканируем нужный нам диапазон.
Для своих целей я буду использовать Гем ipscanner.
Установим Гем (или Gem, для тех кому режет слух):

# gem install ipscanner 

Ipscanner выдает нам массив с перечисленными доступными IP.
Синтаксис у него следующий:

IPScanner.scan(ip_base = ip_first, range = range1..range2, timeout) 

Тут я думаю все понятно без слов, сделаю лишь акцент на поле ip_first — это должен быть строковый параметр, range1, range2 и timeout — это integer.

После того как мы просканируем сеть, каждый полученный IP, передаем в отдельный поток, который и будет проверять открытые порты.

Функция сканирования диапазона IP адресов и создания потоков, будет выглядеть вот так:

def scanner (ip,range1,range2,start_port,end_port)         scanned_ip=IPScanner.scan(ip_base = ip, range = range1..range2, t = 5)         allports=*(start_port..end_port)         pc_thread = []         scanned_ip.each do |ip|                 pc_thread << Thread.new(ip) do                 scanports ip, allports                 end         end         pc_thread.each {|t| t.join } end 

Все доступные IP будут в массиве scanned_ip.
Дополнительно я создам массив allports, в который запишу весь диапазон необходимых для сканирования портов.
Ну и для каждого IP адреса создам поток pc_thread, в который передам функцию сканирования портов и все необходимые порты строкой:

scanports ip, allports 

Сканируем порты

Функция сканирования портов будет выглядеть следующим образом:

def scanports(host, ports)         ports.each do |tryport|                 begin                         sock = Socket.new(:INET, :STREAM)                         puts "#{host}: #{tryport} open." if sock.connect(Socket.sockaddr_in(tryport, host))                         rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT                 end         end end 

Результатом выполнения данной функции будет надпись о том что порт открыт, если он открыт, и отвечает за это:

puts "#{host}: #{tryport} open." if sock.connect(Socket.sockaddr_in(tryport, host)) 

Код целиком

require 'ipscanner' require 'socket' require 'thread'  def scanports(host, ports)         ports.each do |tryport|                 begin                         sock = Socket.new(:INET, :STREAM)                         puts "#{host}: #{tryport} open." if sock.connect(Socket.sockaddr_in(tryport, host))                         rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT                 end         end end  def scanner (ip,range1,range2,start_port,end_port)         scanned_ip=IPScanner.scan(ip_base = ip, range = range1..range2, t = 5)         allports=*(start_port..end_port)         pc_thread = []         scanned_ip.each do |ip|                 pc_thread << Thread.new(ip) do                 scanports ip, allports                 end         end         pc_thread.each {|t| t.join } end  scanner '10.166.10.',1,254,1,70000 

Согласитесь, что это очень краткий и я надеюсь симпатичный код :).

Результатом выполнения данного кода будет:

... 10.166.10.200: 21 open. 10.166.10.110: 22 open. 10.166.10.2: 22 open. 10.166.10.171: 111 open. 10.166.10.1: 22 open. 10.166.10.151: 80 open. 10.166.10.128: 80 open. 10.166.10.137: 80 open. 10.166.10.170: 80 open. 10.166.10.159: 80 open. ... 

ссылка на оригинал статьи http://habrahabr.ru/post/265973/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *