diff --git a/common/settings/command.go b/common/settings/command.go new file mode 100644 index 00000000..4f2ac92d --- /dev/null +++ b/common/settings/command.go @@ -0,0 +1,19 @@ +package settings + +import ( + "os" + "os/exec" + "strings" + + "github.com/sagernet/sing-box/log" +) + +func runCommand(name string, args ...string) error { + log.Debug(name, " ", strings.Join(args, " ")) + command := exec.Command(name, args...) + command.Env = os.Environ() + command.Stdin = os.Stdin + command.Stdout = os.Stderr + command.Stderr = os.Stderr + return command.Run() +} diff --git a/common/settings/proxy_android.go b/common/settings/proxy_android.go new file mode 100644 index 00000000..2efce080 --- /dev/null +++ b/common/settings/proxy_android.go @@ -0,0 +1,39 @@ +package settings + +import ( + "os" + "strings" + + C "github.com/sagernet/sing-box/constant" + F "github.com/sagernet/sing/common/format" +) + +var ( + useRish bool + rishPath string +) + +func init() { + userId := os.Getuid() + if userId == 0 || userId == 1000 || userId == 2000 { + useRish = false + } else { + rishPath, useRish = C.FindPath("rish") + } +} + +func runAndroidShell(name string, args ...string) error { + if !useRish { + return runCommand(name, args...) + } else { + return runCommand("sh", rishPath, "-c", F.ToString(name, " ", strings.Join(args, " "))) + } +} + +func ClearSystemProxy() 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)) +} diff --git a/common/settings/proxy_linux.go b/common/settings/proxy_linux.go new file mode 100644 index 00000000..3db3432c --- /dev/null +++ b/common/settings/proxy_linux.go @@ -0,0 +1,69 @@ +//go:build linux && !android + +package settings + +import ( + "os/exec" + + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing/common" + F "github.com/sagernet/sing/common/format" +) + +var hasGSettings bool + +func init() { + hasGSettings = common.Error(exec.LookPath("gsettings")) == nil +} + +func ClearSystemProxy() error { + if hasGSettings { + return runCommand("gsettings", "set", "org.gnome.system.proxy", "mode", "none") + } + return nil +} + +func SetSystemProxy(port uint16, mixed bool) error { + if hasGSettings { + err := runCommand("gsettings", "set", "org.gnome.system.proxy.http", "enabled", "true") + if err != nil { + return err + } + if mixed { + err = setGnomeProxy(port, "ftp", "http", "https", "socks") + if err != nil { + return err + } + } else { + err = setGnomeProxy(port, "http", "https") + if err != nil { + return err + } + } + err = runCommand("gsettings", "set", "org.gnome.system.proxy", "use-same-proxy", F.ToString(mixed)) + if err != nil { + return err + } + err = runCommand("gsettings", "set", "org.gnome.system.proxy", "mode", "manual") + if err != nil { + return err + } + } else { + log.Warn("set system proxy: unsupported desktop environment") + } + return nil +} + +func setGnomeProxy(port uint16, proxyTypes ...string) error { + for _, proxyType := range proxyTypes { + err := runCommand("gsettings", "set", "org.gnome.system.proxy."+proxyType, "host", "127.0.0.1") + if err != nil { + return err + } + err = runCommand("gsettings", "set", "org.gnome.system.proxy."+proxyType, "port", F.ToString(port)) + if err != nil { + return err + } + } + return nil +} diff --git a/common/settings/proxy_stub.go b/common/settings/proxy_stub.go new file mode 100644 index 00000000..a0418837 --- /dev/null +++ b/common/settings/proxy_stub.go @@ -0,0 +1,14 @@ +//go:build !windows && !linux + +package settings + +import "github.com/sagernet/sing-box/log" + +func ClearSystemProxy() error { + return nil +} + +func SetSystemProxy(port uint16, mixed bool) error { + log.Warn("set system proxy: unsupported operating system") + return nil +} diff --git a/common/wininet/wininet_windows.go b/common/settings/proxy_windows.go similarity index 91% rename from common/wininet/wininet_windows.go rename to common/settings/proxy_windows.go index 2d32f6d6..71e79f8e 100644 --- a/common/wininet/wininet_windows.go +++ b/common/settings/proxy_windows.go @@ -1,15 +1,17 @@ -package wininet +package settings import ( "os" "syscall" "unsafe" + F "github.com/sagernet/sing/common/format" + "golang.org/x/sys/windows" ) var ( - modwininet = windows.NewLazySystemDLL("wininet.dll") + modwininet = windows.NewLazySystemDLL("settings.dll") procInternetSetOptionW = modwininet.NewProc("InternetSetOptionW") ) @@ -95,15 +97,15 @@ func ClearSystemProxy() error { return setOptions(flagsOption) } -func SetSystemProxy(proxy string, bypass string) error { +func SetSystemProxy(port uint16, mixed bool) error { var flagsOption internetPerConnOption flagsOption.dwOption = internetPerConnFlags *((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeProxy | proxyTypeDirect var proxyOption internetPerConnOption proxyOption.dwOption = internetPerConnProxyServer - *((*uintptr)(unsafe.Pointer(&proxyOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(proxy))) + *((*uintptr)(unsafe.Pointer(&proxyOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(F.ToString("http://127.0.0.1:", port)))) var bypassOption internetPerConnOption bypassOption.dwOption = internetPerConnProxyBypass - *((*uintptr)(unsafe.Pointer(&bypassOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(bypass))) + *((*uintptr)(unsafe.Pointer(&bypassOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("local"))) return setOptions(flagsOption, proxyOption, bypassOption) } diff --git a/common/wininet/wininet_stub.go b/common/wininet/wininet_stub.go deleted file mode 100644 index a624c023..00000000 --- a/common/wininet/wininet_stub.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !windows - -package wininet - -import "os" - -func ClearSystemProxy() error { - return os.ErrInvalid -} - -func SetSystemProxy(proxy string, bypass string) error { - return os.ErrInvalid -} diff --git a/constant/path.go b/constant/path.go index 61486b2f..98acacdc 100644 --- a/constant/path.go +++ b/constant/path.go @@ -20,12 +20,18 @@ func FindPath(name string) (string, bool) { if path := filepath.Join(dir, dirName, name); rw.FileExists(path) { return path, true } + if path := filepath.Join(dir, name); rw.FileExists(path) { + return path, true + } } return name, false } func init() { resourcePaths = append(resourcePaths, ".") + if home := os.Getenv("HOME"); home != "" { + resourcePaths = append(resourcePaths, home) + } if userConfigDir, err := os.UserConfigDir(); err == nil { resourcePaths = append(resourcePaths, userConfigDir) } diff --git a/go.mod b/go.mod index 5f007158..5890f800 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module github.com/sagernet/sing-box go 1.18 require ( - github.com/database64128/tfo-go v1.0.4 + github.com/database64128/tfo-go v1.1.0 github.com/goccy/go-json v0.9.8 github.com/logrusorgru/aurora v2.0.3+incompatible github.com/oschwald/maxminddb-golang v1.9.0 - github.com/sagernet/sing v0.0.0-20220712060558-029ab1ce4f91 + github.com/sagernet/sing v0.0.0-20220714121943-f8c0f71a89f5 github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 - github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649 - github.com/sagernet/sing-tun v0.0.0-20220713125153-6c2c28da9d76 + github.com/sagernet/sing-shadowsocks v0.0.0-20220714111527-a6fa7ada6e81 + github.com/sagernet/sing-tun v0.0.0-20220714105342-455aba7939ae github.com/spf13/cobra v1.5.0 github.com/stretchr/testify v1.8.0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d diff --git a/go.sum b/go.sum index 2a536437..8535de68 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/database64128/tfo-go v1.0.4 h1:0D9CsLor6q+2UrLhFYY3MkKkxRGf2W+27beMAo43SJc= -github.com/database64128/tfo-go v1.0.4/go.mod h1:q5W+W0+2IHrw/Lnl0yg4sz7Kz5IDsm9x0vhwZXkRwG4= +github.com/database64128/tfo-go v1.1.0 h1:VO0polyGNSAmr99nYw9GQeMz7ZOcQ/QbjlTwniHwfTQ= +github.com/database64128/tfo-go v1.1.0/go.mod h1:95pOT8bnV3P2Lmu9upHNWFHz6dYGJ9cr7pnb0tGQAG8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -25,14 +25,14 @@ github.com/oschwald/maxminddb-golang v1.9.0/go.mod h1:TK+s/Z2oZq0rSl4PSeAEoP0bgm github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagernet/sing v0.0.0-20220712060558-029ab1ce4f91 h1:fYsRChEViZHDvrOLp7fbswYCH3txaVyAl1zB0cnSNlc= -github.com/sagernet/sing v0.0.0-20220712060558-029ab1ce4f91/go.mod h1:3ZmoGNg/nNJTyHAZFNRSPaXpNIwpDvyIiAUd0KIWV5c= +github.com/sagernet/sing v0.0.0-20220714121943-f8c0f71a89f5 h1:OdcGVZQxCe8xlb4jc5LWrYFu54Tz4IULxLco44qOnN8= +github.com/sagernet/sing v0.0.0-20220714121943-f8c0f71a89f5/go.mod h1:3ZmoGNg/nNJTyHAZFNRSPaXpNIwpDvyIiAUd0KIWV5c= github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 h1:oHbOmq1WS0XaZmXp6WpxzyB2xeyRIA1/L8EJKuNntfY= github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619/go.mod h1:y2fpvoxukw3G7eApIZwkcpcG/NE4AB8pCQI0Qd8rMqk= -github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649 h1:whNDUGOAX5GPZkSy4G3Gv9QyIgk5SXRyjkRuP7ohF8k= -github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649/go.mod h1:MuyT+9fEPjvauAv0fSE0a6Q+l0Tv2ZrAafTkYfnxBFw= -github.com/sagernet/sing-tun v0.0.0-20220713125153-6c2c28da9d76 h1:/nvko0np1sAZrY5s+0HIn99SXbAkN7lPWiBZ22nDEL0= -github.com/sagernet/sing-tun v0.0.0-20220713125153-6c2c28da9d76/go.mod h1:oIK1kg8hkeA5zNSv9BcbTPzdR00bbVBt6eYvJp+rsck= +github.com/sagernet/sing-shadowsocks v0.0.0-20220714111527-a6fa7ada6e81 h1:VuUk/04yCr3dw2uJj0/OFVeVO5O2dwYGlj/RzuEfYDE= +github.com/sagernet/sing-shadowsocks v0.0.0-20220714111527-a6fa7ada6e81/go.mod h1:MuyT+9fEPjvauAv0fSE0a6Q+l0Tv2ZrAafTkYfnxBFw= +github.com/sagernet/sing-tun v0.0.0-20220714105342-455aba7939ae h1:kTchVdHf8akqVEwuG59JpwGwcUNDQWys8cxP7IVvNbE= +github.com/sagernet/sing-tun v0.0.0-20220714105342-455aba7939ae/go.mod h1:oIK1kg8hkeA5zNSv9BcbTPzdR00bbVBt6eYvJp+rsck= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/inbound/default.go b/inbound/default.go index 094036bc..597537fd 100644 --- a/inbound/default.go +++ b/inbound/default.go @@ -9,7 +9,7 @@ import ( "time" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/wininet" + "github.com/sagernet/sing-box/common/settings" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" @@ -17,7 +17,6 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" E "github.com/sagernet/sing/common/exceptions" - F "github.com/sagernet/sing/common/format" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" @@ -95,7 +94,7 @@ func (a *myInboundAdapter) Start() error { a.logger.Info("udp server started at ", udpConn.LocalAddr()) } if a.setSystemProxy { - err := wininet.SetSystemProxy(F.ToString("http://127.0.0.1:", M.SocksaddrFromNet(a.tcpListener.Addr()).Port), "local") + err := settings.SetSystemProxy(M.SocksaddrFromNet(a.tcpListener.Addr()).Port, a.protocol == C.TypeMixed) if err != nil { return E.Cause(err, "set system proxy") } @@ -106,7 +105,7 @@ func (a *myInboundAdapter) Start() error { func (a *myInboundAdapter) Close() error { var err error if a.setSystemProxy { - err = wininet.ClearSystemProxy() + err = settings.ClearSystemProxy() } return E.Errors(err, common.Close( common.PtrOrNil(a.tcpListener), diff --git a/test/go.mod b/test/go.mod index c9c1d758..a098068b 100644 --- a/test/go.mod +++ b/test/go.mod @@ -5,9 +5,8 @@ go 1.18 require ( github.com/docker/docker v20.10.17+incompatible github.com/docker/go-connections v0.4.0 - github.com/sagernet/sing v0.0.0-20220714062657-6685f65aac21 + github.com/sagernet/sing v0.0.0-20220714121943-f8c0f71a89f5 github.com/sagernet/sing-box v0.0.0 - github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.8.0 golang.org/x/net v0.0.0-20220708220712-1185a9018129 ) @@ -16,7 +15,7 @@ replace github.com/sagernet/sing-box => ../ require ( github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/database64128/tfo-go v1.0.4 // indirect + github.com/database64128/tfo-go v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/go-units v0.4.0 // indirect @@ -34,8 +33,9 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 // indirect - github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649 // indirect - github.com/sagernet/sing-tun v0.0.0-20220713125153-6c2c28da9d76 // indirect + github.com/sagernet/sing-shadowsocks v0.0.0-20220714111527-a6fa7ada6e81 // indirect + github.com/sagernet/sing-tun v0.0.0-20220714105342-455aba7939ae // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/vishvananda/netlink v1.1.0 // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect diff --git a/test/go.sum b/test/go.sum index fe836c61..dfbff795 100644 --- a/test/go.sum +++ b/test/go.sum @@ -4,8 +4,8 @@ github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VM github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/database64128/tfo-go v1.0.4 h1:0D9CsLor6q+2UrLhFYY3MkKkxRGf2W+27beMAo43SJc= -github.com/database64128/tfo-go v1.0.4/go.mod h1:q5W+W0+2IHrw/Lnl0yg4sz7Kz5IDsm9x0vhwZXkRwG4= +github.com/database64128/tfo-go v1.1.0 h1:VO0polyGNSAmr99nYw9GQeMz7ZOcQ/QbjlTwniHwfTQ= +github.com/database64128/tfo-go v1.1.0/go.mod h1:95pOT8bnV3P2Lmu9upHNWFHz6dYGJ9cr7pnb0tGQAG8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -52,14 +52,14 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sagernet/sing v0.0.0-20220714062657-6685f65aac21 h1:PaX9VR0gVUagiRHwp9imiVZ9VW169WoEyToJg3UCKBI= -github.com/sagernet/sing v0.0.0-20220714062657-6685f65aac21/go.mod h1:wbwi++q4pI7qbFYMbteUOakZUBdc4NmL+OQ08C3hTqc= +github.com/sagernet/sing v0.0.0-20220714121943-f8c0f71a89f5 h1:OdcGVZQxCe8xlb4jc5LWrYFu54Tz4IULxLco44qOnN8= +github.com/sagernet/sing v0.0.0-20220714121943-f8c0f71a89f5/go.mod h1:3ZmoGNg/nNJTyHAZFNRSPaXpNIwpDvyIiAUd0KIWV5c= github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 h1:oHbOmq1WS0XaZmXp6WpxzyB2xeyRIA1/L8EJKuNntfY= github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619/go.mod h1:y2fpvoxukw3G7eApIZwkcpcG/NE4AB8pCQI0Qd8rMqk= -github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649 h1:whNDUGOAX5GPZkSy4G3Gv9QyIgk5SXRyjkRuP7ohF8k= -github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649/go.mod h1:MuyT+9fEPjvauAv0fSE0a6Q+l0Tv2ZrAafTkYfnxBFw= -github.com/sagernet/sing-tun v0.0.0-20220713125153-6c2c28da9d76 h1:/nvko0np1sAZrY5s+0HIn99SXbAkN7lPWiBZ22nDEL0= -github.com/sagernet/sing-tun v0.0.0-20220713125153-6c2c28da9d76/go.mod h1:oIK1kg8hkeA5zNSv9BcbTPzdR00bbVBt6eYvJp+rsck= +github.com/sagernet/sing-shadowsocks v0.0.0-20220714111527-a6fa7ada6e81 h1:VuUk/04yCr3dw2uJj0/OFVeVO5O2dwYGlj/RzuEfYDE= +github.com/sagernet/sing-shadowsocks v0.0.0-20220714111527-a6fa7ada6e81/go.mod h1:MuyT+9fEPjvauAv0fSE0a6Q+l0Tv2ZrAafTkYfnxBFw= +github.com/sagernet/sing-tun v0.0.0-20220714105342-455aba7939ae h1:kTchVdHf8akqVEwuG59JpwGwcUNDQWys8cxP7IVvNbE= +github.com/sagernet/sing-tun v0.0.0-20220714105342-455aba7939ae/go.mod h1:oIK1kg8hkeA5zNSv9BcbTPzdR00bbVBt6eYvJp+rsck= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=