You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
11 KiB

package system
import (
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"github.com/sirupsen/logrus"
)
type SystemProxy struct {
logger *logrus.Logger
proxyAddr string
backupConfig map[string]string
}
type Config struct {
HTTPProxy string
HTTPSProxy string
SOCKSProxy string
NoProxy []string
}
func NewSystemProxy(proxyAddr string, logger *logrus.Logger) *SystemProxy {
return &SystemProxy{
logger: logger,
proxyAddr: proxyAddr,
backupConfig: make(map[string]string),
}
}
// SetSystemProxy 设置系统代理
func (sp *SystemProxy) SetSystemProxy(config Config) error {
sp.logger.Info("Setting system proxy configuration")
// 备份当前配置
if err := sp.backupCurrentConfig(); err != nil {
sp.logger.WithError(err).Warn("Failed to backup current proxy config")
}
switch runtime.GOOS {
case "darwin":
return sp.setMacOSProxy(config)
case "linux":
return sp.setLinuxProxy(config)
case "windows":
return sp.setWindowsProxy(config)
default:
return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
}
// RestoreSystemProxy 恢复系统代理设置
func (sp *SystemProxy) RestoreSystemProxy() error {
sp.logger.Info("Restoring system proxy configuration")
switch runtime.GOOS {
case "darwin":
return sp.restoreMacOSProxy()
case "linux":
return sp.restoreLinuxProxy()
case "windows":
return sp.restoreWindowsProxy()
default:
return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
}
// setMacOSProxy 设置macOS系统代理
func (sp *SystemProxy) setMacOSProxy(config Config) error {
// 获取所有网络服务
services, err := sp.getMacOSNetworkServices()
if err != nil {
return fmt.Errorf("failed to get network services: %w", err)
}
for _, service := range services {
// 设置HTTP代理
if config.HTTPProxy != "" {
parts := strings.Split(config.HTTPProxy, ":")
if len(parts) == 2 {
if err := sp.runCommand("networksetup", "-setwebproxy", service, parts[0], parts[1]); err != nil {
sp.logger.WithError(err).WithField("service", service).Warn("Failed to set HTTP proxy")
}
if err := sp.runCommand("networksetup", "-setwebproxystate", service, "on"); err != nil {
sp.logger.WithError(err).WithField("service", service).Warn("Failed to enable HTTP proxy")
}
}
}
// 设置HTTPS代理
if config.HTTPSProxy != "" {
parts := strings.Split(config.HTTPSProxy, ":")
if len(parts) == 2 {
if err := sp.runCommand("networksetup", "-setsecurewebproxy", service, parts[0], parts[1]); err != nil {
sp.logger.WithError(err).WithField("service", service).Warn("Failed to set HTTPS proxy")
}
if err := sp.runCommand("networksetup", "-setsecurewebproxystate", service, "on"); err != nil {
sp.logger.WithError(err).WithField("service", service).Warn("Failed to enable HTTPS proxy")
}
}
}
// 设置SOCKS代理
if config.SOCKSProxy != "" {
parts := strings.Split(config.SOCKSProxy, ":")
if len(parts) == 2 {
if err := sp.runCommand("networksetup", "-setsocksfirewallproxy", service, parts[0], parts[1]); err != nil {
sp.logger.WithError(err).WithField("service", service).Warn("Failed to set SOCKS proxy")
}
if err := sp.runCommand("networksetup", "-setsocksfirewallproxystate", service, "on"); err != nil {
sp.logger.WithError(err).WithField("service", service).Warn("Failed to enable SOCKS proxy")
}
}
}
// 设置代理绕过列表
if len(config.NoProxy) > 0 {
bypassList := strings.Join(config.NoProxy, " ")
if err := sp.runCommand("networksetup", "-setproxybypassdomains", service, bypassList); err != nil {
sp.logger.WithError(err).WithField("service", service).Warn("Failed to set proxy bypass list")
}
}
}
return nil
}
// setLinuxProxy 设置Linux系统代理(通过环境变量)
func (sp *SystemProxy) setLinuxProxy(config Config) error {
envVars := make(map[string]string)
if config.HTTPProxy != "" {
envVars["http_proxy"] = "http://" + config.HTTPProxy
envVars["HTTP_PROXY"] = "http://" + config.HTTPProxy
}
if config.HTTPSProxy != "" {
envVars["https_proxy"] = "https://" + config.HTTPSProxy
envVars["HTTPS_PROXY"] = "https://" + config.HTTPSProxy
}
if len(config.NoProxy) > 0 {
noProxy := strings.Join(config.NoProxy, ",")
envVars["no_proxy"] = noProxy
envVars["NO_PROXY"] = noProxy
}
// 写入到用户的shell配置文件
return sp.writeLinuxProxyConfig(envVars)
}
// setWindowsProxy 设置Windows系统代理
func (sp *SystemProxy) setWindowsProxy(config Config) error {
// Windows代理设置通过注册表
if config.HTTPProxy != "" {
// 启用代理
if err := sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "1", "/f"); err != nil {
return fmt.Errorf("failed to enable proxy: %w", err)
}
// 设置代理服务器
if err := sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyServer", "/t", "REG_SZ", "/d", config.HTTPProxy, "/f"); err != nil {
return fmt.Errorf("failed to set proxy server: %w", err)
}
}
// 设置代理绕过列表
if len(config.NoProxy) > 0 {
bypassList := strings.Join(config.NoProxy, ";")
if err := sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyOverride", "/t", "REG_SZ", "/d", bypassList, "/f"); err != nil {
return fmt.Errorf("failed to set proxy bypass list: %w", err)
}
}
return nil
}
func (sp *SystemProxy) getMacOSNetworkServices() ([]string, error) {
output, err := exec.Command("networksetup", "-listallnetworkservices").Output()
if err != nil {
return nil, err
}
lines := strings.Split(string(output), "\n")
var services []string
for _, line := range lines {
line = strings.TrimSpace(line)
if line != "" && !strings.HasPrefix(line, "*") && line != "An asterisk (*) denotes that a network service is disabled." {
services = append(services, line)
}
}
return services, nil
}
func (sp *SystemProxy) backupCurrentConfig() error {
switch runtime.GOOS {
case "darwin":
return sp.backupMacOSConfig()
case "linux":
return sp.backupLinuxConfig()
case "windows":
return sp.backupWindowsConfig()
}
return nil
}
func (sp *SystemProxy) backupMacOSConfig() error {
services, err := sp.getMacOSNetworkServices()
if err != nil {
return err
}
for _, service := range services {
// 备份HTTP代理设置
output, _ := exec.Command("networksetup", "-getwebproxy", service).Output()
sp.backupConfig[fmt.Sprintf("http_%s", service)] = string(output)
// 备份HTTPS代理设置
output, _ = exec.Command("networksetup", "-getsecurewebproxy", service).Output()
sp.backupConfig[fmt.Sprintf("https_%s", service)] = string(output)
// 备份SOCKS代理设置
output, _ = exec.Command("networksetup", "-getsocksfirewallproxy", service).Output()
sp.backupConfig[fmt.Sprintf("socks_%s", service)] = string(output)
}
return nil
}
func (sp *SystemProxy) backupLinuxConfig() error {
// 备份环境变量
sp.backupConfig["http_proxy"] = os.Getenv("http_proxy")
sp.backupConfig["https_proxy"] = os.Getenv("https_proxy")
sp.backupConfig["no_proxy"] = os.Getenv("no_proxy")
return nil
}
func (sp *SystemProxy) backupWindowsConfig() error {
// 备份Windows注册表设置
output, _ := exec.Command("reg", "query", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyEnable").Output()
sp.backupConfig["ProxyEnable"] = string(output)
output, _ = exec.Command("reg", "query", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyServer").Output()
sp.backupConfig["ProxyServer"] = string(output)
return nil
}
func (sp *SystemProxy) restoreMacOSProxy() error {
services, err := sp.getMacOSNetworkServices()
if err != nil {
return err
}
for _, service := range services {
// 禁用所有代理
sp.runCommand("networksetup", "-setwebproxystate", service, "off")
sp.runCommand("networksetup", "-setsecurewebproxystate", service, "off")
sp.runCommand("networksetup", "-setsocksfirewallproxystate", service, "off")
}
return nil
}
func (sp *SystemProxy) restoreLinuxProxy() error {
// 清除环境变量(这里简化处理)
os.Unsetenv("http_proxy")
os.Unsetenv("https_proxy")
os.Unsetenv("no_proxy")
os.Unsetenv("HTTP_PROXY")
os.Unsetenv("HTTPS_PROXY")
os.Unsetenv("NO_PROXY")
return nil
}
func (sp *SystemProxy) restoreWindowsProxy() error {
// 禁用代理
return sp.runCommand("reg", "add", `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "0", "/f")
}
func (sp *SystemProxy) writeLinuxProxyConfig(envVars map[string]string) error {
// 写入到 ~/.bashrc 和 ~/.profile
homeDir, err := os.UserHomeDir()
if err != nil {
return err
}
configFiles := []string{
homeDir + "/.bashrc",
homeDir + "/.profile",
}
proxyLines := []string{"\n# Wormhole SOCKS5 Proxy Configuration"}
for key, value := range envVars {
proxyLines = append(proxyLines, fmt.Sprintf("export %s=%s", key, value))
}
proxyLines = append(proxyLines, "# End Wormhole Configuration\n")
for _, configFile := range configFiles {
file, err := os.OpenFile(configFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
sp.logger.WithError(err).WithField("file", configFile).Warn("Failed to open config file")
continue
}
for _, line := range proxyLines {
if _, err := file.WriteString(line + "\n"); err != nil {
sp.logger.WithError(err).WithField("file", configFile).Warn("Failed to write to config file")
}
}
file.Close()
}
return nil
}
func (sp *SystemProxy) runCommand(name string, args ...string) error {
cmd := exec.Command(name, args...)
output, err := cmd.CombinedOutput()
if err != nil {
sp.logger.WithFields(logrus.Fields{
"command": fmt.Sprintf("%s %s", name, strings.Join(args, " ")),
"output": string(output),
}).WithError(err).Debug("Command execution failed")
return err
}
return nil
}
// GetCurrentConfig 获取当前系统代理配置
func (sp *SystemProxy) GetCurrentConfig() (Config, error) {
config := Config{
NoProxy: []string{},
}
switch runtime.GOOS {
case "linux":
config.HTTPProxy = os.Getenv("http_proxy")
config.HTTPSProxy = os.Getenv("https_proxy")
noProxy := os.Getenv("no_proxy")
if noProxy != "" {
config.NoProxy = strings.Split(noProxy, ",")
}
}
return config, nil
}
// IsProxySet 检查是否已设置代理
func (sp *SystemProxy) IsProxySet() bool {
switch runtime.GOOS {
case "linux":
return os.Getenv("http_proxy") != "" || os.Getenv("https_proxy") != ""
case "darwin":
// 检查macOS代理设置(简化)
return false
case "windows":
// 检查Windows代理设置(简化)
return false
}
return false
}