mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00:00
Add set system proxy support for macOS
This commit is contained in:
parent
64dbac8138
commit
f691bd5ce1
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/sagernet/sing-box/common/geoip"
|
||||
"github.com/sagernet/sing-dns"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
|
@ -33,10 +34,9 @@ type Router interface {
|
|||
InterfaceBindManager() control.BindManager
|
||||
DefaultInterface() string
|
||||
AutoDetectInterface() bool
|
||||
AutoDetectInterfaceName() string
|
||||
AutoDetectInterfaceIndex() int
|
||||
DefaultMark() int
|
||||
|
||||
NetworkMonitor() tun.NetworkUpdateMonitor
|
||||
InterfaceMonitor() tun.DefaultInterfaceMonitor
|
||||
Rules() []Rule
|
||||
SetTrafficController(controller TrafficController)
|
||||
}
|
||||
|
|
1
box.go
1
box.go
|
@ -90,6 +90,7 @@ func New(ctx context.Context, options option.Options) (*Box, error) {
|
|||
logFactory.NewLogger("dns"),
|
||||
common.PtrValueOrDefault(options.Route),
|
||||
common.PtrValueOrDefault(options.DNS),
|
||||
options.Inbounds,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse route options")
|
||||
|
|
|
@ -61,27 +61,27 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
|
|||
var listener net.ListenConfig
|
||||
if options.BindInterface != "" {
|
||||
warnBindInterfaceOnUnsupportedPlatform.Check()
|
||||
dialer.Control = control.Append(dialer.Control, control.BindToInterface(router.InterfaceBindManager(), options.BindInterface))
|
||||
listener.Control = control.Append(listener.Control, control.BindToInterface(router.InterfaceBindManager(), options.BindInterface))
|
||||
bindFunc := control.BindToInterface(router.InterfaceBindManager(), options.BindInterface)
|
||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||
listener.Control = control.Append(listener.Control, bindFunc)
|
||||
} else if router.AutoDetectInterface() {
|
||||
if C.IsWindows {
|
||||
dialer.Control = control.Append(dialer.Control, control.BindToInterfaceIndexFunc(func() int {
|
||||
return router.AutoDetectInterfaceIndex()
|
||||
}))
|
||||
listener.Control = control.Append(listener.Control, control.BindToInterfaceIndexFunc(func() int {
|
||||
return router.AutoDetectInterfaceIndex()
|
||||
}))
|
||||
bindFunc := control.BindToInterfaceIndexFunc(func() int {
|
||||
return router.InterfaceMonitor().DefaultInterfaceIndex()
|
||||
})
|
||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||
listener.Control = control.Append(listener.Control, bindFunc)
|
||||
} else {
|
||||
dialer.Control = control.Append(dialer.Control, control.BindToInterfaceFunc(router.InterfaceBindManager(), func() string {
|
||||
return router.AutoDetectInterfaceName()
|
||||
}))
|
||||
listener.Control = control.Append(listener.Control, control.BindToInterfaceFunc(router.InterfaceBindManager(), func() string {
|
||||
return router.AutoDetectInterfaceName()
|
||||
}))
|
||||
bindFunc := control.BindToInterfaceFunc(router.InterfaceBindManager(), func() string {
|
||||
return router.InterfaceMonitor().DefaultInterfaceName()
|
||||
})
|
||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||
listener.Control = control.Append(listener.Control, bindFunc)
|
||||
}
|
||||
} else if router.DefaultInterface() != "" {
|
||||
dialer.Control = control.Append(dialer.Control, control.BindToInterface(router.InterfaceBindManager(), router.DefaultInterface()))
|
||||
listener.Control = control.Append(listener.Control, control.BindToInterface(router.InterfaceBindManager(), router.DefaultInterface()))
|
||||
bindFunc := control.BindToInterface(router.InterfaceBindManager(), router.DefaultInterface())
|
||||
dialer.Control = control.Append(dialer.Control, bindFunc)
|
||||
listener.Control = control.Append(listener.Control, bindFunc)
|
||||
}
|
||||
if options.RoutingMark != 0 {
|
||||
warnRoutingMarkOnUnsupportedPlatform.Check()
|
||||
|
|
|
@ -13,3 +13,9 @@ func runCommand(name string, args ...string) error {
|
|||
command.Stderr = os.Stderr
|
||||
return command.Run()
|
||||
}
|
||||
|
||||
func readCommand(name string, args ...string) ([]byte, error) {
|
||||
command := exec.Command(name, args...)
|
||||
command.Env = os.Environ()
|
||||
return command.CombinedOutput()
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
@ -30,10 +31,12 @@ func runAndroidShell(name string, args ...string) error {
|
|||
}
|
||||
}
|
||||
|
||||
func ClearSystemProxy() error {
|
||||
func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
|
||||
err := runAndroidShell("settings", "put", "global", "http_proxy", F.ToString("127.0.0.1:", port))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func() error {
|
||||
return runAndroidShell("settings", "put", "global", "http_proxy", ":0")
|
||||
}
|
||||
|
||||
func SetSystemProxy(port uint16, mixed bool) error {
|
||||
return runAndroidShell("settings", "put", "global", "http_proxy", F.ToString("127.0.0.1:", port))
|
||||
}, nil
|
||||
}
|
||||
|
|
98
common/settings/proxy_darwin.go
Normal file
98
common/settings/proxy_darwin.go
Normal file
|
@ -0,0 +1,98 @@
|
|||
package settings
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-tun"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/common/x/list"
|
||||
)
|
||||
|
||||
type systemProxy struct {
|
||||
monitor tun.DefaultInterfaceMonitor
|
||||
interfaceName string
|
||||
element *list.Element[tun.DefaultInterfaceUpdateCallback]
|
||||
port uint16
|
||||
isMixed bool
|
||||
}
|
||||
|
||||
func (p *systemProxy) update() error {
|
||||
newInterfaceName := p.monitor.DefaultInterfaceName()
|
||||
if p.interfaceName == newInterfaceName {
|
||||
return nil
|
||||
}
|
||||
if p.interfaceName != "" {
|
||||
_ = p.unset()
|
||||
}
|
||||
p.interfaceName = newInterfaceName
|
||||
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p.isMixed {
|
||||
err = runCommand("networksetup", "-setsocksfirewallproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port))
|
||||
}
|
||||
if err == nil {
|
||||
err = runCommand("networksetup", "-setwebproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port))
|
||||
}
|
||||
if err == nil {
|
||||
err = runCommand("networksetup", "-setsecurewebproxy", interfaceDisplayName, "127.0.0.1", F.ToString(p.port))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *systemProxy) unset() error {
|
||||
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p.isMixed {
|
||||
err = runCommand("networksetup", "-setsocksfirewallproxystate", interfaceDisplayName, "off")
|
||||
}
|
||||
if err == nil {
|
||||
err = runCommand("networksetup", "-setwebproxystate", interfaceDisplayName, "off")
|
||||
}
|
||||
if err == nil {
|
||||
err = runCommand("networksetup", "-setsecurewebproxystate", interfaceDisplayName, "off")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getInterfaceDisplayName(name string) (string, error) {
|
||||
content, err := readCommand("networksetup", "-listallhardwareports")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, deviceSpan := range strings.Split(string(content), "Ethernet Address") {
|
||||
if strings.Contains(deviceSpan, "Device: "+name) {
|
||||
substr := "Hardware Port: "
|
||||
deviceSpan = deviceSpan[strings.Index(deviceSpan, substr)+len(substr):]
|
||||
deviceSpan = deviceSpan[:strings.Index(deviceSpan, "\n")]
|
||||
return deviceSpan, nil
|
||||
}
|
||||
}
|
||||
return "", E.New(name, " not found in networksetup -listallhardwareports")
|
||||
}
|
||||
|
||||
func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
|
||||
interfaceMonitor := router.InterfaceMonitor()
|
||||
if interfaceMonitor == nil {
|
||||
return nil, E.New("missing interface monitor")
|
||||
}
|
||||
proxy := &systemProxy{
|
||||
monitor: interfaceMonitor,
|
||||
port: port,
|
||||
isMixed: isMixed,
|
||||
}
|
||||
err := proxy.update()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proxy.element = interfaceMonitor.RegisterCallback(proxy.update)
|
||||
return func() error {
|
||||
interfaceMonitor.UnregisterCallback(proxy.element)
|
||||
return proxy.unset()
|
||||
}, nil
|
||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
|
@ -35,42 +35,33 @@ func runAsUser(name string, args ...string) error {
|
|||
}
|
||||
}
|
||||
|
||||
func ClearSystemProxy() error {
|
||||
if hasGSettings {
|
||||
return runAsUser("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
|
||||
func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
|
||||
if !hasGSettings {
|
||||
return nil, E.New("unsupported desktop environment")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetSystemProxy(port uint16, mixed bool) error {
|
||||
if hasGSettings {
|
||||
err := runAsUser("gsettings", "set", "org.gnome.system.proxy.http", "enabled", "true")
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if mixed {
|
||||
if isMixed {
|
||||
err = setGnomeProxy(port, "ftp", "http", "https", "socks")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = setGnomeProxy(port, "http", "https")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = runAsUser("gsettings", "set", "org.gnome.system.proxy", "use-same-proxy", F.ToString(mixed))
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
err = runAsUser("gsettings", "set", "org.gnome.system.proxy", "use-same-proxy", F.ToString(isMixed))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = runAsUser("gsettings", "set", "org.gnome.system.proxy", "mode", "manual")
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
log.Warn("set system proxy: unsupported desktop environment")
|
||||
}
|
||||
return nil
|
||||
return func() error {
|
||||
return runAsUser("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
|
||||
}, nil
|
||||
}
|
||||
|
||||
func setGnomeProxy(port uint16, proxyTypes ...string) error {
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
//go:build !windows && !linux
|
||||
//go:build !(windows || linux || darwin)
|
||||
|
||||
package settings
|
||||
|
||||
import "github.com/sagernet/sing-box/log"
|
||||
import (
|
||||
"os"
|
||||
|
||||
func ClearSystemProxy() error {
|
||||
return nil
|
||||
}
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
)
|
||||
|
||||
func SetSystemProxy(port uint16, mixed bool) error {
|
||||
log.Warn("set system proxy: unsupported operating system")
|
||||
return nil
|
||||
func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package settings
|
||||
|
||||
import (
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/common/wininet"
|
||||
)
|
||||
|
||||
func ClearSystemProxy() error {
|
||||
func SetSystemProxy(router adapter.Router, port uint16, isMixed bool) (func() error, error) {
|
||||
err := wininet.SetSystemProxy(F.ToString("http://127.0.0.1:", port), "local")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func() error {
|
||||
return wininet.ClearSystemProxy()
|
||||
}
|
||||
|
||||
func SetSystemProxy(port uint16, mixed bool) error {
|
||||
return wininet.SetSystemProxy(F.ToString("http://127.0.0.1:", port), "local")
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ If `sniff_override_destination` is in effect, its value will be taken as a fallb
|
|||
|
||||
!!! error ""
|
||||
|
||||
Windows only
|
||||
Only supported on Linux, Android, Windows, and macOS.
|
||||
|
||||
Automatically set system proxy configuration when start and clean up when stop.
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ If `sniff_override_destination` is in effect, its value will be taken as a fallb
|
|||
|
||||
!!! error ""
|
||||
|
||||
Windows only
|
||||
Only supported on Linux, Android, Windows, and macOS.
|
||||
|
||||
Automatically set system proxy configuration when start and clean up when stop.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ Default outbound tag. the first outbound will be used if empty.
|
|||
|
||||
!!! error ""
|
||||
|
||||
Linux and Windows only
|
||||
Only supported on Linux and Windows.
|
||||
|
||||
Bind outbound connections to the default NIC by default to prevent routing loops under Tun.
|
||||
|
||||
|
@ -40,7 +40,7 @@ Takes no effect if `outbound.bind_interface` is set.
|
|||
|
||||
!!! error ""
|
||||
|
||||
Linux and Windows only
|
||||
Only supported on Linux and Windows.
|
||||
|
||||
Bind outbound connections to the specified NIC by default to prevent routing loops under Tun.
|
||||
|
||||
|
@ -50,7 +50,7 @@ Takes no effect if `auto_detect_interface` is set.
|
|||
|
||||
!!! error ""
|
||||
|
||||
Linux only
|
||||
Only supported on Linux.
|
||||
|
||||
Set iptables routing mark by default.
|
||||
|
||||
|
|
4
go.mod
4
go.mod
|
@ -16,7 +16,7 @@ require (
|
|||
github.com/sagernet/sing v0.0.0-20220804023557-9c64b40e7050
|
||||
github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1
|
||||
github.com/sagernet/sing-tun v0.0.0-20220803112223-a8fd6450d4ed
|
||||
github.com/sagernet/sing-tun v0.0.0-20220804154459-7ee0d19103d2
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220804023624-e829b41c84c2
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
|
@ -24,7 +24,7 @@ require (
|
|||
go.uber.org/atomic v1.9.0
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||
golang.org/x/net v0.0.0-20220802222814-0bcc04d9c69b
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d
|
||||
golang.org/x/sys v0.0.0-20220803195053-6e608f9ce704
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
8
go.sum
8
go.sum
|
@ -155,8 +155,8 @@ github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91 h1:jxt2PYixIkK2i
|
|||
github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91/go.mod h1:T77zZdE2Cm6VqnFumrpwsq+kxYsbq+vWDhmjtdSl/oM=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1 h1:RYvOc69eSNMN0dwVugrDts41Nn7Ar/C/n/fvytvFcp4=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1/go.mod h1:NqZjiXszgVCMQ4gVDa2V+drhS8NMfGqUqDF86EacEFc=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220803112223-a8fd6450d4ed h1:28qeqeuHLZEkzdcZjYwcCn8y4ckyKimaP+L4P25dqUo=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220803112223-a8fd6450d4ed/go.mod h1:jNlPidQzZYkpmpQJ+sDN2YGrPsL4QImoqBpuauId9po=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220804154459-7ee0d19103d2 h1:har8hmVNhGxp14zLNAoGrgfzgxZQn0KTYJDfJudj0RU=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220804154459-7ee0d19103d2/go.mod h1:K1Hfxaa/1zsxZix3ats3k1TJftVwK0l4OoRnUjjhi0g=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220804023624-e829b41c84c2 h1:C8sc2MYiNx0O7uQ0nieJWq5qYeIHj20XHFWPlcgoQeY=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220804023624-e829b41c84c2/go.mod h1:bNXBqSWYaG3ePl6u0xQY5zneE+ZKa3683ZpuE8S1M1w=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
|
@ -279,8 +279,8 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220803195053-6e608f9ce704 h1:Y7NOhdqIOU8kYI7BxsgL38d0ot0raxvcW+EMQU2QrT4=
|
||||
golang.org/x/sys v0.0.0-20220803195053-6e608f9ce704/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -41,6 +41,7 @@ type myInboundAdapter struct {
|
|||
// http mixed
|
||||
|
||||
setSystemProxy bool
|
||||
clearSystemProxy func() error
|
||||
|
||||
// internal
|
||||
|
||||
|
@ -60,10 +61,10 @@ func (a *myInboundAdapter) Tag() string {
|
|||
}
|
||||
|
||||
func (a *myInboundAdapter) Start() error {
|
||||
var err error
|
||||
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
|
||||
if common.Contains(a.network, N.NetworkTCP) {
|
||||
var tcpListener *net.TCPListener
|
||||
var err error
|
||||
if !a.listenOptions.TCPFastOpen {
|
||||
tcpListener, err = net.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
|
||||
} else {
|
||||
|
@ -77,7 +78,8 @@ func (a *myInboundAdapter) Start() error {
|
|||
a.logger.Info("tcp server started at ", tcpListener.Addr())
|
||||
}
|
||||
if common.Contains(a.network, N.NetworkUDP) {
|
||||
udpConn, err := net.ListenUDP(M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.UDPAddr())
|
||||
var udpConn *net.UDPConn
|
||||
udpConn, err = net.ListenUDP(M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.UDPAddr())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -101,7 +103,7 @@ func (a *myInboundAdapter) Start() error {
|
|||
a.logger.Info("udp server started at ", udpConn.LocalAddr())
|
||||
}
|
||||
if a.setSystemProxy {
|
||||
err := settings.SetSystemProxy(M.SocksaddrFromNet(a.tcpListener.Addr()).Port, a.protocol == C.TypeMixed)
|
||||
a.clearSystemProxy, err = settings.SetSystemProxy(a.router, M.SocksaddrFromNet(a.tcpListener.Addr()).Port, a.protocol == C.TypeMixed)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set system proxy")
|
||||
}
|
||||
|
@ -111,8 +113,8 @@ func (a *myInboundAdapter) Start() error {
|
|||
|
||||
func (a *myInboundAdapter) Close() error {
|
||||
var err error
|
||||
if a.setSystemProxy {
|
||||
err = settings.ClearSystemProxy()
|
||||
if a.clearSystemProxy != nil {
|
||||
err = a.clearSystemProxy()
|
||||
}
|
||||
return E.Errors(err, common.Close(
|
||||
common.PtrOrNil(a.tcpListener),
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package route
|
||||
|
||||
import "github.com/sagernet/sing/common/x/list"
|
||||
|
||||
type (
|
||||
NetworkUpdateCallback = func() error
|
||||
DefaultInterfaceUpdateCallback = func()
|
||||
)
|
||||
|
||||
type NetworkUpdateMonitor interface {
|
||||
Start() error
|
||||
Close() error
|
||||
RegisterCallback(callback NetworkUpdateCallback) *list.Element[NetworkUpdateCallback]
|
||||
UnregisterCallback(element *list.Element[NetworkUpdateCallback])
|
||||
}
|
||||
|
||||
type DefaultInterfaceMonitor interface {
|
||||
Start() error
|
||||
Close() error
|
||||
DefaultInterfaceName() string
|
||||
DefaultInterfaceIndex() int
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
//go:build !(linux || windows) || no_gvisor
|
||||
|
||||
package route
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewNetworkUpdateMonitor(errorHandler E.Handler) (NetworkUpdateMonitor, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func NewDefaultInterfaceMonitor(networkMonitor NetworkUpdateMonitor, callback DefaultInterfaceUpdateCallback) (DefaultInterfaceMonitor, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
//go:build (linux || windows) && !no_gvisor
|
||||
|
||||
package route
|
||||
|
||||
import (
|
||||
"github.com/sagernet/sing-tun"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewNetworkUpdateMonitor(errorHandler E.Handler) (NetworkUpdateMonitor, error) {
|
||||
return tun.NewNetworkUpdateMonitor(errorHandler)
|
||||
}
|
||||
|
||||
func NewDefaultInterfaceMonitor(networkMonitor NetworkUpdateMonitor, callback DefaultInterfaceUpdateCallback) (DefaultInterfaceMonitor, error) {
|
||||
return tun.NewDefaultInterfaceMonitor(networkMonitor, callback)
|
||||
}
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-dns"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
|
@ -83,16 +84,16 @@ type Router struct {
|
|||
transports []dns.Transport
|
||||
transportMap map[string]dns.Transport
|
||||
interfaceBindManager control.BindManager
|
||||
networkMonitor NetworkUpdateMonitor
|
||||
autoDetectInterface bool
|
||||
defaultInterface string
|
||||
interfaceMonitor DefaultInterfaceMonitor
|
||||
defaultMark int
|
||||
networkMonitor tun.NetworkUpdateMonitor
|
||||
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||
trafficController adapter.TrafficController
|
||||
processSearcher process.Searcher
|
||||
}
|
||||
|
||||
func NewRouter(ctx context.Context, logger log.ContextLogger, dnsLogger log.ContextLogger, options option.RouteOptions, dnsOptions option.DNSOptions) (*Router, error) {
|
||||
func NewRouter(ctx context.Context, logger log.ContextLogger, dnsLogger log.ContextLogger, options option.RouteOptions, dnsOptions option.DNSOptions, inbounds []option.Inbound) (*Router, error) {
|
||||
if options.DefaultInterface != "" {
|
||||
warnDefaultInterfaceOnUnsupportedPlatform.Check()
|
||||
}
|
||||
|
@ -231,8 +232,13 @@ func NewRouter(ctx context.Context, logger log.ContextLogger, dnsLogger log.Cont
|
|||
router.transports = transports
|
||||
router.transportMap = transportMap
|
||||
|
||||
if router.interfaceBindManager != nil || options.AutoDetectInterface {
|
||||
networkMonitor, err := NewNetworkUpdateMonitor(router)
|
||||
needInterfaceMonitor := options.AutoDetectInterface ||
|
||||
C.IsDarwin && common.Any(inbounds, func(inbound option.Inbound) bool {
|
||||
return inbound.HTTPOptions.SetSystemProxy || inbound.MixedOptions.SetSystemProxy
|
||||
})
|
||||
|
||||
if router.interfaceBindManager != nil || needInterfaceMonitor {
|
||||
networkMonitor, err := tun.NewNetworkUpdateMonitor(router)
|
||||
if err == nil {
|
||||
router.networkMonitor = networkMonitor
|
||||
if router.interfaceBindManager != nil {
|
||||
|
@ -241,15 +247,18 @@ func NewRouter(ctx context.Context, logger log.ContextLogger, dnsLogger log.Cont
|
|||
}
|
||||
}
|
||||
|
||||
if router.networkMonitor != nil && options.AutoDetectInterface {
|
||||
interfaceMonitor, err := NewDefaultInterfaceMonitor(router.networkMonitor, func() {
|
||||
router.logger.Info("updated default interface ", router.interfaceMonitor.DefaultInterfaceName(), ", index ", router.interfaceMonitor.DefaultInterfaceIndex())
|
||||
})
|
||||
if router.networkMonitor != nil && needInterfaceMonitor {
|
||||
interfaceMonitor, err := tun.NewDefaultInterfaceMonitor(router.networkMonitor)
|
||||
if err != nil {
|
||||
return nil, E.New("auto_detect_interface unsupported on current platform")
|
||||
}
|
||||
interfaceMonitor.RegisterCallback(func() error {
|
||||
router.logger.Info("updated default interface ", router.interfaceMonitor.DefaultInterfaceName(), ", index ", router.interfaceMonitor.DefaultInterfaceIndex())
|
||||
return nil
|
||||
})
|
||||
router.interfaceMonitor = interfaceMonitor
|
||||
}
|
||||
|
||||
if hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess {
|
||||
searcher, err := process.NewSearcher(logger)
|
||||
if err != nil {
|
||||
|
@ -648,20 +657,6 @@ func (r *Router) DefaultInterface() string {
|
|||
return r.defaultInterface
|
||||
}
|
||||
|
||||
func (r *Router) AutoDetectInterfaceName() string {
|
||||
if r.interfaceMonitor == nil {
|
||||
return ""
|
||||
}
|
||||
return r.interfaceMonitor.DefaultInterfaceName()
|
||||
}
|
||||
|
||||
func (r *Router) AutoDetectInterfaceIndex() int {
|
||||
if r.interfaceMonitor == nil {
|
||||
return -1
|
||||
}
|
||||
return r.interfaceMonitor.DefaultInterfaceIndex()
|
||||
}
|
||||
|
||||
func (r *Router) DefaultMark() int {
|
||||
return r.defaultMark
|
||||
}
|
||||
|
@ -670,6 +665,14 @@ func (r *Router) Rules() []adapter.Rule {
|
|||
return r.rules
|
||||
}
|
||||
|
||||
func (r *Router) NetworkMonitor() tun.NetworkUpdateMonitor {
|
||||
return r.networkMonitor
|
||||
}
|
||||
|
||||
func (r *Router) InterfaceMonitor() tun.DefaultInterfaceMonitor {
|
||||
return r.interfaceMonitor
|
||||
}
|
||||
|
||||
func (r *Router) SetTrafficController(controller adapter.TrafficController) {
|
||||
r.trafficController = controller
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 // indirect
|
||||
github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91 // indirect
|
||||
github.com/sagernet/sing-tun v0.0.0-20220803112223-a8fd6450d4ed // indirect
|
||||
github.com/sagernet/sing-tun v0.0.0-20220804154459-7ee0d19103d2 // indirect
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220804023624-e829b41c84c2 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||
|
@ -62,7 +62,7 @@ require (
|
|||
go.uber.org/atomic v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d // indirect
|
||||
golang.org/x/sys v0.0.0-20220803195053-6e608f9ce704 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||
golang.org/x/tools v0.1.9 // indirect
|
||||
|
|
|
@ -180,8 +180,8 @@ github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91 h1:jxt2PYixIkK2i
|
|||
github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91/go.mod h1:T77zZdE2Cm6VqnFumrpwsq+kxYsbq+vWDhmjtdSl/oM=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1 h1:RYvOc69eSNMN0dwVugrDts41Nn7Ar/C/n/fvytvFcp4=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1/go.mod h1:NqZjiXszgVCMQ4gVDa2V+drhS8NMfGqUqDF86EacEFc=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220803112223-a8fd6450d4ed h1:28qeqeuHLZEkzdcZjYwcCn8y4ckyKimaP+L4P25dqUo=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220803112223-a8fd6450d4ed/go.mod h1:jNlPidQzZYkpmpQJ+sDN2YGrPsL4QImoqBpuauId9po=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220804154459-7ee0d19103d2 h1:har8hmVNhGxp14zLNAoGrgfzgxZQn0KTYJDfJudj0RU=
|
||||
github.com/sagernet/sing-tun v0.0.0-20220804154459-7ee0d19103d2/go.mod h1:K1Hfxaa/1zsxZix3ats3k1TJftVwK0l4OoRnUjjhi0g=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220804023624-e829b41c84c2 h1:C8sc2MYiNx0O7uQ0nieJWq5qYeIHj20XHFWPlcgoQeY=
|
||||
github.com/sagernet/sing-vmess v0.0.0-20220804023624-e829b41c84c2/go.mod h1:bNXBqSWYaG3ePl6u0xQY5zneE+ZKa3683ZpuE8S1M1w=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
|
@ -314,8 +314,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d h1:Sv5ogFZatcgIMMtBSTTAgMYsicp25MXBubjXNDKwm80=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220803195053-6e608f9ce704 h1:Y7NOhdqIOU8kYI7BxsgL38d0ot0raxvcW+EMQU2QrT4=
|
||||
golang.org/x/sys v0.0.0-20220803195053-6e608f9ce704/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
Loading…
Reference in a new issue