
概述
當我們的網(wǎng)絡(luò)首次接入一些新的設(shè)備,而且這些設(shè)備不是像手機、電腦一類的有屏幕設(shè)備,如服務(wù)器、Nas、樹莓派等硬件,我們想要通過網(wǎng)絡(luò)連接控制,但是并不知道設(shè)備的 IP 地址,這時,我們就需要掃描網(wǎng)絡(luò)找到我們目標硬件設(shè)備的 IP 地址。
常用的方法如進入路由器管理后臺,我們就可以找到我們的設(shè)備 IP 地址,或者使用現(xiàn)成的軟件,如 Adbanced IP Scanner 軟件,也可以掃描網(wǎng)絡(luò)實現(xiàn)我們想要的目標。但是,實際上我們真正需要的僅僅是要知道設(shè)備名和 IP 地址即可,無論登錄路由器還是使用軟件,都顯得有點牛刀殺雞的感覺,因此我們嘗試使用 Python 編寫一個查找內(nèi)網(wǎng)存活在線主機IP地址的腳本。
關(guān)鍵詞 Python nmap 局域網(wǎng) 存活主機IP
NMAP
Nmap 是一款用于網(wǎng)絡(luò)發(fā)現(xiàn)和安全審計的網(wǎng)絡(luò)安全工具,可以檢測目標主機是否在線、端口開放情況、偵測運行的服務(wù)類型及版本信息、偵測操作系統(tǒng)與設(shè)備類型等信息。
在使用之前,我們需要先安裝 Nmap 軟件。對于 WIndow 系統(tǒng),可以登錄 Nmap 官網(wǎng)下載頁面 下載相應(yīng)版本安裝即可。
對于 MacOS 系統(tǒng),可以使用 HomeBrew 安裝,具體方法如下:
brew update
brew install nmap
對于 Ubuntu/Linux,可以使用 apt 來安裝,具體方法如下:
sudo apt install nmap
完成 nmap 軟件安裝后,我們在繼續(xù)安裝 python 模塊,具體方法如下:
pip install nmap
pip install python-nmap
除此之外,為了我們后面代碼的方便,我們還需要安裝一個 netifaces 模塊,具體方法如下:
pip instal netifaces
腳本代碼詳解
首先,我們可以直接使用 nmap 工具來掃描局域網(wǎng),操作如下:
# 假設(shè)本地 ip 地址范圍為 192.168.100.1 ~ 192.168.100.255
nmap 192.168.100.1-255 -sP
>>
(...省略部分內(nèi)容...)
Nmap scan report for 192.168.100.16
Host is up (0.0020s latency).
Nmap scan report for MIMAX-xiaomishouji (192.168.100.17)
Host is up (0.0019s latency).
(...省略部分內(nèi)容...)
我們可以看到,nmap 會把所有 ip 地址都掃描一遍,然后把掃描結(jié)果輸出,如果主機在線,那么就能看到主機名和其IP地址。我們也可以單獨掃描一個IP地址,具體操作如下:
# 掃描小米手機ip地址 192.168.100.17
nmap 192.168.100.17
>>
Starting Nmap 7.70 ( https://nmap.org ) at 2018-04-30 17:34 CST
Nmap scan report for MIMAX-xiaomishouji (192.168.100.17)
Host is up (0.00099s latency).
Not shown: 995 filtered ports
PORT STATE SERVICE
80/tcp open http
110/tcp open pop3
143/tcp open imap
3128/tcp open squid-http
8080/tcp open http-proxy
Nmap done: 1 IP address (1 host up) scanned in 4.39 seconds
我們不加 -sP 參數(shù),nmap 會掃描該IP的所有端口,我們可以從結(jié)果看到我的這一只小米手機開放的端口。
接下來,使用python來完成以上的操作,具體代碼如下:
import nmap
nmScan = nmap.PortScanner()
nmScan.scan(hosts='192.168.100.17', arguments='-sP')
>>
{'nmap': {'command_line': 'nmap -oX - -sP 192.168.100.17',
'scaninfo': {},
'scanstats': {'downhosts': '0',
'elapsed': '0.01',
'timestr': 'Mon Apr 30 17:39:50 2018',
'totalhosts': '1',
'uphosts': '1'}},
'scan': {'192.168.100.17': {'addresses': {'ipv4': '192.168.100.17'},
'hostnames': [{'name': 'MIMAX-xiaomishouji', 'type': 'PTR'}],
'status': {'reason': 'syn-ack', 'state': 'up'},
'vendor': {}}}}
nmScan.scan(hosts='192.168.100.16', arguments='-sP')
>>
{'nmap': {'command_line': 'nmap -oX - -sP 192.168.100.16',
'scaninfo': {},
'scanstats': {'downhosts': '0',
'elapsed': '0.01',
'timestr': 'Mon Apr 30 17:40:19 2018',
'totalhosts': '1',
'uphosts': '1'}},
'scan': {'192.168.100.16': {'addresses': {'ipv4': '192.168.100.16'},
'hostnames': [{'name': '', 'type': ''}],
'status': {'reason': 'syn-ack', 'state': 'up'},
'vendor': {}}}}
可以看到,和直接使用 nmap 一樣,如果存在主機在線,能顯示主機名字,否則主機名字為空,這樣我們就可以通過判斷結(jié)果是否存在主機名來篩選在線的主機。判斷主機名是否存在的方法也很簡單,我們根據(jù)上面的輸出獲取 name 字段,判斷其是否為空即可,代碼如下:
mScan['192.168.100.16']['hostnames'][0]['name']
>>
'' # 因為 192.168.100.16 不存在在線主機,所以輸出為空
接下來,我們只需要一個內(nèi)網(wǎng) IP 列表,然后逐個掃描判斷即可,獲取 IP 列表也很簡單,一般簡單的網(wǎng)絡(luò)環(huán)境下我們可以先獲取網(wǎng)關(guān)地址,然后通過網(wǎng)關(guān)地址來拼接 IP 列表,具體代碼如下:
import netifaces
gateway = netifaces.gateways()['default'][netifaces.AF_INET][0]
gateway
>>
'192.168.100.1'
# 拼接 IP 列表
ip_lists = []
for ip in range(1, 256):
ip_lists.append('{}{}'.format(gateway[:-1], ip))
最后,我們根據(jù)上面的IP列表逐個遍歷使用 nmap 掃描即可。
完整代碼
我們整合一下上面的思路,整理一下代碼,以下為完整代碼的展示:
# filename: lan_ip_scan.py
import netifaces
import nmap
def get_gateways():
return netifaces.gateways()['default'][netifaces.AF_INET][0]
def get_ip_lists(gateway):
ip_lists = []
for i in range(1, 256):
ip_lists.append('{}{}'.format(gateway[:-1], i))
return ip_lists
def scan_ip_survial(ip):
nmScan = nmap.PortScanner()
nmScan.scan(hosts=ip, arguments='-sP')
if nmScan[ip]['hostnames'][0]['name']:
return {'IP Address:': ip,
'Hostname:': nmScan[ip]['hostnames'][0]['name']
}
else:
return None
def get_all_survial_hosts():
survial_hosts = []
gateway = get_gateways()
ip_lists = get_ip_lists(gateway)
for ip in ip_lists:
scan_rst = scan_ip_survial(ip)
if scan_rst:
survial_hosts.append(scan_rst)
print(scan_rst)
return survial_hosts
if __name__ == '__main__':
get_all_survial_hosts()
接下來,我們嘗試以下運行腳本看一下結(jié)果:
# 因隱私問題,屏蔽結(jié)果的 host 名稱
python lan_ip_scan.py
{'IP Address:': '192.168.100.1', 'Hostname:': 'ch***n'}
{'IP Address:': '192.168.100.17', 'Hostname:': 'MIMAX-xiaomishouji'}
{'IP Address:': '192.168.100.18', 'Hostname:': '*****'}
{'IP Address:': '192.168.100.19', 'Hostname:': '***MBP'}
{'IP Address:': '192.168.100.20', 'Hostname:': '***iPhone'}
{'IP Address:': '192.168.100.21', 'Hostname:': '***-xiaomishouji'}
{'IP Address:': '192.168.100.22', 'Hostname:': '****-iPhone'}
{'IP Address:': '192.168.100.23', 'Hostname:': 'raspberrypi'}
{'IP Address:': '192.168.100.26', 'Hostname:': '**'}
到這里為止,我們就已經(jīng)完成我們使用 Python 查看局域網(wǎng)內(nèi)存活主機的探索以及代碼編寫。我們在本文中探討了 nmap 及相關(guān) python模塊的安裝,簡單的 nmap 掃描使用,以及一些腳本編寫的小技巧,希望本文能對你有用,如果文中有技術(shù)或理論的錯誤,歡迎指出交流,共同探究進步。