为了账号安全,请及时绑定邮箱和手机立即绑定

Golang - 获取网络接口的混杂模式状态

Golang - 获取网络接口的混杂模式状态

Go
白衣染霜花 2021-11-22 19:39:35
我使用以下 Go 代码来获取有关网络接口的一些信息。关于如何获得每个界面的混杂模式状态的任何建议?type Iface struct {  Name      string `json:"name"`  Status    string `json:"status"`  Multicast bool   `json:"multicast"`  Broadcast bool   `json:"broadcast"`}func (c *InterfacesController) GetInterfaces() {  interfaces, err := net.Interfaces()  if err != nil {    fmt.Println(err)    return  }  var ifaceset []Iface  var ifc Iface  for _, i := range interfaces {    ifc.Name = i.Name    if strings.Contains(i.Flags.String(), "up") {        ifc.Status = "UP"    } else {        ifc.Status = "DOWN"    }    if strings.Contains(i.Flags.String(), "multicast") {        ifc.Multicast = true    } else {        ifc.Multicast = false    }    if strings.Contains(i.Flags.String(), "broadcast") {        ifc.Broadcast = true    } else {        ifc.Broadcast = false    }    ifaceset = append(ifaceset, ifc)  }}
查看完整描述

2 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

Go 似乎没有跨平台的方式来检查 PROMISC 标志(我什至无法确定 Windows 是否存在这样的标志。)这是在 linux 上获取它的一种方法,我正在猜你在:


package main


import (

    "fmt"

    "net"

    "os"

    "syscall"

    "unsafe"

)


func GetPromiscuous(i net.Interface) (bool, error) {

    tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)

    if err != nil {

        return false, os.NewSyscallError("netlinkrib", err)

    }

    msgs, err := syscall.ParseNetlinkMessage(tab)

    if err != nil {

        return false, os.NewSyscallError("parsenetlinkmessage", err)

    }

loop:

    for _, m := range msgs {

        switch m.Header.Type {

        case syscall.NLMSG_DONE:

            break loop

        case syscall.RTM_NEWLINK:

            ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))

            if ifim.Index == int32(i.Index) {

                return (ifim.Flags & syscall.IFF_PROMISC) != 0, nil

            }

        }

    }

    return false, os.ErrNotExist

}


func main() {

    ints, err := net.Interfaces()

    if err != nil {

        panic(err)

    }


    for _, i := range ints {

        p, err := GetPromiscuous(i)

        if err != nil {

            panic(err)

        }

        fmt.Println(i.Name, p)

    }

}

这是基于interfaceTable标准库中的函数。它用于rtnetlink获取接口的标志。除非您想推出自己的syscall.NetlinkRIB功能,否则此代码将始终为每个网络设备提取信息并过滤掉请求的设备。


获得所需标志的一种不太神奇的方法是使用 cgo 和 ioctl:


package main


/*

#include <stdlib.h>

#include <stdbool.h>

#include <string.h>

#include <sys/socket.h>

#include <sys/ioctl.h>

#include <net/if.h>


bool is_promisc(char *name) {

    int s = socket(AF_INET, SOCK_STREAM, 0);

    struct ifreq *i = malloc(sizeof *i);


    strncpy((char *)&(i->ifr_name), name, IFNAMSIZ);


    ioctl(s, SIOCGIFFLAGS, i);


    bool p = (i->ifr_flags & IFF_PROMISC) != 0;


    free(i);


    return p;

}

*/

import "C"

import (

    "fmt"

    "net"

)


func GetPromiscuous(i net.Interface) (bool, error) {

    set, err := C.is_promisc(C.CString(i.Name))

    return bool(set), err

}


func main() {

    ints, err := net.Interfaces()

    if err != nil {

        panic(err)

    }


    for _, i := range ints {

        p, err := GetPromiscuous(i)

        if err != nil {

            panic(err)

        }

        fmt.Println(i.Name, p)

    }


}

最后要注意的是,无论哪种方式都可能无法始终正确地告诉您接口实际上是否处于混杂模式。有关更多详细信息,请参阅此线程。


从我阅读的内容来看,使用 netlink 路由应该可以正常工作,但另一篇文章说我们应该检查混杂计数。如果有人知道怎么做,请告诉我,因为我找不到怎么做。关于这个问题的唯一 stackoverflow 问题没有得到解答。


我认为只要您不做任何疯狂的网络事情(网桥、vlan 接口、macvtap 等),这些方法中的任何一种都可以工作。如果您使用 iproute2 工具在接口上打开和关闭 promisc,则代码肯定有效。


查看完整回答
反对 回复 2021-11-22
?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

工作环境是Ubuntu,我用了ifconfig命令,查看了各个界面的详细信息,看是否包含PROMISC. 像这样的东西:


//

// get the interfaces

//

interfaces, err := net.Interfaces()


//

// run the ifconfig command

//

out, err := exec.Command("/bin/sh", "-c", "ifconfig").Output()


var ifc Iface

var ifaceset []Iface


//

// split the output to handle each interface separately

//

var ifaceDetails = strings.Split(string(out), "\n\n")


//

// iterate interfaces

//

for _, i := range interfaces {

    ifc.Name = i.Name

    if strings.Contains(i.Flags.String(), "up") {

    ifc.Status = "UP"

    } else {

        ifc.Status = "DOWN"

    }

    if strings.Contains(i.Flags.String(), "multicast") {

        ifc.Multicast = true

    } else {

        ifc.Multicast = false

    }

    if strings.Contains(i.Flags.String(), "broadcast") {

        ifc.Broadcast = true

    } else {

        ifc.Broadcast = false

    }


    //

    // try to find the word PROMISC to check if it is UP

    //

    for _, ifdetails := range ifaceDetails {

        if strings.Contains(ifdetails, i.Name) {

            if strings.Contains(ifdetails, "PROMISC") {

                ifc.Promisc = true

            } else {

                ifc.Promisc = false

            }


        }

    }

    ifaceset = append(ifaceset, ifc)

}

}


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 419 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信