From d397d30fb594b168753364b0802bab1259803550 Mon Sep 17 00:00:00 2001
From: Ledorub <ledorubden@gmail.com>
Date: Sun, 25 Aug 2024 09:57:38 +0300
Subject: [PATCH] Refactor proxy setting. (#191)

---
 cmd/spoof-dpi/main.go |  2 +-
 util/os.go            | 79 +++++++++++++++++++++++++++----------------
 2 files changed, 50 insertions(+), 31 deletions(-)

diff --git a/cmd/spoof-dpi/main.go b/cmd/spoof-dpi/main.go
index ca71397..4e1b902 100644
--- a/cmd/spoof-dpi/main.go
+++ b/cmd/spoof-dpi/main.go
@@ -36,7 +36,7 @@ func main() {
 	}
 
 	if config.SystemProxy {
-		if err := util.SetOsProxy(config.Port); err != nil {
+		if err := util.SetOsProxy(uint16(config.Port)); err != nil {
 			logger.Fatal().Msgf("error while changing proxy settings: %s", err)
 		}
 		defer func() {
diff --git a/util/os.go b/util/os.go
index 4c2ecae..e251488 100644
--- a/util/os.go
+++ b/util/os.go
@@ -5,15 +5,19 @@ import (
 	"fmt"
 	"os/exec"
 	"runtime"
+	"strconv"
 	"strings"
 )
 
-const getDefaultNetworkCMD = "networksetup -listnetworkserviceorder | grep" +
-	" `(route -n get default | grep 'interface' || route -n get -inet6 default | grep 'interface') | cut -d ':' -f2`" +
-	" -B 1 | head -n 1 | cut -d ' ' -f 2-"
+const (
+	getDefaultNetworkCMD = "networksetup -listnetworkserviceorder | grep" +
+		" `(route -n get default | grep 'interface' || route -n get -inet6 default | grep 'interface') | cut -d ':' -f2`" +
+		" -B 1 | head -n 1 | cut -d ' ' -f 2-"
+	darwinOS = "darwin"
+)
 
-func SetOsProxy(port int) error {
-	if runtime.GOOS != "darwin" {
+func SetOsProxy(port uint16) error {
+	if runtime.GOOS != darwinOS {
 		return nil
 	}
 
@@ -22,23 +26,11 @@ func SetOsProxy(port int) error {
 		return err
 	}
 
-	args := fmt.Sprintf("'%s' 127.0.0.1 %d", network, port)
-
-	_, err = exec.Command("sh", "-c", "networksetup -setwebproxy "+args).Output()
-	if err != nil {
-		return err
-	}
-
-	_, err = exec.Command("sh", "-c", "networksetup -setsecurewebproxy "+args).Output()
-	if err != nil {
-		return err
-	}
-
-	return nil
+	return setProxy(getProxyTypes(), network, "127.0.0.1", port)
 }
 
 func UnsetOsProxy() error {
-	if runtime.GOOS != "darwin" {
+	if runtime.GOOS != darwinOS {
 		return nil
 	}
 
@@ -47,17 +39,7 @@ func UnsetOsProxy() error {
 		return err
 	}
 
-	_, err = exec.Command("sh", "-c", "networksetup -setwebproxystate "+"'"+network+"'"+" off").Output()
-	if err != nil {
-		return err
-	}
-
-	_, err = exec.Command("sh", "-c", "networksetup -setsecurewebproxystate "+"'"+network+"'"+" off").Output()
-	if err != nil {
-		return err
-	}
-
-	return nil
+	return unsetProxy(getProxyTypes(), network)
 }
 
 func getDefaultNetwork() (string, error) {
@@ -69,3 +51,40 @@ func getDefaultNetwork() (string, error) {
 	}
 	return strings.TrimSpace(string(network)), nil
 }
+
+func getProxyTypes() []string {
+	return []string{"webproxy", "securewebproxy"}
+}
+
+func setProxy(proxyTypes []string, network, domain string, port uint16) error {
+	args := []string{"", network, domain, strconv.FormatUint(uint64(port), 10)}
+
+	for _, proxyType := range proxyTypes {
+		args[0] = "-set" + proxyType
+		if err := networkSetup(args); err != nil {
+			return fmt.Errorf("setting %s: %w", proxyType, err)
+		}
+	}
+	return nil
+}
+
+func unsetProxy(proxyTypes []string, network string) error {
+	args := []string{"", network, "off"}
+
+	for _, proxyType := range proxyTypes {
+		args[0] = "-set" + proxyType + "state"
+		if err := networkSetup(args); err != nil {
+			return fmt.Errorf("unsetting %s: %w", proxyType, err)
+		}
+	}
+	return nil
+}
+
+func networkSetup(args []string) error {
+	cmd := exec.Command("networksetup", args...)
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		return fmt.Errorf("%s: %s", cmd.String(), out)
+	}
+	return nil
+}