Add set_system_proxy for linux and android
This commit is contained in:
19
common/settings/command.go
Normal file
19
common/settings/command.go
Normal 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()
|
||||
}
|
||||
39
common/settings/proxy_android.go
Normal file
39
common/settings/proxy_android.go
Normal 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))
|
||||
}
|
||||
69
common/settings/proxy_linux.go
Normal file
69
common/settings/proxy_linux.go
Normal 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
|
||||
}
|
||||
14
common/settings/proxy_stub.go
Normal file
14
common/settings/proxy_stub.go
Normal 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
|
||||
}
|
||||
111
common/settings/proxy_windows.go
Normal file
111
common/settings/proxy_windows.go
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user