1
1
package settings
2
2
3
3
import (
4
+ "context"
4
5
"net/netip"
6
+ "strconv"
5
7
"strings"
6
8
7
9
"github.com/sagernet/sing-box/adapter"
8
10
"github.com/sagernet/sing-tun"
9
11
E "github.com/sagernet/sing/common/exceptions"
10
- F "github.com/sagernet/sing/common/format "
12
+ M "github.com/sagernet/sing/common/metadata "
11
13
"github.com/sagernet/sing/common/shell"
12
14
"github.com/sagernet/sing/common/x/list"
13
15
)
14
16
15
- type systemProxy struct {
17
+ type DarwinSystemProxy struct {
16
18
monitor tun.DefaultInterfaceMonitor
17
19
interfaceName string
18
20
element * list.Element [tun.DefaultInterfaceUpdateCallback ]
19
- port uint16
20
- isMixed bool
21
+ serverAddr M.Socksaddr
22
+ supportSOCKS bool
23
+ isEnabled bool
21
24
}
22
25
23
- func ( p * systemProxy ) update ( event int ) {
24
- newInterfaceName := p . monitor . DefaultInterfaceName ( netip . IPv4Unspecified () )
25
- if p . interfaceName == newInterfaceName {
26
- return
26
+ func NewSystemProxy ( ctx context. Context , serverAddr M. Socksaddr , supportSOCKS bool ) ( * DarwinSystemProxy , error ) {
27
+ interfaceMonitor := adapter . RouterFromContext ( ctx ). InterfaceMonitor ( )
28
+ if interfaceMonitor == nil {
29
+ return nil , E . New ( "missing interface monitor" )
27
30
}
28
- if p .interfaceName != "" {
29
- _ = p .unset ()
31
+ proxy := & DarwinSystemProxy {
32
+ monitor : interfaceMonitor ,
33
+ serverAddr : serverAddr ,
34
+ supportSOCKS : supportSOCKS ,
30
35
}
31
- p .interfaceName = newInterfaceName
36
+ proxy .element = interfaceMonitor .RegisterCallback (proxy .update )
37
+ return proxy , nil
38
+ }
39
+
40
+ func (p * DarwinSystemProxy ) IsEnabled () bool {
41
+ return p .isEnabled
42
+ }
43
+
44
+ func (p * DarwinSystemProxy ) Enable () error {
45
+ return p .update0 ()
46
+ }
47
+
48
+ func (p * DarwinSystemProxy ) Disable () error {
32
49
interfaceDisplayName , err := getInterfaceDisplayName (p .interfaceName )
33
50
if err != nil {
34
- return
51
+ return err
35
52
}
36
- if p .isMixed {
37
- err = shell .Exec ("networksetup" , "-setsocksfirewallproxy " , interfaceDisplayName , "127.0.0.1" , F . ToString ( p . port ) ).Attach ().Run ()
53
+ if p .supportSOCKS {
54
+ err = shell .Exec ("networksetup" , "-setsocksfirewallproxystate " , interfaceDisplayName , "off" ).Attach ().Run ()
38
55
}
39
56
if err == nil {
40
- err = shell .Exec ("networksetup" , "-setwebproxy" , interfaceDisplayName , "127.0.0.1" , F .ToString (p .port )).Attach ().Run ()
57
+ err = shell .Exec ("networksetup" , "-setwebproxystate" , interfaceDisplayName , "off" ).Attach ().Run ()
58
+ }
59
+ if err == nil {
60
+ err = shell .Exec ("networksetup" , "-setsecurewebproxystate" , interfaceDisplayName , "off" ).Attach ().Run ()
41
61
}
42
62
if err == nil {
43
- _ = shell .Exec ("networksetup" , "-setsecurewebproxy" , interfaceDisplayName , "127.0.0.1" , F .ToString (p .port )).Attach ().Run ()
63
+ p .isEnabled = false
64
+ }
65
+ return err
66
+ }
67
+
68
+ func (p * DarwinSystemProxy ) update (event int ) {
69
+ if event & tun .EventInterfaceUpdate == 0 {
70
+ return
71
+ }
72
+ if ! p .isEnabled {
73
+ return
44
74
}
45
- return
75
+ _ = p . update0 ()
46
76
}
47
77
48
- func (p * systemProxy ) unset () error {
78
+ func (p * DarwinSystemProxy ) update0 () error {
79
+ newInterfaceName := p .monitor .DefaultInterfaceName (netip .IPv4Unspecified ())
80
+ if p .interfaceName == newInterfaceName {
81
+ return nil
82
+ }
83
+ if p .interfaceName != "" {
84
+ _ = p .Disable ()
85
+ }
86
+ p .interfaceName = newInterfaceName
49
87
interfaceDisplayName , err := getInterfaceDisplayName (p .interfaceName )
50
88
if err != nil {
51
89
return err
52
90
}
53
- if p .isMixed {
54
- err = shell .Exec ("networksetup" , "-setsocksfirewallproxystate " , interfaceDisplayName , "off" ).Attach ().Run ()
91
+ if p .supportSOCKS {
92
+ err = shell .Exec ("networksetup" , "-setsocksfirewallproxy " , interfaceDisplayName , p . serverAddr . AddrString (), strconv . Itoa ( int ( p . serverAddr . Port )) ).Attach ().Run ()
55
93
}
56
- if err = = nil {
57
- err = shell . Exec ( "networksetup" , "-setwebproxystate" , interfaceDisplayName , "off" ). Attach (). Run ()
94
+ if err ! = nil {
95
+ return err
58
96
}
59
- if err == nil {
60
- err = shell .Exec ("networksetup" , "-setsecurewebproxystate" , interfaceDisplayName , "off" ).Attach ().Run ()
97
+ err = shell .Exec ("networksetup" , "-setwebproxy" , interfaceDisplayName , p .serverAddr .AddrString (), strconv .Itoa (int (p .serverAddr .Port ))).Attach ().Run ()
98
+ if err != nil {
99
+ return err
61
100
}
62
- return err
101
+ err = shell .Exec ("networksetup" , "-setsecurewebproxy" , interfaceDisplayName , p .serverAddr .AddrString (), strconv .Itoa (int (p .serverAddr .Port ))).Attach ().Run ()
102
+ if err != nil {
103
+ return err
104
+ }
105
+ p .isEnabled = true
106
+ return nil
63
107
}
64
108
65
109
func getInterfaceDisplayName (name string ) (string , error ) {
@@ -77,21 +121,3 @@ func getInterfaceDisplayName(name string) (string, error) {
77
121
}
78
122
return "" , E .New (name , " not found in networksetup -listallhardwareports" )
79
123
}
80
-
81
- func SetSystemProxy (router adapter.Router , port uint16 , isMixed bool ) (func () error , error ) {
82
- interfaceMonitor := router .InterfaceMonitor ()
83
- if interfaceMonitor == nil {
84
- return nil , E .New ("missing interface monitor" )
85
- }
86
- proxy := & systemProxy {
87
- monitor : interfaceMonitor ,
88
- port : port ,
89
- isMixed : isMixed ,
90
- }
91
- proxy .update (tun .EventInterfaceUpdate )
92
- proxy .element = interfaceMonitor .RegisterCallback (proxy .update )
93
- return func () error {
94
- interfaceMonitor .UnregisterCallback (proxy .element )
95
- return proxy .unset ()
96
- }, nil
97
- }
0 commit comments