vtun/common/netutil/netutil.go
2022-04-07 21:52:47 +08:00

129 lines
3.1 KiB
Go

package netutil
import (
"context"
"log"
"net"
"net/http"
"net/url"
"strings"
"time"
"github.com/gobwas/ws"
"github.com/net-byte/vtun/common/config"
)
func ConnectServer(config config.Config) net.Conn {
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
var dialer net.Dialer
return dialer.DialContext(ctx, network, config.DNS)
},
}
scheme := "ws"
if config.Protocol == "wss" {
scheme = "wss"
}
u := url.URL{Scheme: scheme, Host: config.ServerAddr, Path: config.WebSocketPath}
header := make(http.Header)
header.Set("user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36")
header.Set("key", config.Key)
dialer := ws.Dialer{
Header: ws.HandshakeHeaderHTTP(header),
Timeout: time.Duration(config.Timeout) * time.Second,
}
c, _, _, err := dialer.Dial(context.Background(), u.String())
if err != nil {
log.Printf("[client] failed to dial websocket %s %v", u.String(), err)
return nil
}
return c
}
func GetPhysicalInterface() (name string, gateway string, network string) {
ifaces := getAllPhysicalInterfaces()
if len(ifaces) == 0 {
return "", "", ""
}
netAddrs, _ := ifaces[0].Addrs()
for _, addr := range netAddrs {
ip, ok := addr.(*net.IPNet)
if ok && ip.IP.To4() != nil && !ip.IP.IsLoopback() {
ipNet := ip.IP.To4().Mask(ip.IP.DefaultMask()).To4()
network = strings.Join([]string{ipNet.String(), strings.Split(ip.String(), "/")[1]}, "/")
ipNet[3]++
gateway = ipNet.String()
name = ifaces[0].Name
log.Printf("physical interface %v gateway %v network %v", name, gateway, network)
break
}
}
return name, gateway, network
}
func getAllPhysicalInterfaces() []net.Interface {
ifaces, err := net.Interfaces()
if err != nil {
log.Println(err)
return nil
}
var outInterfaces []net.Interface
for _, iface := range ifaces {
if iface.Flags&net.FlagLoopback == 0 && iface.Flags&net.FlagUp == 1 && isPhysicalInterface(iface.Name) {
netAddrs, _ := iface.Addrs()
if len(netAddrs) > 0 {
outInterfaces = append(outInterfaces, iface)
}
}
}
return outInterfaces
}
func isPhysicalInterface(addr string) bool {
prefixArray := []string{"ens", "enp", "enx", "eno", "eth", "en0", "wlan", "wlp", "wlo", "wlx", "wifi0", "lan0"}
for _, pref := range prefixArray {
if strings.HasPrefix(strings.ToLower(addr), pref) {
return true
}
}
return false
}
func LookupIP(domain string) string {
ips, err := net.LookupIP(domain)
if err != nil {
log.Println(err)
return ""
}
for _, ip := range ips {
return ip.To4().String()
}
return ""
}
func IsIPv4(packet []byte) bool {
return 4 == (packet[0] >> 4)
}
func IsIPv6(packet []byte) bool {
return 6 == (packet[0] >> 4)
}
func GetIPv4Source(packet []byte) net.IP {
return net.IPv4(packet[12], packet[13], packet[14], packet[15])
}
func GetIPv4Destination(packet []byte) net.IP {
return net.IPv4(packet[16], packet[17], packet[18], packet[19])
}
func GetIPv6Source(packet []byte) net.IP {
return net.IP(packet[8:24])
}
func GetIPv6Destination(packet []byte) net.IP {
return net.IP(packet[24:40])
}