Last active
April 26, 2024 01:41
-
-
Save Ultraporing/fe52981f678be6831f747c206a4861cb to your computer and use it in GitHub Desktop.
Golang implementation of an physical network interface filter usefull for packetsniffing and pcap. It provides you with the Adapter Name (in windows Friendly Name in addition) and MAC Address. Tunnels (VMs and such), loopback adapters get ignored. I updated my code from the https://github.com/regner/albiondata-client project and added an example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
ifil "./ifilter" | |
) | |
func main() { | |
physicalInterfaceList := ifil.GetAllPhysicalInterfaces() | |
fmt.Println("All Physical Network Interfaces:", physicalInterfaceList) | |
} | |
// Displays on my Windows PC: | |
// All Physical Network Interfaces: [{70:85:c2:81:12:b2:00:00 \Device\NPF_{78C88161-D74A-42E5-A0B8-EE6F815905C0} Ethernet 2}] | |
// On Linux and Mac there are no friendly names, so i replaced it with the name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ifilter | |
import ( | |
"strings" | |
) | |
type PhysicalInterface struct { | |
MACAddress string | |
Name string | |
FriendlyName string | |
} | |
// Mac Address parts to look for, and identify non physical devices. There may be more, update me! | |
var macAddrPartsToFilter []string = []string{ | |
"00:03:FF", // Microsoft Hyper-V, Virtual Server, Virtual PC | |
"0A:00:27", // VirtualBox | |
"00:00:00:00:00", // Teredo Tunneling Pseudo-Interface | |
"00:50:56", // VMware ESX 3, Server, Workstation, Player | |
"00:1C:14", // VMware ESX 3, Server, Workstation, Player | |
"00:0C:29", // VMware ESX 3, Server, Workstation, Player | |
"00:05:69", // VMware ESX 3, Server, Workstation, Player | |
"00:1C:42", // Microsoft Hyper-V, Virtual Server, Virtual PC | |
"00:0F:4B", // Virtual Iron 4 | |
"00:16:3E", // Red Hat Xen, Oracle VM, XenSource, Novell Xen | |
"08:00:27", // Sun xVM VirtualBox | |
"7A:79", // Hamachi | |
} | |
// Filters the possible physical interface address by comparing it to known popular VM Software adresses | |
// and Teredo Tunneling Pseudo-Interface. | |
func isPhysicalInterface(addr string) bool { | |
for _, macPart := range macAddrPartsToFilter { | |
if strings.HasPrefix(strings.ToLower(addr), strings.ToLower(macPart)) { | |
return false | |
} | |
} | |
return true | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// +build linux darwin | |
package ifilter | |
import ( | |
"net" | |
"fmt" | |
) | |
// Gets all physical interfaces based on filter results, ignoring all VM, Loopback and Tunnel interfaces. | |
func GetAllPhysicalInterfaces() []PhysicalInterface { | |
ifaces, err := net.Interfaces() | |
if err != nil { | |
fmt.Println(err) | |
return nil | |
} | |
var outInterfaces []PhysicalInterface | |
for _, element := range ifaces { | |
if element.Flags&net.FlagLoopback == 0 && element.Flags&net.FlagUp == 1 && isPhysicalInterface(element.HardwareAddr.String()) { | |
outInterfaces = append(outInterfaces, PhysicalInterface{MACAddress:element.HardwareAddr.String(), Name:element.Name, FriendlyName:element.Name}) | |
} | |
} | |
return outInterfaces | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// +build windows | |
package ifilter | |
import ( | |
"os" | |
"syscall" | |
"unicode/utf16" | |
"unsafe" | |
"golang.org/x/sys/windows" | |
) | |
const ( | |
IfOperStatusUp = 1 | |
IF_TYPE_SOFTWARE_LOOPBACK = 24 | |
IF_TYPE_TUNNEL = 131 | |
) | |
const hexDigit = "0123456789abcdef" | |
func adapterAddresses() ([]*windows.IpAdapterAddresses, error) { | |
var b []byte | |
l := uint32(15000) // recommended initial size | |
for { | |
b = make([]byte, l) | |
err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l) | |
if err == nil { | |
if l == 0 { | |
return nil, nil | |
} | |
break | |
} | |
if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW { | |
return nil, os.NewSyscallError("getadaptersaddresses", err) | |
} | |
if l <= uint32(len(b)) { | |
return nil, os.NewSyscallError("getadaptersaddresses", err) | |
} | |
} | |
var aas []*windows.IpAdapterAddresses | |
for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next { | |
aas = append(aas, aa) | |
} | |
return aas, nil | |
} | |
func bytePtrToString(p *uint8) string { | |
a := (*[10000]uint8)(unsafe.Pointer(p)) | |
i := 0 | |
for a[i] != 0 { | |
i++ | |
} | |
return string(a[:i]) | |
} | |
func physicalAddrToString(physAddr [8]byte) string { | |
if len(physAddr) == 0 { | |
return "" | |
} | |
buf := make([]byte, 0, len(physAddr)*3-1) | |
for i, b := range physAddr { | |
if i > 0 { | |
buf = append(buf, ':') | |
} | |
buf = append(buf, hexDigit[b>>4]) | |
buf = append(buf, hexDigit[b&0xF]) | |
} | |
return string(buf) | |
} | |
func cStringToString(cs *uint16) (s string) { | |
if cs != nil { | |
us := make([]uint16, 0, 256) | |
for p := uintptr(unsafe.Pointer(cs)); ; p += 2 { | |
u := *(*uint16)(unsafe.Pointer(p)) | |
if u == 0 { | |
return string(utf16.Decode(us)) | |
} | |
us = append(us, u) | |
} | |
} | |
return "" | |
} | |
// Gets all physical interfaces based on filter results, ignoring all VM, Loopback and Tunnel interfaces. | |
func GetAllPhysicalInterfaces() []PhysicalInterface { | |
aa, _ := adapterAddresses() | |
var outInterfaces []PhysicalInterface | |
for _, pa := range aa { | |
mac := physicalAddrToString(pa.PhysicalAddress) | |
name := "\\Device\\NPF_" + bytePtrToString(pa.AdapterName) | |
if pa.IfType != uint32(IF_TYPE_SOFTWARE_LOOPBACK) && pa.IfType != uint32(IF_TYPE_TUNNEL) && | |
pa.OperStatus == uint32(IfOperStatusUp) && isPhysicalInterface(mac) { | |
outInterfaces = append(outInterfaces, PhysicalInterface{MACAddress:mac, Name:name, FriendlyName:cStringToString(pa.FriendlyName)}) | |
} | |
} | |
return outInterfaces | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment