@@ -21,25 +21,23 @@ import (
2121 M "github.com/sagernet/sing/common/metadata"
2222 "github.com/sagernet/sing/common/x/list"
2323
24- "go4.org/netipx"
2524 "golang.org/x/sys/windows"
2625)
2726
2827type autoRedirect struct {
29- tunOptions * Options
30- ctx context.Context
31- connContext func (context.Context ) context.Context
32- handler Handler
33- logger logger.Logger
34- errorHandler func (error )
35- networkMonitor NetworkUpdateMonitor
36- networkListener * list.Element [NetworkUpdateCallback ]
37- interfaceFinder control.InterfaceFinder
38- driverManager * winredirect.Manager
39- redirectServer * redirectServer
40- routeAddressSet * []* netipx.IPSet
41- routeExcludeAddressSet * []* netipx.IPSet
42-
28+ tunOptions * Options
29+ ctx context.Context
30+ connContext func (context.Context ) context.Context
31+ handler Handler
32+ logger logger.Logger
33+ errorHandler func (error )
34+ networkMonitor NetworkUpdateMonitor
35+ networkListener * list.Element [NetworkUpdateCallback ]
36+ interfaceFinder control.InterfaceFinder
37+ driverManager * winredirect.Manager
38+ redirectServer * redirectServer
39+
40+ selfPID uint32
4341 enableIPv4 bool
4442 enableIPv6 bool
4543
@@ -56,22 +54,21 @@ type autoRedirect struct {
5654
5755func NewAutoRedirect (options AutoRedirectOptions ) (AutoRedirect , error ) {
5856 r := & autoRedirect {
59- tunOptions : options .TunOptions ,
60- ctx : options .Context ,
61- connContext : options .ConnContext ,
62- handler : options .Handler ,
63- logger : options .Logger ,
64- errorHandler : options .ErrorHandler ,
65- networkMonitor : options .NetworkMonitor ,
66- interfaceFinder : options .InterfaceFinder ,
67- routeAddressSet : options .RouteAddressSet ,
68- routeExcludeAddressSet : options .RouteExcludeAddressSet ,
69- workerCount : 1 ,
57+ tunOptions : options .TunOptions ,
58+ ctx : options .Context ,
59+ connContext : options .ConnContext ,
60+ handler : options .Handler ,
61+ logger : options .Logger ,
62+ errorHandler : options .ErrorHandler ,
63+ networkMonitor : options .NetworkMonitor ,
64+ interfaceFinder : options .InterfaceFinder ,
65+ workerCount : 1 ,
7066 }
7167 return r , nil
7268}
7369
7470func (r * autoRedirect ) Start () error {
71+ r .selfPID = uint32 (os .Getpid ())
7572 r .enableIPv4 = len (r .tunOptions .Inet4Address ) > 0
7673 r .enableIPv6 = len (r .tunOptions .Inet6Address ) > 0
7774 if ! r .enableIPv4 && ! r .enableIPv6 {
@@ -142,7 +139,7 @@ func (r *autoRedirect) startRedirect() error {
142139 redirectPort := M .AddrPortFromNet (server .listener .Addr ()).Port ()
143140 err = manager .SetConfig (& winredirect.Config {
144141 RedirectPort : redirectPort ,
145- ProxyPID : uint32 ( os . Getpid ()) ,
142+ ProxyPID : r . selfPID ,
146143 TunGUID : tunGUID ,
147144 })
148145 if err != nil {
@@ -173,9 +170,6 @@ func (r *autoRedirect) Close() error {
173170}
174171
175172func (r * autoRedirect ) UpdateRouteAddressSet () {
176- // Dynamic route address sets are updated via pointer indirection.
177- // The IPSet pointers are swapped atomically by the caller.
178- // No driver communication needed — all filtering is in Go.
179173}
180174
181175func (r * autoRedirect ) preMatchWorker () {
@@ -233,38 +227,33 @@ func (r *autoRedirect) evaluateConnection(conn *winredirect.PendingConn) uint32
233227 src := pendingConnSrc (conn )
234228
235229 // Proxy process outbound connections must never be redirected back into itself.
236- if conn .ProcessID == uint32 ( os . Getpid ()) {
230+ if conn .ProcessID == r . selfPID {
237231 return winredirect .VerdictBypass
238232 }
239233
240- // 1. Loopback destinations
241234 if dst .Addr .IsLoopback () {
242235 return winredirect .VerdictBypass
243236 }
244237
245- // DNS hijack: port 53 from local network → redirect to DNS server
246238 if ! r .tunOptions .EXP_DisableDNSHijack && dst .Port == 53 {
247239 if r .isLocalAddress (src .Addr ) {
248240 dnsServer := r .dnsServerForFamily (dst .Addr )
249241 if dnsServer .IsValid () {
250242 metadata := r .resolveMetadata (conn )
251243 ctx := r .newConnContext (metadata )
252- r .redirectServer .connTable .StoreDNS (src , dst , M .SocksaddrFrom (dnsServer , 53 ), ctx , metadata )
244+ r .redirectServer .connTable .StoreDNS (src , dst , M .SocksaddrFrom (dnsServer , 53 ), ctx )
253245 return winredirect .VerdictRedirect
254246 }
255247 }
256248 }
257249
258- // Strict route: reject disabled address family
259250 if r .tunOptions .StrictRoute && r .isDisabledFamily (dst .Addr ) {
260251 return winredirect .VerdictDrop
261252 }
262253
263- // Resolve PID → process path
264254 metadata := r .resolveMetadata (conn )
265255 ctx := r .newConnContext (metadata )
266256
267- // PrepareConnection (NFQUEUE equivalent)
268257 _ , err := r .handler .PrepareConnection (ctx , "tcp" , src , dst , nil , 0 )
269258 if errors .Is (err , ErrDrop ) {
270259 return winredirect .VerdictDrop
@@ -276,8 +265,7 @@ func (r *autoRedirect) evaluateConnection(conn *winredirect.PendingConn) uint32
276265 r .logger .Warn ("prepare connection fallback to redirect: " , err )
277266 }
278267
279- // Store metadata for redirect server
280- r .redirectServer .connTable .Store (src , dst , ctx , metadata )
268+ r .redirectServer .connTable .Store (src , dst , ctx )
281269
282270 return winredirect .VerdictRedirect
283271}
0 commit comments