Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package to setup system wide HTTP(S) Proxy on Desktop Platforms #190

Merged
merged 76 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
e793764
add dynamic config support
amircybersec Jan 16, 2024
bbd9f82
Merge branch 'Jigsaw-Code:main' into main
amircybersec Jan 21, 2024
ba98871
Revert "add dynamic config support"
amircybersec Jan 21, 2024
bcb602e
Merge branch 'Jigsaw-Code:main' into main
amircybersec Feb 14, 2024
4cb44eb
Merge branch 'Jigsaw-Code:main' into main
amircybersec Feb 24, 2024
c11ab04
add sys proxy for desktop platforms
amircybersec Feb 26, 2024
fdf398f
do nothing on unsupported platforms
amircybersec Feb 26, 2024
6a5680c
add proxyType and clean up code for Darwin
amircybersec Feb 29, 2024
f48a095
remove safeclose and clean up the package doc
amircybersec Feb 29, 2024
cc694c9
moved package docs to doc.go
amircybersec Feb 29, 2024
044d794
return an error if platform is not supported
amircybersec Feb 29, 2024
422ca10
refactored runCommad
amircybersec Feb 29, 2024
e2247d5
added docs and clean up
amircybersec Mar 1, 2024
f91cafc
linux code refactor and cleanup
amircybersec Mar 1, 2024
65db63e
Update x/sysproxy/doc.go
amircybersec Mar 6, 2024
f48f419
Update x/sysproxy/sysproxy_darwin.go
amircybersec Mar 6, 2024
ed4c93b
Update x/sysproxy/sysproxy_darwin.go
amircybersec Mar 6, 2024
ceec53f
Update x/sysproxy/sysproxy_windows.go
amircybersec Mar 6, 2024
5952a45
Update x/sysproxy/sysproxy_windows.go
amircybersec Mar 6, 2024
0faac88
Update x/sysproxy/sysproxy_windows.go
amircybersec Mar 6, 2024
7339b23
Update x/sysproxy/sysproxy_windows.go
amircybersec Mar 6, 2024
7b895a5
Update x/sysproxy/sysproxy_windows.go
amircybersec Mar 6, 2024
b6f3c97
Update x/sysproxy/sysproxy_darwin.go
amircybersec Mar 6, 2024
6c59ad8
Update x/sysproxy/sysproxy_windows.go
amircybersec Mar 6, 2024
a04317e
Update x/sysproxy/sysproxy_windows.go
amircybersec Mar 6, 2024
7dd57d0
Update x/sysproxy/sysproxy_linux.go
amircybersec Mar 6, 2024
75ea37c
windows: backup settings before change & revert
amircybersec Mar 16, 2024
bdc6d2d
linux: add backup settings + socks5
amircybersec Mar 16, 2024
f8906a1
darwin: backup settings + socks
amircybersec Mar 16, 2024
2826419
return error if socks5 is not supported
amircybersec Mar 16, 2024
d3020d3
updated readme.md
amircybersec Mar 17, 2024
34ce3c3
updated doc.go
amircybersec Mar 17, 2024
0522adb
removed backup settings from Darwin
amircybersec Mar 24, 2024
7cf4822
windows: add socks, remove backup
amircybersec Mar 24, 2024
1ef992a
linux: replaced backup with clearing
amircybersec Mar 24, 2024
029a9c4
windows: removed backup method
amircybersec Mar 24, 2024
3f736c9
windows: bug fix
amircybersec Mar 24, 2024
1baff92
darwin: added back getProxySetting for testing
amircybersec Mar 24, 2024
3c593f9
darwin: added back getHostandPort
amircybersec Mar 24, 2024
9d8c9c9
added back ProxySettings type
amircybersec Mar 24, 2024
b6558e2
add getWebProxy and getSocksProxy
amircybersec Mar 25, 2024
2594efb
linux: add getwebproxy and getsocksproxy
amircybersec Mar 25, 2024
984833e
darwin: added tests
amircybersec Mar 25, 2024
66658ac
windows: add getproxysetting
amircybersec Mar 25, 2024
1dedbf7
one test file for all platforms
amircybersec Mar 25, 2024
630fc56
updating tests
amircybersec Mar 25, 2024
4765b77
fixed getsocksproxy issue on windows
amircybersec Mar 25, 2024
3f15492
linux: getsocksproxy bug fix
amircybersec Mar 25, 2024
4700f68
test clean up
amircybersec Mar 25, 2024
8855f10
windows: made proxySettings private
amircybersec Mar 25, 2024
8d5f311
remove print line
amircybersec Mar 25, 2024
c7e805c
linux: removed proxysettings struct
amircybersec Mar 25, 2024
4405b78
darwin: proxySettings made private
amircybersec Mar 25, 2024
38e2535
update docs
amircybersec Mar 25, 2024
9cfad5f
update readme
amircybersec Mar 25, 2024
4fd18a6
typo fix
amircybersec Mar 25, 2024
428f291
Update x/sysproxy/README.md
amircybersec Mar 25, 2024
7490cd1
Update x/sysproxy/README.md
amircybersec Mar 25, 2024
00f414c
update go.mod file + delete readme
amircybersec Mar 26, 2024
17aeeb7
update go.doc file
amircybersec Mar 26, 2024
b3c6f61
doc polish
amircybersec Mar 26, 2024
e49e0da
Merge branch 'main' into sysproxy-amir
amircybersec Mar 26, 2024
136c2db
changed clear proxy to disable proxy
amircybersec Mar 27, 2024
3fbb4ed
test: check if proxy setting is cleared
amircybersec Mar 27, 2024
e5b3ad1
disable proxy instead of clearing it
amircybersec Mar 28, 2024
7d22038
linux: diable proxy instead of clearing it
amircybersec Mar 28, 2024
235ad1d
linux: get proxy mode bugfix
amircybersec Mar 28, 2024
7e4abd9
linux: fixed enabled comparison bug
amircybersec Mar 28, 2024
d9c10c8
Update x/sysproxy/doc.go
amircybersec Apr 1, 2024
3da2ff2
Update x/sysproxy/sysproxy_test.go
amircybersec Apr 1, 2024
05e3d14
Update x/sysproxy/sysproxy_windows.go
amircybersec Apr 1, 2024
d71b726
Update x/sysproxy/sysproxy_windows.go
amircybersec Apr 1, 2024
7cdec08
doc update
amircybersec Apr 1, 2024
77faf78
change unset to diable in other platforms
amircybersec Apr 1, 2024
b34db8e
exclude ios explictly
amircybersec Apr 1, 2024
35273de
return joined errors
amircybersec Apr 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions x/sysproxy/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
jyyi1 marked this conversation as resolved.
Show resolved Hide resolved
Package sysproxy provides a simple interface to set/unset system-wide proxy settings.

# Platform Support
Currently this package supports desktop platforms only. The following platforms are supported:
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
- macOS
- Linux (Gnome is the only supported desktop environment for now.)
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
- Windows
amircybersec marked this conversation as resolved.
Show resolved Hide resolved

# Usage

- To set up system-wide proxy settings, use the `SetProxy` function. This function takes two arguments: the IP address and the port of the proxy server.
`SetProxy(ip string, port string) error`
amircybersec marked this conversation as resolved.
Show resolved Hide resolved

- To unset system-wide proxy settings, use the `UnsetProxy` function.
`UnsetProxy() error`
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
amircybersec marked this conversation as resolved.
Show resolved Hide resolved

You need to also clean up the proxy settings when you are done with the proxy server. This is important because the proxy settings will remain in place even after the proxy server is stopped.
The following example demonstrates how to safely unset proxy upon program termination:

```go
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
func main () {
// Create channels to receive signals
done := make(chan bool, 1)
sigs := make(chan os.Signal, 1)
sysproxy.SafeCloseProxy(done, sigs)
amircybersec marked this conversation as resolved.
Show resolved Hide resolved

// Your code here

// Send a signal to the program to terminate
sigs<-syscall.SIGTERM
// Wait for the program to terminate
<-done
}

```
*/

package sysproxy
27 changes: 27 additions & 0 deletions x/sysproxy/sysproxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package sysproxy

import (
"fmt"
"os"
"os/signal"
"syscall"
)

func SafeCloseProxy(done chan bool, sigs chan os.Signal) {
// Channel to indicate the program can stop
// Register the channel to receive notifications of the specified signals
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
// Start a goroutine to handle the signals
// This goroutine executes a blocking receive for signals
go func() {
sig := <-sigs
fmt.Println(sig)
// Here you can call your cleanup or exit function
if err := UnsetProxy(); err != nil {
fmt.Println("Error setting up proxy:", err)
} else {
fmt.Println("Proxy unset successful")
}
done <- true
}()
}
101 changes: 101 additions & 0 deletions x/sysproxy/sysproxy_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//go:build darwin

package sysproxy

import (
"bytes"
"fmt"
"os/exec"
"strings"
)

func SetProxy(ip string, port string) error {
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't set the SOCKS proxy. We need to specify what type of proxy we are setting somehow.

Two options:

  • Different method names: SetWebProxy, SetSecureWebProxy, SetSOCKSProxy...
  • Type parameter: SetProxy(ProxyTypeWeb, host, port)

Perhaps use HTTP/HTTPS instead of Web/SecureWeb.

I tend to prefer the first option because it allows us to potentially pass different options to different types, but passing the types is easier to implement. Up to you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fortuna I agree it would be helpful to export different functions to set different types of proxies and perhaps one method that sets them all at once such as SetProxyAll(). This way developers can choose one method if they just want to set a specific type of proxy.

  • Also, I realized that HTTP proxy also allows for setting username/password for authentication. Do you thing we should expose that in the API?

  • Regarding socks proxy, I am researching on how to do it on Windows but if I can't get it working, we can just return platform not supported error for SetSocksProxy on Windows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fortuna I did some further research on this. The table below summarizes system-wide support for various types of proxies on desktop platforms.

Proxy Type Windows MacOS Linux
HTTP Yes (No Auth)1 Yes Yes
HTTPS Yes (No Auth)1 Yes Yes (No Auth)3
FTP No No Yes (No Auth)
SOCKS No Yes (No Auth)2 Yes (No Auth)
  1. Windows does not explicitly distinguish between HTTP and HTTPS proxy. Also, username/password authentication is not supported.

  2. MacOS SOCKS does not seems to correctly support authentication even though it accepts credentials [ref].

  3. Username/Pass authentication is not currently supported for HTTPS proxy [ref].

Given the poor support for username/password authentication, do you think it makes sense to add authentication option to the sysproxy package?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably return not supported on iOS. I think you can check GOOS.

// Execute macOS specific commands to set proxy
// Get the active network interface
activeInterface, err := getActiveNetworkInterfaceMacOS()
if err != nil {
return err
}

// Set the web proxy and secure web proxy
if err := setProxyMacOS("web", activeInterface, ip, port); err != nil {
return err
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
}
if err := setProxyMacOS("secureweb", activeInterface, ip, port); err != nil {
return err
}

return nil
}

func UnsetProxy() error {
// Execute macOS specific commands to unset proxy
// Get the active network interface
activeInterface, err := getActiveNetworkInterfaceMacOS()
if err != nil {
return err
}

// Set the web proxy and secure web proxy
if err := removeProxyMacOS("web", activeInterface); err != nil {
return err
}
if err := removeProxyMacOS("secureweb", activeInterface); err != nil {
return err
}

return nil
}

// getActiveNetworkInterface finds the active network interface using shell commands.
func getActiveNetworkInterfaceMacOS() (string, error) {
cmd := "sh -c \"networksetup -listnetworkserviceorder | grep `route -n get 0.0.0.0 | grep 'interface' | cut -d ':' -f2` -B 1 | head -n 1 | cut -d ' ' -f2\""
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
out, err := exec.Command("bash", "-c", cmd).Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
}

// setProxyMacOS sets the specified type of proxy on the given network interface.
func setProxyMacOS(proxyType string, interfaceName string, ip string, port string) error {
var cmdStr string
if proxyType == "web" {
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
cmdStr = fmt.Sprintf("networksetup -setwebproxy \"%s\" %s %s", interfaceName, ip, port)
} else if proxyType == "secureweb" {
cmdStr = fmt.Sprintf("networksetup -setsecurewebproxy \"%s\" %s %s", interfaceName, ip, port)
} else {
return fmt.Errorf("unknown proxy type: %s", proxyType)
}

cmd := exec.Command("bash", "-c", cmdStr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

var stderr bytes.Buffer
cmd.Stderr = &stderr
amircybersec marked this conversation as resolved.
Show resolved Hide resolved

err := cmd.Run()
if err != nil {
return fmt.Errorf("%v: %s", err, stderr.String())
}
return nil
}

func removeProxyMacOS(proxyType string, interfaceName string) error {
var cmdStr string
if proxyType == "web" {
cmdStr = fmt.Sprintf("networksetup -setwebproxystate \"%s\" off", interfaceName)
} else if proxyType == "secureweb" {
cmdStr = fmt.Sprintf("networksetup -setsecurewebproxystate \"%s\" off", interfaceName)
} else {
return fmt.Errorf("unknown proxy type: %s", proxyType)
}

cmd := exec.Command("bash", "-c", cmdStr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't recreate the command. You already created it in the caller. I don't think runCommand is needed., since you can call cmd.Run() in the caller.

var stderr bytes.Buffer
cmd.Stderr = &stderr

err := cmd.Run()
if err != nil {
return fmt.Errorf("%v: %s", err, stderr.String())
}
return nil
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
}
73 changes: 73 additions & 0 deletions x/sysproxy/sysproxy_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//go:build linux

package sysproxy

import (
"fmt"
"os/exec"
)

func SetProxy(ip string, port string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably return not supported on Android. I think you can check GOOS?

// Execute Linux specific commands to set proxy
if err := setManualMode(); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should enable manual mode after you set the proxies, so whoever observing this change can get the right values. Also in case one of them fails.

return err
}
if err := setHttpProxy(ip, port); err != nil {
return err
}
if err := setHttpsProxy(ip, port); err != nil {
return err
}
if err := setFtpProxy(ip, port); err != nil {
return err
}
return nil
}

func setManualMode() error {
return execCommand("gsettings", "set", "org.gnome.system.proxy", "mode", "manual")
}

func setHttpProxy(ip string, port string) error {
if err := execCommand("gsettings", "set", "org.gnome.system.proxy.http", "host", ip); err != nil {
return err
}
if err := execCommand("gsettings", "set", "org.gnome.system.proxy.http", "port", port); err != nil {
return err
}
return nil
}

func setHttpsProxy(ip string, port string) error {
if err := execCommand("gsettings", "set", "org.gnome.system.proxy.https", "host", ip); err != nil {
return err
}
if err := execCommand("gsettings", "set", "org.gnome.system.proxy.https", "port", port); err != nil {
return err
}
return nil
}

func setFtpProxy(ip string, port string) error {
if err := execCommand("gsettings", "set", "org.gnome.system.proxy.ftp", "host", ip); err != nil {
return err
}
if err := execCommand("gsettings", "set", "org.gnome.system.proxy.ftp", "port", port); err != nil {
return err
}
return nil
}

func UnsetProxy() error {
// Execute Linux specific commands to unset proxy
return execCommand("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it support other modes? If so, do we need to backup the previous settings and restore it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jyyi1 The other modes are auto, and manual. Choosing manual, the system uses the last used proxy settings that can be manually overwritten. I can potentially backup the previous state before setting the proxy to the new settings and restore the system settings back to the previous state when UnsetProxy is called.

auto uses a link to .pac file that contains the proxy settings.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amircybersec marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also erase the individual proxy entries we added, in case someone else enables the manual mode later.

}

func execCommand(name string, arg ...string) error {
cmd := exec.Command(name, arg...)
err := cmd.Run()
if err != nil {
return fmt.Errorf("failed to execute command: %w", err)
}
return nil
}
13 changes: 13 additions & 0 deletions x/sysproxy/sysproxy_other.go
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this file so we get a build error instead of run time error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fortuna this approach was suggested by @jyyi1 which does what you have in mind (we get a build error instead of run time error). The functions in this file gets called if the platform we are building on is not darwin or linux, or windows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, I believe I need to explicitly exclude ios and android in the build constraints in this form: //go:build darwin && !ios in sysproxy_darwin.go file and //go:build linux && !android in sysproxy_linux.go

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build !linux && !windows && !darwin

package sysproxy

// SetProxy does nothing on unsupported platforms.
func SetProxy(ip string, port string) error {
return nil
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
}

// SetProxy does nothing on unsupported platforms.
func UnsetProxy() error {
return nil
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
}
108 changes: 108 additions & 0 deletions x/sysproxy/sysproxy_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//go:build windows

package sysproxy

import (
"errors"
"fmt"

"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)

var (
modwininet = windows.NewLazySystemDLL("wininet.dll")
procInternetSetOption = modwininet.NewProc("InternetSetOptionW")
)

const (
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
INTERNET_OPTION_SETTINGS_CHANGED = 39
INTERNET_OPTION_REFRESH = 37
)

func internetSetOption(hInternet uintptr, dwOption int, lpBuffer uintptr, dwBufferLength uint32) bool {
ret, _, _ := procInternetSetOption.Call(
hInternet,
uintptr(dwOption),
lpBuffer,
uintptr(dwBufferLength),
)
return ret != 0
}
amircybersec marked this conversation as resolved.
Show resolved Hide resolved

func resetWininetProxySettings() error {
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
result1 := internetSetOption(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to error, and return early if failed.

Suggested change
result1 := internetSetOption(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0)
if err := internetSetOption(0, INTERNET_OPTION_SETTINGS_CHANGED, 0, 0); err != nil {
return fmt.Errorf("call to InternetSetOptionW(INTERNET_OPTION_SETTINGS_CHANGED, 0, 0) failed: %w", err)
}

result2 := internetSetOption(0, INTERNET_OPTION_REFRESH, 0, 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to error and return if error.


if result1 && result2 {
fmt.Println("Operation successful")
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
return nil
} else {
fmt.Println("Operation failed")
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
return errors.New("Wininet setting change operation failed")
}
}

func SetProxy(ip string, port string) error {
key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Internet Settings`, registry.SET_VALUE)
if err != nil {
return err
}
defer key.Close()

values := map[string]interface{}{
"MigrateProxy": 1,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this option mean? Do we need to unset it in our UnsetProxy function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jyyi1 Documentation for MigrateProxy DWORD was sparse. From what I understood by reading up one some resources I found (1, 2), It appears that this is related to how Internet Explore / Edge migrate their proxy settings.

I am a bit conflicted now since the docs say that IE sets this value to 1 after migrating the settings. BTW, I followed the way GreenTunnel was setting up Windows proxy params and tested the code on Windows successfully. But there could be corner and untested cases that I missed.

If you recall in the office, we looked at Chrome proxy settings was in sync with system proxy settings and we could see the settings switching in the Browser on Windows. I did not however test this with IE. I am looking further into this...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the information. I think we can ignore IE for now because Microsoft has already ended its support on June 15, 2022.

For the Edge, since it's using Chromium, I believe it should behave the same as Chrome.

Let's remove this setting and make sure everything works fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jyyi1 It seems like "ProxyHttp1.1": 0, setting is also related to IE according to this. I am going to remove this one too and test the changes on Windows.

"ProxyEnable": 1,
"ProxyHttp1.1": 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar question to the MigrationProxy configuration, do we need to unset it?

"ProxyServer": fmt.Sprintf("%s:%s", ip, port),
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
"ProxyOverride": "*.local;<local>",
}

for name, value := range values {
switch v := value.(type) {
case int:
err = key.SetDWordValue(name, uint32(v))
case string:
err = key.SetStringValue(name, v)
default:
return fmt.Errorf("unsupported value type")
}
if err != nil {
return err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to unset the registry here, so we don't leave it in an unusable state?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. That's definitely a much safer approach. I will make a copy of settings param before making changes and revert then back to previous state at UnsetProxy.

}
}

// Refresh the settings
err = resetWininetProxySettings()
if err != nil {
return err
}

return nil
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
}

func UnsetProxy() error {
key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Internet Settings`, registry.SET_VALUE)
if err != nil {
return err
}
defer key.Close()

// Set ProxyEnable to 0 and ProxyServer to an empty string
err = key.SetDWordValue("ProxyEnable", 0)
if err != nil {
return err
}
err = key.SetStringValue("ProxyServer", "")
if err != nil {
return err
}

// Refresh the settings
err = resetWininetProxySettings()
if err != nil {
return err
}

return nil
amircybersec marked this conversation as resolved.
Show resolved Hide resolved
}
Loading