mirror of
https://github.com/bettercap/bettercap
synced 2025-07-15 09:33:40 -07:00
170 lines
3.6 KiB
Go
170 lines
3.6 KiB
Go
package network
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/bettercap/bettercap/core"
|
|
)
|
|
|
|
var ErrNoIfaces = errors.New("No active interfaces found.")
|
|
|
|
const (
|
|
MonitorModeAddress = "0.0.0.0"
|
|
BroadcastSuffix = ".255"
|
|
BroadcastMac = "ff:ff:ff:ff:ff:ff"
|
|
IPv4MulticastStart = "01:00:5e:00:00:00"
|
|
IPv4MulticastEnd = "01:00:5e:7f:ff:ff"
|
|
)
|
|
|
|
var (
|
|
BroadcastHw = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
|
IPv4Validator = regexp.MustCompile("^[0-9\\.]+/?\\d*$")
|
|
)
|
|
|
|
func NormalizeMac(mac string) string {
|
|
var parts []string
|
|
if strings.ContainsRune(mac, '-') {
|
|
parts = strings.Split(mac, "-")
|
|
} else {
|
|
parts = strings.Split(mac, ":")
|
|
}
|
|
|
|
for i, p := range parts {
|
|
if len(p) < 2 {
|
|
parts[i] = "0" + p
|
|
}
|
|
}
|
|
return strings.Join(parts, ":")
|
|
}
|
|
|
|
func buildEndpointFromInterface(iface net.Interface) (*Endpoint, error) {
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
e := NewEndpointNoResolve(MonitorModeAddress, iface.HardwareAddr.String(), "", 0)
|
|
|
|
e.Hostname = iface.Name
|
|
e.Index = iface.Index
|
|
|
|
for _, addr := range addrs {
|
|
ip := addr.String()
|
|
|
|
if IPv4Validator.MatchString(ip) {
|
|
if strings.IndexRune(ip, '/') == -1 {
|
|
// plain ip
|
|
e.SetIP(ip)
|
|
} else {
|
|
// ip/bits
|
|
parts := strings.Split(ip, "/")
|
|
ip_part := parts[0]
|
|
bits, _ := strconv.Atoi(parts[1])
|
|
|
|
e.SetIP(ip_part)
|
|
e.SubnetBits = uint32(bits)
|
|
}
|
|
} else {
|
|
parts := strings.SplitN(ip, "/", 2)
|
|
e.IPv6 = net.ParseIP(parts[0])
|
|
if e.IPv6 != nil {
|
|
e.Ip6Address = e.IPv6.String()
|
|
}
|
|
}
|
|
}
|
|
|
|
return e, nil
|
|
}
|
|
|
|
func matchByAddress(iface net.Interface, name string) bool {
|
|
ifMac := iface.HardwareAddr.String()
|
|
if NormalizeMac(ifMac) == NormalizeMac(name) {
|
|
return true
|
|
}
|
|
|
|
addrs, err := iface.Addrs()
|
|
if err == nil {
|
|
for _, addr := range addrs {
|
|
ip := addr.String()
|
|
if ip == name || strings.HasPrefix(ip, name) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func findInterfaceByName(name string, ifaces []net.Interface) (*Endpoint, error) {
|
|
for _, iface := range ifaces {
|
|
if iface.Name == name || matchByAddress(iface, name) {
|
|
return buildEndpointFromInterface(iface)
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("No interface matching '%s' found.", name)
|
|
}
|
|
|
|
func FindInterface(name string) (*Endpoint, error) {
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
name = core.Trim(name)
|
|
|
|
if name != "" {
|
|
return findInterfaceByName(name, ifaces)
|
|
}
|
|
|
|
// user did not provide an interface name,
|
|
// return the first one with a valid ipv4
|
|
// address
|
|
for _, iface := range ifaces {
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
fmt.Printf("WTF of the day: %s", err)
|
|
continue
|
|
}
|
|
|
|
for _, address := range addrs {
|
|
ip := address.String()
|
|
if strings.Contains(ip, "127.0.0.1") == false && IPv4Validator.MatchString(ip) {
|
|
return buildEndpointFromInterface(iface)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil, ErrNoIfaces
|
|
}
|
|
|
|
func FindGateway(iface *Endpoint) (*Endpoint, error) {
|
|
output, err := core.Exec(IPv4RouteCmd, IPv4RouteCmdOpts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, line := range strings.Split(output, "\n") {
|
|
m := IPv4RouteParser.FindStringSubmatch(line)
|
|
if len(m) == IPv4RouteTokens {
|
|
return IPv4RouteIsGateway(iface.Name(), m, func(gateway string) (*Endpoint, error) {
|
|
if gateway == iface.IpAddress {
|
|
return iface, nil
|
|
} else {
|
|
// we have the address, now we need its mac
|
|
mac, err := ArpLookup(iface.Name(), gateway, false)
|
|
if err != nil {
|
|
fmt.Printf("%s\n", err)
|
|
}
|
|
return NewEndpoint(gateway, mac), nil
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("Could not detect the gateway.")
|
|
}
|