[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 アドレスなのかが分かりづらい

そこで 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
この端末

見やすくなった 🤗