diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index 3819f52b..ab44a1d5 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -325,6 +325,7 @@ func (h *Handler) Start() error { // Close implements common.Closable. func (h *Handler) Close() error { common.Close(h.mux) + common.Close(h.proxy) return nil } diff --git a/go.mod b/go.mod index c7047ed0..b8dadd1a 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.24 require ( github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 - github.com/cloudflare/circl v1.6.0 + github.com/cloudflare/circl v1.6.1 github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 github.com/golang/mock v1.7.0-rc.1 github.com/google/go-cmp v0.7.0 github.com/gorilla/websocket v1.5.3 - github.com/miekg/dns v1.1.64 + github.com/miekg/dns v1.1.65 github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.8.0 github.com/quic-go/quic-go v0.50.1 @@ -22,12 +22,12 @@ require ( github.com/vishvananda/netlink v1.3.0 github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/crypto v0.36.0 - golang.org/x/net v0.38.0 - golang.org/x/sync v0.12.0 - golang.org/x/sys v0.31.0 + golang.org/x/crypto v0.37.0 + golang.org/x/net v0.39.0 + golang.org/x/sync v0.13.0 + golang.org/x/sys v0.32.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 - google.golang.org/grpc v1.71.0 + google.golang.org/grpc v1.71.1 google.golang.org/protobuf v1.36.6 gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h12.io/socks v1.0.3 @@ -51,7 +51,7 @@ require ( go.uber.org/mock v0.5.0 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/mod v0.23.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.30.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect diff --git a/go.sum b/go.sum index d4df8932..76ec3c42 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJS github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= -github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= +github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -38,8 +38,8 @@ github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0N github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= -github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= +github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc= +github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= @@ -97,8 +97,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= @@ -107,12 +107,12 @@ golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -121,14 +121,14 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -145,8 +145,8 @@ golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uI golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= -google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= -google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/infra/conf/cfgcommon/duration/duration.go b/infra/conf/cfgcommon/duration/duration.go index aed8e613..f1bbd4d7 100644 --- a/infra/conf/cfgcommon/duration/duration.go +++ b/infra/conf/cfgcommon/duration/duration.go @@ -8,11 +8,13 @@ import ( type Duration int64 +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON func (d *Duration) MarshalJSON() ([]byte, error) { dr := time.Duration(*d) return json.Marshal(dr.String()) } +// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (d *Duration) UnmarshalJSON(b []byte) error { var v interface{} if err := json.Unmarshal(b, &v); err != nil { diff --git a/infra/conf/common.go b/infra/conf/common.go index fa48edea..ab3cfba7 100644 --- a/infra/conf/common.go +++ b/infra/conf/common.go @@ -23,6 +23,7 @@ func (v StringList) Len() int { return len(v) } +// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (v *StringList) UnmarshalJSON(data []byte) error { var strarray []string if err := json.Unmarshal(data, &strarray); err == nil { @@ -43,10 +44,12 @@ type Address struct { net.Address } -func (v Address) MarshalJSON() ([]byte, error) { +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON +func (v *Address) MarshalJSON() ([]byte, error) { return json.Marshal(v.Address.String()) } +// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (v *Address) UnmarshalJSON(data []byte) error { var rawStr string if err := json.Unmarshal(data, &rawStr); err != nil { @@ -81,6 +84,7 @@ func (v Network) Build() net.Network { type NetworkList []Network +// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (v *NetworkList) UnmarshalJSON(data []byte) error { var strarray []Network if err := json.Unmarshal(data, &strarray); err == nil { @@ -169,6 +173,19 @@ func (v *PortRange) Build() *net.PortRange { } } +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON +func (v *PortRange) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +func (port *PortRange) String() string { + if port.From == port.To { + return strconv.Itoa(int(port.From)) + } else { + return fmt.Sprintf("%d-%d", port.From, port.To) + } +} + // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (v *PortRange) UnmarshalJSON(data []byte) error { port, err := parseIntPort(data) @@ -203,20 +220,21 @@ func (list *PortList) Build() *net.PortList { return portList } -func (v PortList) MarshalJSON() ([]byte, error) { - return json.Marshal(v.String()) +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON +func (v *PortList) MarshalJSON() ([]byte, error) { + portStr := v.String() + port, err := strconv.Atoi(portStr) + if err == nil { + return json.Marshal(port) + } else { + return json.Marshal(portStr) + } } func (v PortList) String() string { ports := []string{} for _, port := range v.Range { - if port.From == port.To { - p := strconv.Itoa(int(port.From)) - ports = append(ports, p) - } else { - p := fmt.Sprintf("%d-%d", port.From, port.To) - ports = append(ports, p) - } + ports = append(ports, port.String()) } return strings.Join(ports, ",") } @@ -277,7 +295,8 @@ type Int32Range struct { To int32 } -func (v Int32Range) MarshalJSON() ([]byte, error) { +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON +func (v *Int32Range) MarshalJSON() ([]byte, error) { return json.Marshal(v.String()) } @@ -289,6 +308,7 @@ func (v Int32Range) String() string { } } +// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (v *Int32Range) UnmarshalJSON(data []byte) error { defer v.ensureOrder() var str string diff --git a/infra/conf/dns.go b/infra/conf/dns.go index 607cbf07..7baeda87 100644 --- a/infra/conf/dns.go +++ b/infra/conf/dns.go @@ -25,6 +25,7 @@ type NameServerConfig struct { TimeoutMs uint64 `json:"timeoutMs"` } +// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (c *NameServerConfig) UnmarshalJSON(data []byte) error { var address Address if err := json.Unmarshal(data, &address); err == nil { @@ -163,6 +164,18 @@ type HostAddress struct { addrs []*Address } +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON +func (h *HostAddress) MarshalJSON() ([]byte, error) { + if (h.addr != nil) != (h.addrs != nil) { + if h.addr != nil { + return json.Marshal(h.addr) + } else if h.addrs != nil { + return json.Marshal(h.addrs) + } + } + return nil, errors.New("unexpected config state") +} + // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (h *HostAddress) UnmarshalJSON(data []byte) error { addr := new(Address) @@ -208,6 +221,11 @@ func getHostMapping(ha *HostAddress) *dns.Config_HostMapping { } } +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON +func (m *HostsWrapper) MarshalJSON() ([]byte, error) { + return json.Marshal(m.Hosts) +} + // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (m *HostsWrapper) UnmarshalJSON(data []byte) error { hosts := make(map[string]*HostAddress) diff --git a/infra/conf/fakedns.go b/infra/conf/fakedns.go index 86240366..3aa20115 100644 --- a/infra/conf/fakedns.go +++ b/infra/conf/fakedns.go @@ -20,6 +20,18 @@ type FakeDNSConfig struct { pools []*FakeDNSPoolElementConfig } +// MarshalJSON implements encoding/json.Marshaler.MarshalJSON +func (f *FakeDNSConfig) MarshalJSON() ([]byte, error) { + if (f.pool != nil) != (f.pools != nil) { + if f.pool != nil { + return json.Marshal(f.pool) + } else if f.pools != nil { + return json.Marshal(f.pools) + } + } + return nil, errors.New("unexpected config state") +} + // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error { var pool FakeDNSPoolElementConfig diff --git a/proxy/wireguard/client.go b/proxy/wireguard/client.go index ff1592ef..345581c7 100644 --- a/proxy/wireguard/client.go +++ b/proxy/wireguard/client.go @@ -77,6 +77,20 @@ func New(ctx context.Context, conf *DeviceConfig) (*Handler, error) { }, nil } +func (h *Handler) Close() (err error) { + go func() { + h.wgLock.Lock() + defer h.wgLock.Unlock() + + if h.net != nil { + _ = h.net.Close() + h.net = nil + } + }() + + return nil +} + func (h *Handler) processWireGuard(ctx context.Context, dialer internet.Dialer) (err error) { h.wgLock.Lock() defer h.wgLock.Unlock() diff --git a/transport/internet/sockopt_windows.go b/transport/internet/sockopt_windows.go index dd3f0390..fb8a9703 100644 --- a/transport/internet/sockopt_windows.go +++ b/transport/internet/sockopt_windows.go @@ -14,12 +14,9 @@ import ( ) const ( - TCP_FASTOPEN = 15 - IP_UNICAST_IF = 31 - IPV6_UNICAST_IF = 31 - IP_MULTICAST_IF = 9 - IPV6_MULTICAST_IF = 9 - IPV6_V6ONLY = 27 + TCP_FASTOPEN = 15 + IP_UNICAST_IF = 31 + IPV6_UNICAST_IF = 31 ) func setTFO(fd syscall.Handle, tfo int) error { @@ -51,14 +48,14 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, IP_UNICAST_IF, int(idx)); err != nil { return errors.New("failed to set IP_UNICAST_IF").Base(err) } - if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, IP_MULTICAST_IF, int(idx)); err != nil { + if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, int(idx)); err != nil { return errors.New("failed to set IP_MULTICAST_IF").Base(err) } } else { if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_UNICAST_IF, inf.Index); err != nil { return errors.New("failed to set IPV6_UNICAST_IF").Base(err) } - if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_MULTICAST_IF, inf.Index); err != nil { + if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, inf.Index); err != nil { return errors.New("failed to set IPV6_MULTICAST_IF").Base(err) } } @@ -135,7 +132,7 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) } if config.V6Only { - if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_V6ONLY, 1); err != nil { + if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 1); err != nil { return errors.New("failed to set IPV6_V6ONLY").Base(err) } } diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index c0c8c403..ba7db103 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -65,6 +65,11 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne return nil, err } lc.Control = func(network, address string, c syscall.RawConn) error { + for _, ctl := range d.controllers { + if err := ctl(network, address, c); err != nil { + errors.LogInfoInner(ctx, err, "failed to apply external controller") + } + } return c.Control(func(fd uintptr) { if sockopt != nil { if err := applyOutboundSocketOptions(network, destAddr.String(), fd, sockopt); err != nil {