Fix: resolver dial context udp
This commit is contained in:
parent
038cc1f6b5
commit
d0c23998d2
5 changed files with 79 additions and 10 deletions
33
README.md
33
README.md
|
@ -36,6 +36,37 @@
|
||||||
Documentations are now moved to [GitHub Wiki](https://github.com/Dreamacro/clash/wiki).
|
Documentations are now moved to [GitHub Wiki](https://github.com/Dreamacro/clash/wiki).
|
||||||
|
|
||||||
## Advanced usage for this branch
|
## Advanced usage for this branch
|
||||||
|
### DNS configuration
|
||||||
|
Support resolve ip with a proxy tunnel.
|
||||||
|
|
||||||
|
Support `geosite` with `fallback-filter`.
|
||||||
|
```yaml
|
||||||
|
dns:
|
||||||
|
enable: true
|
||||||
|
use-hosts: true
|
||||||
|
ipv6: false
|
||||||
|
enhanced-mode: fake-ip
|
||||||
|
fake-ip-range: 198.18.0.1/16
|
||||||
|
listen: 127.0.0.1:6868
|
||||||
|
default-nameserver:
|
||||||
|
- 119.29.29.29
|
||||||
|
- 114.114.114.114
|
||||||
|
nameserver:
|
||||||
|
- https://doh.pub/dns-query
|
||||||
|
- tls://223.5.5.5:853
|
||||||
|
fallback:
|
||||||
|
- 'https://1.0.0.1/dns-query#Proxy' # append the proxy adapter name to the end of DNS URL with '#' prefix.
|
||||||
|
- 'tls://8.8.4.4:853#Proxy'
|
||||||
|
fallback-filter:
|
||||||
|
geoip: false
|
||||||
|
geosite:
|
||||||
|
- gfw # `geosite` filter only use fallback server to resolve ip, prevent DNS leaks to unsafe DNS providers.
|
||||||
|
domain:
|
||||||
|
- +.example.com
|
||||||
|
ipcidr:
|
||||||
|
- 0.0.0.0/32
|
||||||
|
```
|
||||||
|
|
||||||
### TUN configuration
|
### TUN configuration
|
||||||
Supports macOS, Linux and Windows.
|
Supports macOS, Linux and Windows.
|
||||||
|
|
||||||
|
@ -90,7 +121,7 @@ rules:
|
||||||
- GEOSITE,geolocation-!cn,PROXY
|
- GEOSITE,geolocation-!cn,PROXY
|
||||||
|
|
||||||
# source IPCIDR condition for all rules in gateway proxy
|
# source IPCIDR condition for all rules in gateway proxy
|
||||||
#- GEOSITE,apple,PROXY,192.168.1.88/32,192.168.1.99/32
|
#- GEOSITE,geolocation-!cn,REJECT,192.168.1.88/32,192.168.1.99/32
|
||||||
|
|
||||||
- GEOIP,telegram,PROXY,no-resolve
|
- GEOIP,telegram,PROXY,no-resolve
|
||||||
- GEOIP,private,DIRECT,no-resolve
|
- GEOIP,private,DIRECT,no-resolve
|
||||||
|
|
|
@ -49,14 +49,14 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var conn net.Conn
|
var conn net.Conn
|
||||||
if c.proxyAdapter != "" && network == "tcp" {
|
if c.proxyAdapter == "" {
|
||||||
conn, err = dialContextWithProxyAdapter(ctx, c.proxyAdapter, ip, c.port)
|
|
||||||
} else {
|
|
||||||
options := []dialer.Option{}
|
options := []dialer.Option{}
|
||||||
if c.iface != "" {
|
if c.iface != "" {
|
||||||
options = append(options, dialer.WithInterface(c.iface))
|
options = append(options, dialer.WithInterface(c.iface))
|
||||||
}
|
}
|
||||||
conn, err = dialer.DialContext(ctx, network, net.JoinHostPort(c.host, c.port), options...)
|
conn, err = dialer.DialContext(ctx, network, net.JoinHostPort(ip.String(), c.port), options...)
|
||||||
|
} else {
|
||||||
|
conn, err = dialContextWithProxyAdapter(ctx, c.proxyAdapter, network, ip, c.port)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -100,7 +100,7 @@ func newDoHClient(url string, r *Resolver, proxyAdapter string) *dohClient {
|
||||||
if proxyAdapter == "" {
|
if proxyAdapter == "" {
|
||||||
return dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), port))
|
return dialer.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), port))
|
||||||
} else {
|
} else {
|
||||||
return dialContextWithProxyAdapter(ctx, proxyAdapter, ip, port)
|
return dialContextWithProxyAdapter(ctx, proxyAdapter, "tcp", ip, port)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -379,6 +379,7 @@ func NewMainResolver(old *Resolver) *Resolver {
|
||||||
main: old.main,
|
main: old.main,
|
||||||
lruCache: old.lruCache,
|
lruCache: old.lruCache,
|
||||||
hosts: old.hosts,
|
hosts: old.hosts,
|
||||||
|
policy: old.policy,
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
45
dns/util.go
45
dns/util.go
|
@ -110,25 +110,62 @@ func msgToIP(msg *D.Msg) []net.IP {
|
||||||
return ips
|
return ips
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialContextWithProxyAdapter(ctx context.Context, adapterName string, dstIP net.IP, port string) (net.Conn, error) {
|
type wrapPacketConn struct {
|
||||||
|
net.PacketConn
|
||||||
|
rAddr net.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wpc *wrapPacketConn) Read(b []byte) (n int, err error) {
|
||||||
|
n, _, err = wpc.PacketConn.ReadFrom(b)
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wpc *wrapPacketConn) Write(b []byte) (n int, err error) {
|
||||||
|
return wpc.PacketConn.WriteTo(b, wpc.rAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wpc *wrapPacketConn) RemoteAddr() net.Addr {
|
||||||
|
return wpc.rAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func dialContextWithProxyAdapter(ctx context.Context, adapterName string, network string, dstIP net.IP, port string) (net.Conn, error) {
|
||||||
adapter, ok := tunnel.Proxies()[adapterName]
|
adapter, ok := tunnel.Proxies()[adapterName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("proxy dapter [%s] not found", adapterName)
|
return nil, fmt.Errorf("proxy adapter [%s] not found", adapterName)
|
||||||
|
}
|
||||||
|
|
||||||
|
networkType := C.TCP
|
||||||
|
if network == "udp" {
|
||||||
|
if !adapter.SupportUDP() {
|
||||||
|
return nil, fmt.Errorf("proxy adapter [%s] UDP is not supported", adapterName)
|
||||||
|
}
|
||||||
|
networkType = C.UDP
|
||||||
}
|
}
|
||||||
|
|
||||||
addrType := C.AtypIPv4
|
addrType := C.AtypIPv4
|
||||||
|
|
||||||
if dstIP.To4() == nil {
|
if dstIP.To4() == nil {
|
||||||
addrType = C.AtypIPv6
|
addrType = C.AtypIPv6
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata := &C.Metadata{
|
metadata := &C.Metadata{
|
||||||
NetWork: C.TCP,
|
NetWork: networkType,
|
||||||
AddrType: addrType,
|
AddrType: addrType,
|
||||||
Host: "",
|
Host: "",
|
||||||
DstIP: dstIP,
|
DstIP: dstIP,
|
||||||
DstPort: port,
|
DstPort: port,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if networkType == C.UDP {
|
||||||
|
packetConn, err := adapter.ListenPacketContext(ctx, metadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &wrapPacketConn{
|
||||||
|
PacketConn: packetConn,
|
||||||
|
rAddr: metadata.UDPAddr(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
return adapter.DialContext(ctx, metadata)
|
return adapter.DialContext(ctx, metadata)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue