2015-11-26 1 views
2

J'utilise le code Go suivant pour obtenir des informations sur les interfaces réseau. Des suggestions sur la façon dont je serais en mesure d'obtenir le statut de mode promiscuous pour chaque interface?Golang - obtient l'état en mode promiscuité des interfaces réseau

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) 
    } 
} 

Répondre

2

L'environnement de travail est Ubuntu, j'ai utilisé la commande ifconfig et vérifié les détails de chaque interface pour voir si elle contient le mot PROMISC. Quelque chose comme ceci:

// 
// 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) 
} 

}

1

Il ne semble pas Go a une façon multiplateforme de vérifier le drapeau PROMISC (je ne peux même pas savoir à coup sûr si un tel indicateur existe pour les fenêtres.) Voici une façon de l'obtenir sur linux, que je devine que vous êtes sur:

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) 
    } 
} 

Ceci est basé de la fonction interfaceTable dans la bibliothèque standard. Il utilise rtnetlink pour obtenir les drapeaux de l'interface. À moins que vous ne souhaitiez lancer votre propre fonction syscall.NetlinkRIB, ce code extrait toujours les informations de chaque périphérique réseau et filtre les informations demandées.

Un peu moins de façon magique pour obtenir le drapeau que vous voulez est d'utiliser CGO et 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) 
    } 

} 

Une note finale est que de toute façon ne peut pas toujours vous dire correctement si une interface est en fait en mode promiscuous ou pas. Voir this thread pour plus de détails. D'après ce que je lis en utilisant la route netlink devrait fonctionner correctement, mais un autre message dit que nous devrions vérifier le nombre promiscuous. S'il vous plaît laissez-moi savoir si quelqu'un sait comment faire cela, parce que je ne peux pas trouver comment. Le only stackoverflow question sur le sujet a gone unanswered.

Je pense que l'une ou l'autre de ces méthodes fonctionnera tant que vous n'utilisez pas de réseau douteux (bridge, interfaces vlan, macvtap, etc.) Le code fonctionne si vous utilisez les outils iproute2 pour activer et désactiver le Promisc sur une interface.