代码

package main

import (
    "bufio"
    "fmt"
    "io"
    "log"
    "net"
    "os"
    "strconv"
    "strings"
    "time"

    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "github.com/google/gopacket/pcap"
)

var (
    snapshotLen int32         = 1024
    promiscuous bool          = false
    err         error
    timeout     time.Duration = 30 * time.Second
    handle      *pcap.Handle

    ipMap  = make(map[string]string)
    macMap = make(map[string]string)

    logEnabled bool = true
    logger     *log.Logger
)

func main() {
    // 创建日志文件
    logFile, err := os.OpenFile("log.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
    if err != nil {
        log.Fatal(err)
    }
    defer logFile.Close()

    // 创建一个新的日志记录器
    logger = log.New(io.MultiWriter(os.Stdout, logFile), "", log.LstdFlags)

    // 设置输出编码为UTF-8
    logger.SetPrefix("\xEF\xBB\xBF")

    // 获取所有网络接口
    devices, err := pcap.FindAllDevs()
    if err != nil {
        logger.Fatal(err)
    }

    // 打印网卡信息
    fmt.Println("Available network interfaces:")
    for i, device := range devices {
        fmt.Printf("%d. %s\n", i+1, device.Name)
        fmt.Printf("   Description: %s\n", device.Description)
        fmt.Printf("   Flags: %s\n", device.Flags)

        // 打印网卡的IP地址信息
        fmt.Printf("   IP Addresses:\n")
        for _, addr := range device.Addresses {
            if addr.IP.To4() != nil {
                fmt.Printf("     - %s\n", addr.IP.String())
            }
        }

    // 检查网卡是否已经插入线缆
    isConnected := false
    for _, addr := range device.Addresses {
        if addr.IP.IsGlobalUnicast() {
            isConnected = true
            break
        }
    }
    if isConnected {
        fmt.Printf("   Status: Connected\n")
    } else {
        fmt.Printf("   Status: Disconnected\n")
    }

        fmt.Println()
    }

    // 提示用户选择网卡
    fmt.Print("Enter the number of the interface to listen on: ")
    reader := bufio.NewReader(os.Stdin)
    input, _ := reader.ReadString('\n')
    input = strings.TrimSpace(input)

    // 解析用户输入的序号
    index, err := strconv.Atoi(input)
    if err != nil || index < 1 || index > len(devices) {
        logger.Fatal("Invalid interface number")
    }

    // 选择网卡
    device := devices[index-1]
    logger.Print("开始抓包:\r\n")

    // 打开网络接口
    handle, err = pcap.OpenLive(device.Name, snapshotLen, promiscuous, timeout)
    if err != nil {
        logger.Fatal(err)
    }
    defer handle.Close()

    packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
    for packet := range packetSource.Packets() {
        arpLayer := packet.Layer(layers.LayerTypeARP)
        if arpLayer != nil {
            arpPacket := arpLayer.(*layers.ARP)
            if arpPacket.Operation == layers.ARPReply {
                ip := net.IP(arpPacket.SourceProtAddress).String()
                mac := net.HardwareAddr(arpPacket.SourceHwAddress).String()

                if existingMAC, ok := ipMap[ip]; ok {
                    if existingMAC != mac {
                        logger.Printf("Warning: IP %s has a different MAC address: %s (previously %s)\n", ip, mac, existingMAC)
                    }
                } else {
                    ipMap[ip] = mac
                    if existingIP, ok := macMap[mac]; ok {
                        if existingIP != ip {
                            logger.Printf("Warning: MAC %s has a different IP address: %s (previously %s)\n", mac, ip, existingIP)
                        }
                    } else {
                        macMap[mac] = ip
                        logger.Printf("IP: %s, MAC: %s\n", ip, mac)
                    }
                }
            }
        }
    }
}

编译

#!/bin/bash

export GOROOT=/usr/local/go
export GOPATH=/opt/go/
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

# 定义目标操作系统和架构
targets=(
  "darwin/amd64"
  "darwin/arm64"
  "linux/386"
  "linux/amd64"
  "linux/arm"
  "linux/arm64"
  "windows/386"
  "windows/amd64"
)

# 获取Go文件名
go_file=$(ls *.go)
binary_name="${go_file%.*}"

# 编译目标文件
for target in "${targets[@]}"; do
  os_name=${target%/*}
  arch_name=${target#*/}

  output_name="${binary_name}_${os_name}_${arch_name}"
  if [ "$os_name" == "windows" ]; then
    output_name="${output_name}.exe"
  fi

  if [ "$os_name" == "linux" ]; then
    #env GOOS=$os_name GOARCH=$arch_name go build -ldflags "-linkmode external -extldflags '-static'" -o $output_name $go_file
    env GOOS=$os_name GOARCH=$arch_name go build -o $output_name $go_file
  else
    env GOOS=$os_name GOARCH=$arch_name go build -o $output_name $go_file
  fi

  if [ $? -eq 0 ]; then
    echo "Successfully built $output_name"
  else
    echo "Failed to build $output_name"
  fi
done

go mod init lanipcollect
go mod tidy
go get -u
./build_all.sh

下载

https://d2.sddts.cn/download/jingan/lan_ip_collect

运行

./lanipcollect

测试

最后修改:2024 年 06 月 05 日
如果觉得我的文章对你有用,请随意赞赏