openwrt利用arp获取局域网设备IP
1. 前言
目前我们通过arp协议搜索局域网设备,根据局域网设备地址判断子设备是否在线(子设备ip为静态ip地址),所以这里简单总结一下arp的使用。
2. ARP概念
以下内容来自维基百科:
ARP:地址解析协议(英语:Address Resolution Protocol,缩写:ARP)是一个通过解析网络层地址来找寻数据链路层地址的网络传输协议,它在IPv4中极其重要。ARP最初在1982年的RFC 826(征求意见稿)[1]中提出并纳入互联网标准STD 37。ARP也可能指是在多数操作系统中管理其相关地址的一个进程。
ARP是通过网络地址来定位MAC地址。 ARP已经在很多网路层和数据链接层之间得以实现,包括IPv4,Chaosnet, DECnet和Xerox PARC Universal Packet(PUP)使用IEEE 802标准, 光纤分布式数据接口, X.25, 帧中继和异步传输模式(ATM),IEEE 802.3和IEEE 802.11标准上IPv4占了多数流量。
在IPv6中邻居发现协议(NDP)用于代替地址解析协议(ARP)。
3. arp局域网搜索设备实现思路和代码
上面我们已经说过主要是通过配置子设备为静态ip,没有静态ip的话知晓设备mac地址也可以(这也是设备不要轻易泄露mac地址的原因,容易被嗅探)。然后通过arp信息对照ip或mac来确认设备是否在线,这里有个问题时arp的信息存在2分钟左右的缓存,所以为了防止查找出的信息为缓存信息,我们可以清除缓存之后等待一段时间再获取arp信息,代码如下(不同系统和设备可能有差异,这里以openwrt为主):
package main
import (
"bufio"
"os/exec"
"strings"
"time"
"github.com/wonderivan/logger"
)
func main() {
//这里的设备名称可通过ifconfig查找
GetLANDevIP("eth0")
}
func GetLANDevIP(devName string) ([]string, error) {
//清除对应设备的arp缓存
cmd := exec.Command("ip", "neigh", "flush", "dev", devName)
output, err := cmd.CombinedOutput()
if err != nil {
logger.Error(err)
return nil, err
}
time.Sleep(time.Second * time.Duration(5))
//目前openwrt上似乎不是安装的arp命令,而是软链接的查看该文件,所以arp命令实际上应该是如下内容
cmd = exec.Command("cat", "/proc/1/net/arp")
output, err = cmd.Output()
if err != nil {
logger.Error(err)
return nil, err
}
logger.Debug(string(output))
var res []string
scanner := bufio.NewScanner(strings.NewReader(string(output)))
for scanner.Scan() {
logger.Debug(scanner.Text())
if strings.Contains(scanner.Text(), devName) {
tmp := strings.Split(scanner.Text(), " ")
res = append(res, tmp[0])
}
}
return res, nil
}
编译运行于openwrt后结果如下: