Edited at

[Nmap][Ruby] nmap -sP の実行結果を Ruby で見やすく加工する


概要

Nmap をインストールして

nmap -sP ネットワークアドレス

というコマンドを実行すると、LAN 内の端末と割り当てられた IP アドレスを調べることができる。

$ sudo nmap -sP 192.168.0.0/24

Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-12 21:26 JST

Nmap scan report for 192.168.0.1
Host is up (0.0049s latency).
MAC Address: 90:F3:05:AC:EE:B6 (Humax)
Nmap scan report for 192.168.0.11
Host is up (0.0066s latency).
MAC Address: 34:AF:2C:25:A9:25 (Nintendo)
Nmap scan report for 192.168.0.12
Host is up (0.0056s latency).
MAC Address: 70:9E:29:82:0E:2C (Sony Interactive Entertainment)
Nmap scan report for 192.168.0.23
Host is up (0.041s latency).
MAC Address: F0:99:B6:88:88:97 (Unknown)
Nmap scan report for 192.168.0.13
Host is up.
Nmap done: 256 IP addresses (5 hosts up) scanned in 3.40 seconds

ただどうにも視認性が悪い。どの端末がどの IP アドレスなのかが分かりづらい :worried:

そこで Ruby を使って実行結果をわかりやすく加工してみた。


Ruby スクリプト


コード

#! /usr/bin/env ruby

require 'open3'

NETWORK_ADRESS = '192.168.0.0/24'.freeze

class NmapResult
IP_ADDRESS_PATTERN = /\d+\.\d+\.\d+\.\d+/.freeze

attr_reader :lines

def self.parse(stdout)
_header, *lines, _footer = *stdout.split("\n")
lines
.slice_when { |_l1, l2| l2.match?(IP_ADDRESS_PATTERN) }
.map { |partial_lines| NmapResult.new(partial_lines) }
end

def initialize(lines)
@lines = lines
end

def ip
lines[0][IP_ADDRESS_PATTERN]
end

def mac_address
return nil unless lines[2]

lines[2][/([\dA-F]{2}:){5}[\dA-F]{2}/]
end

def device
return nil unless lines[2]

lines[2][/(?<=\()[\w\s]+(?=\))/]
end
end

stdout, = Open3.capture2("sudo nmap -sP #{NETWORK_ADRESS}")
results = NmapResult.parse(stdout)
results.each_with_index do |result, i|
puts if i.positive?
puts(result.ip)
if result.device
puts("#{result.device} (#{result.mac_address})")
else
puts('この端末')
end
end


実行結果

$ ruby nmap.rb  

192.168.0.1

Humax (90:F3:05:AC:EE:B6)

192.168.0.11
Nintendo (34:AF:2C:25:A9:25)

192.168.0.12
Sony Interactive Entertainment (70:9E:29:82:0E:2C)

192.168.0.23
Unknown (F0:99:B6:88:88:97)

192.168.0.13
この端末

見やすくなった 🤗