Add set_system_proxy for linux and android

This commit is contained in:
世界
2022-07-14 20:30:57 +08:00
parent de2db7c2d2
commit b9086b31e6
12 changed files with 182 additions and 47 deletions

View File

@@ -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()
}

View File

@@ -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))
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -0,0 +1,111 @@
package settings
import (
"os"
"syscall"
"unsafe"
F "github.com/sagernet/sing/common/format"
"golang.org/x/sys/windows"
)
var (
modwininet = windows.NewLazySystemDLL("settings.dll")
procInternetSetOptionW = modwininet.NewProc("InternetSetOptionW")
)
const (
internetOptionPerConnectionOption = 75
internetOptionSettingsChanged = 39
internetOptionRefresh = 37
internetOptionProxySettingsChanged = 95
)
const (
internetPerConnFlags = 1
internetPerConnProxyServer = 2
internetPerConnProxyBypass = 3
internetPerConnAutoconfigUrl = 4
internetPerConnAutodiscoveryFlags = 5
internetPerConnAutoconfigSecondaryUrl = 6
internetPerConnAutoconfigReloadDelayMins = 7
internetPerConnAutoconfigLastDetectTime = 8
internetPerConnAutoconfigLastDetectUrl = 9
internetPerConnFlagsUi = 10
internetOptionProxyUsername = 43
internetOptionProxyPassword = 44
)
const (
proxyTypeDirect = 1
proxyTypeProxy = 2
proxyTypeAutoProxyUrl = 4
proxyTypeAutoDetect = 8
)
type internetPerConnOptionList struct {
dwSize uint32
pszConnection uintptr
dwOptionCount uint32
dwOptionError uint32
pOptions uintptr
}
type internetPerConnOption struct {
dwOption uint32
value [8]byte
}
func internetSetOption(option uintptr, lpBuffer uintptr, dwBufferSize uintptr) error {
r0, _, err := syscall.SyscallN(procInternetSetOptionW.Addr(), 0, option, lpBuffer, dwBufferSize)
if r0 != 1 {
return err
}
return nil
}
func setOptions(options ...internetPerConnOption) error {
var optionList internetPerConnOptionList
optionList.dwSize = uint32(unsafe.Sizeof(optionList))
optionList.dwOptionCount = uint32(len(options))
optionList.dwOptionError = 0
optionList.pOptions = uintptr(unsafe.Pointer(&options[0]))
err := internetSetOption(internetOptionPerConnectionOption, uintptr(unsafe.Pointer(&optionList)), uintptr(optionList.dwSize))
if err != nil {
return os.NewSyscallError("InternetSetOption(Direct)", err)
}
err = internetSetOption(internetOptionSettingsChanged, 0, 0)
if err != nil {
return os.NewSyscallError("InternetSetOption(SettingsChanged)", err)
}
err = internetSetOption(internetOptionProxySettingsChanged, 0, 0)
if err != nil {
return os.NewSyscallError("InternetSetOption(ProxySettingsChanged)", err)
}
err = internetSetOption(internetOptionRefresh, 0, 0)
if err != nil {
return os.NewSyscallError("InternetSetOption(Refresh)", err)
}
return nil
}
func ClearSystemProxy() error {
var flagsOption internetPerConnOption
flagsOption.dwOption = internetPerConnFlags
*((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeDirect | proxyTypeAutoDetect
return setOptions(flagsOption)
}
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(F.ToString("http://127.0.0.1:", port))))
var bypassOption internetPerConnOption
bypassOption.dwOption = internetPerConnProxyBypass
*((*uintptr)(unsafe.Pointer(&bypassOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("local")))
return setOptions(flagsOption, proxyOption, bypassOption)
}