6.1 列出网络上所有活跃的主机

当网络首次接入一些新的设备,而且这些设备不是像手机、电脑一类的有屏幕设备,如服务器、Nas、树莓派等硬件,想要通过网络连接控制,但是并不知道设备的 IP 地址,这时,就需要扫描网络找到目标硬件设备的 IP 地址。

常用的方法如进入路由器管理后台,就可以找到设备 IP 地址,或者使用现成的软件,如Adbanced IP Scanner软件,也可以扫描网络实现想要的目标。

下面使用 Python 编写一个查找内网存活在线主机IP地址的脚本。

NMAP

Nmap 是一款用于网络发现和安全审计的网络安全工具,可以检测目标主机是否在线、端口开放情况、侦测运行的服务类型及版本信息、侦测操作系统与设备类型等信息。

安装时用:

pip install nmap
pip install python-nmap

如果提示gdbm没有,则需要如下安装:

sudo apt-get install python3.6-gdbm
apt install nmap

安装后可以查看安装结果:

root@liu-ubuntu:~# nmap -V

Nmap version 7.01 ( https://nmap.org )
Platform: x86_64-pc-linux-gnu
Compiled with: liblua-5.2.4 openssl-1.0.2g libpcre-8.38 libpcap-1.7.4 nmap-libdnet-1.12 ipv6
Compiled without:
Available nsock engines: epoll poll select

可以通过nmap的一些方法进行网络信息的查询:

import nmap 

# 获取 PortScanner 对象
nm = nmap.PortScanner() 

# 扫描主机 127.0.0.1 端口号 22-443
nm.scan('127.0.0.1', '22-443')  
# 获取用于扫描的命令行:nmap -oX - -p 22-443 127.0.0.1
nm.command_line() 
# 获取本次扫描的信息 {'tcp': {'services': '22-443', 'method': 'connect'}}
nm.scaninfo()
# 获取所有扫描到的主机
nm.all_hosts()
# 获取 127.0.0.1 的主机名
nm['127.0.0.1'].hostname() 
# 获取list格式的主机名dict 127.0.0.1
# 如 [{'name':'hostname1', 'type':'PTR'}, {'name':'hostname2', 'type':'user'}]
nm['127.0.0.1'].hostnames() 
# 获取主机 127.0.0.1 的状态 (up|down|unknown|skipped)
nm['127.0.0.1'].state() 
# 获取所有tcp端口
nm['127.0.0.1']['tcp'].keys() 
# 获取所有tcp端口 (已排序)
nm['127.0.0.1'].all_tcp() 
# 获取所有udp端口 (已排序)
nm['127.0.0.1'].all_udp() 
# 获取所有ip端口 (已排序)
nm['127.0.0.1'].all_ip()
# 获取所有sctp端口 (已排序)
nm['127.0.0.1'].all_sctp()
# 是否含有主机 127.0.0.1 的 22 端口的信息
nm['127.0.0.1'].has_tcp(22) 
# 获取主机 127.0.0.1 22 端口(tcp)的所有信息
nm['127.0.0.1']['tcp'][22] 
# 获取主机 127.0.0.1 22 端口的所有信息
nm['127.0.0.1'].tcp(22) 
# 获取主机 127.0.0.1 22 端口(tcp)的状态 (open|closed|filter)
nm['127.0.0.1']['tcp'][22]['state']

编写代码如下:

#!/usr/bin/python3
import netifaces
import nmap

nm = nmap.PortScanner()
nm.scan(hosts='192.168.31.0/24', arguments='-n -sP -PE -PA21,23,80,3389')
hosts_list = [(x, nm[x]['status']['state']) for x in nm.all_hosts()]
for host, status in hosts_list:
    print('{0}:{1}'.format(host, status))

运行结果为:

192.168.31.1:up
192.168.31.119:up
192.168.31.165:up
192.168.31.199:up
192.168.31.71:up