這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
之前用了一個牛逼的App,叫做Fing,它可以擷取到本地區域網路裡面所有裝置的IP、MAC地址和裝置廠商。一直覺得很牛逼,今天好好想了想,發現也沒那麼多神秘。
窮舉區域網路裡的IP
區域網路IP一般有192
和10
兩種形式。一般來說,10
開始的區域網路高端一些,能容納的裝置比較多。
窮舉所有IP,有一個方式是通過trancert
命令,記錄訪問某個網站經過的路徑,那麼第一條路徑就是訪問路由器,得到路由器IP之後,按最後一部分進行窮舉。
但是這個方法有點麻煩,簡化一點的,就是擷取當前裝置在區域網路裡面的IP,以此IP進行窮舉。通過Golang擷取IP的方法可以參考[1]。擷取當前裝置IP的方式可以參考:
func ExternalIP() (string, string, error) {ifaces, err := net.Interfaces()if err != nil {return "", "", err}for _, iface := range ifaces {if iface.Flags&net.FlagUp == 0 {continue // interface down}if iface.Flags&net.FlagLoopback != 0 {continue // loopback interface}addrs, err := iface.Addrs()if err != nil {return "", "", err}for _, addr := range addrs {var ip net.IPswitch v := addr.(type) {case *net.IPNet:ip = v.IPcase *net.IPAddr:ip = v.IP}if ip == nil || ip.IsLoopback() {continue}ip = ip.To4()if ip == nil {continue // not an ipv4 address}return ip.String(), iface.HardwareAddr.String(), nil}}return "", "", errors.New("are you connected to the network?")}
Ping窮舉的IP,擷取MAC地址。
Ping窮舉的IP地址,得到線上裝置的IP,然後通過arp
協議得到裝置的MAC地址。arp
協議就是用來將IP轉換成MAC的協議。這兩步可以用在GitHub開源的github.com/j-keck/arping
包輔助實現,這個包的文檔可以參考[2]。簡單的使用如下:
func Mac(ip string) (net.HardwareAddr, time.Duration, error) {dstIP := net.ParseIP(ip)return arping.Ping(dstIP)}
擷取裝置的廠商,也就是俗稱的Vendor
這步逼格最高。我一直以為裝置的Vendor,就像HTTP協議裡面的UserAgent
,可以通過這個東西來擷取。所以有個協議可以用來得到這些東西。但是沒找到。後來發現百度知道(沒想到這個東西還是有點用的)裡面有位大哥寫了。
MAC
地址是國際上有個機構管理(好像是IEEE)的,它能保證每塊網卡有不同的MAC
地址。而它在分配這些地址的時候,也不是隨機分配的。MAC
地址有6個位元組,簡單的可以把前三個位元組用來表示廠商編號,後3個位元組用來區分廠商的網卡編號。那麼,我們就能通過前3個位元組來得到裝置的Vendor
。
在IEEE的網站上,提供了查詢方式,我把那個介面提取了出來,是向http://standards.ieee.org/cgi-bin/ouisearch
發送一個POST
的FORM
請求。還要將得到的HTML頁面進行解析,就得到了Vendor
。
func Vendor(mac string) (string, error) {macs := strings.Split(mac, ":")if len(macs) != 6 {return "", fmt.Errorf("MAC Error: %s", mac)}mac = strings.Join(macs[0:3], "-")form := url.Values{}form.Add("x", mac)form.Add("submit2", "Search!")res, err := goreq.Request{Method: "POST",Uri: "http://standards.ieee.org/cgi-bin/ouisearch",ContentType: "application/x-www-form-urlencoded",UserAgent: "Cyeam",ShowDebug: true,Body: form.Encode(),}.Do()if err != nil {return "", err}body, err := res.Body.ToString()if err != nil {return "", err}vendor := body[strings.Index(body, strings.ToUpper(mac))+len(mac):]vendor = strings.TrimLeft(vendor, "</b> (hex)")vendor = strings.TrimSpace(vendor)return strings.Split(vendor, "\n")[0], nil}
HTTP請求通過goreq
發送,FORM請求application/x-www-form-urlencoded
格式,還需要用的net/url
包。
結果
最後放上運行結果:
第一個是我當前啟動並執行裝置,網卡是Intel的,剩下的是路由器和手機。
我將上述完整的功能進行封裝,本文所涉及到的完整源碼請參考。
參考文獻
- How do I get the local IP address in Go? - Stackoverflow
- package arping - GoDoc
- go如何讀取MAC地址或硬碟ID - Golang中國
- 如何通過MAC地址查詢網路裝置的廠家和型號 - 百度知道
原文連結:探測區域網路裡面的裝置,轉載請註明來源!