Files
v2ray_simple/netLayer/interface_darwin.go
e1732a364fed 07b0a53a12 添加 -cvqxtvs 和 -eqxrs 命令,
分别意思是 convert QX to verysimple 和 extract QX remote servers

将圈叉的配置文件转换为verysimple格式,这样就可以更快地使用自己的vs客户端
2022-12-20 16:08:55 +08:00

255 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package netLayer
import (
"errors"
"net"
"strings"
"syscall"
"github.com/e1732a364fed/v2ray_simple/utils"
"go.uber.org/zap"
"golang.org/x/net/route"
)
func init() {
SetSystemDNS = setSystemDNS
ToggleSystemProxy = toggleSystemProxy
GetSystemProxyState = getSystemProxyState
}
/*
我们的auto route使用纯命令行方式。
sing-box 使用了另一种系统级别的方式。使用了
golang.org/x/net/route
下面给出一些参考
https://github.com/libp2p/go-netroute
https://github.com/jackpal/gateway/issues/27
https://github.com/GameXG/gonet/blob/master/route/route_windows.go
除了 GetGateway之外还可以使用更多其他代码
*/
func GetGateway() (ip net.IP, index int, err error) {
var rib []byte
rib, err = route.FetchRIB(syscall.AF_INET, syscall.NET_RT_DUMP, 0)
if err != nil {
return
}
var msgs []route.Message
msgs, err = route.ParseRIB(syscall.NET_RT_DUMP, rib)
if err != nil {
return
}
for _, m := range msgs {
switch m := m.(type) {
case *route.RouteMessage:
switch sa := m.Addrs[syscall.RTAX_GATEWAY].(type) {
case *route.Inet4Addr:
ip = net.IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
case *route.Inet6Addr:
ip = make(net.IP, net.IPv6len)
copy(ip, sa.IP[:])
}
index = m.Index
return
}
}
err = errors.New("no gateway")
return
}
// out, err = exec.Command("netstat", "-nr", "-f", "inet").Output()
// if err != nil {
// if ce := utils.CanLogErr("auto route failed"); ce != nil {
// ce.Write(zap.Error(err))
// }
// return
// }
// startLineIndex := -1
// fields := strings.Split(string(out), "\n")
// for i, l := range fields {
// if strings.HasPrefix(l, "Destination") {
// if i < len(fields)-1 && strings.HasPrefix(fields[i+1], "default") {
// startLineIndex = i + 1
// }
// break
// }
// }
// if startLineIndex < 0 {
// utils.Warn("auto route failed, parse netstat output failed,1")
// return
// }
// str := utils.StandardizeSpaces(fields[startLineIndex])
// fields = strings.Split(str, " ")
// if len(fields) <= 1 {
// utils.Warn("auto route failed, parse netstat output failed,2")
// return
// }
// routerIP := fields[1]
func GetHardwarePortByInterfaceName(str string) string {
searchStr := "Device: " + str
//List All Network Hardware on a Mac via Command Line
out, err := utils.LogRunCmd("networksetup", "-listallhardwareports")
if err == nil {
lines := strings.Split(out, "\n")
for i, l := range lines {
if l == searchStr {
l = lines[i-1]
return strings.TrimPrefix(l, "Hardware Port: ")
}
}
}
return ""
}
// helper func, call GetGateway and GetDeviceNameIndex
func GetGatewayDeviceName() (string, error) {
_, idx, err := GetGateway()
if err != nil {
return "", err
}
return GetDeviceNameIndex(idx), nil
}
// helper func, call GetGatewayDeviceName and utils.GetDarwinNetAdapterNameByInterfaceName.
//
// hardwarePort 和 interface的名称不同hardwareport是 Wi-Fi, 而interface.Name 是 en0
func GetDefaultHardwarePort() (string, error) {
n, e := GetGatewayDeviceName()
if e != nil {
return "", utils.ErrInErr{ErrDetail: e, ErrDesc: "GetGatewayDeviceName failed"}
}
return GetHardwarePortByInterfaceName(n), nil
}
func setSystemDNS(dns string) {
hardwareportStr, err := GetDefaultHardwarePort()
if err != nil {
if ce := utils.CanLogErr("SetSystemDNS: call GetDefaultHardwarePort failed"); ce != nil {
ce.Write(zap.Error(err))
}
return
}
utils.LogRunCmd("networksetup", "-setdnsservers", hardwareportStr, dns)
}
/*
darwin 获取wifi名称
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | grep ' SSID:' | awk '{print $2}'
*/
func GetSystemDNS() string {
hardwareportStr, err := GetDefaultHardwarePort()
if err != nil {
if ce := utils.CanLogErr("GetSystemDNS: call GetDefaultHardwarePort failed"); ce != nil {
ce.Write(zap.Error(err))
}
return ""
}
out, e := utils.LogRunCmd("networksetup", "-getdnsservers", hardwareportStr)
if e != nil {
return ""
}
return out
}
func toggleSystemProxy(isSocks5 bool, addr, port string, enable bool) {
//我们使用命令行方式。
//todo: 还可以参考 https://github.com/getlantern/sysproxy 这里用了另一种实现还用到elevate
hardwareportStr, err := GetDefaultHardwarePort()
if err != nil {
if ce := utils.CanLogErr("ToggleSystemProxy: call GetDefaultHardwarePort failed"); ce != nil {
ce.Write(zap.Error(err))
}
return
}
if isSocks5 {
if enable {
utils.LogRunCmd("networksetup", "-setsocksfirewallproxy", hardwareportStr, addr, port)
} else {
utils.LogRunCmd("networksetup", "-setsocksfirewallproxystate", hardwareportStr, "off")
}
} else {
if enable {
utils.LogRunCmd("networksetup", "-setwebproxy", hardwareportStr, addr, port)
utils.LogRunCmd("networksetup", "-setsecurewebproxy", hardwareportStr, addr, port)
} else {
utils.LogRunCmd("networksetup", "-setwebproxystate", hardwareportStr, "off")
utils.LogRunCmd("networksetup", "-setsecurewebproxystate", hardwareportStr, "off")
}
}
}
func getSystemProxyState(isSocks5 bool) (ok, enabled bool, addr, port string) {
hardwareportStr, err := GetDefaultHardwarePort()
if err != nil {
if ce := utils.CanLogErr("ToggleSystemProxy: call GetDefaultHardwarePort failed"); ce != nil {
ce.Write(zap.Error(err))
}
return
}
var out string
if isSocks5 {
var e error
out, e = utils.LogRunCmd("networksetup", "-getsocksfirewallproxy", hardwareportStr)
if e != nil {
return
}
ok = true
} else {
var e error
out, e = utils.LogRunCmd("networksetup", "-getwebproxy", hardwareportStr)
if e != nil {
return
}
ok = true
}
strs := strings.Split(out, "\n")
if len(strs) < 1 {
return
}
if strings.Contains(strs[0], "Yes") {
enabled = true
}
if len(strs) < 3 {
return
}
if strings.Contains(strs[1], "Server: ") {
addr = strings.TrimPrefix(strs[1], "Server: ")
}
if strings.Contains(strs[2], "Port: ") {
port = strings.TrimPrefix(strs[2], "Port: ")
}
return
}