Feature: resolve ip with a proxy adapter

This commit is contained in:
yaling888
2022-02-23 02:38:50 +08:00
parent b192238699
commit d876d6e74c
14 changed files with 357 additions and 101 deletions

View File

@ -9,6 +9,19 @@ import (
)
func DialContext(ctx context.Context, network, address string, options ...Option) (net.Conn, error) {
opt := &option{
interfaceName: DefaultInterface.Load(),
routingMark: int(DefaultRoutingMark.Load()),
}
for _, o := range DefaultOptions {
o(opt)
}
for _, o := range options {
o(opt)
}
switch network {
case "tcp4", "tcp6", "udp4", "udp6":
host, port, err := net.SplitHostPort(address)
@ -19,17 +32,25 @@ func DialContext(ctx context.Context, network, address string, options ...Option
var ip net.IP
switch network {
case "tcp4", "udp4":
ip, err = resolver.ResolveIPv4(host)
if opt.interfaceName != "" {
ip, err = resolver.ResolveIPv4WithMain(host)
} else {
ip, err = resolver.ResolveIPv4(host)
}
default:
ip, err = resolver.ResolveIPv6(host)
if opt.interfaceName != "" {
ip, err = resolver.ResolveIPv6WithMain(host)
} else {
ip, err = resolver.ResolveIPv6(host)
}
}
if err != nil {
return nil, err
}
return dialContext(ctx, network, ip, port, options)
return dialContext(ctx, network, ip, port, opt)
case "tcp", "udp":
return dualStackDialContext(ctx, network, address, options)
return dualStackDialContext(ctx, network, address, opt)
default:
return nil, errors.New("network invalid")
}
@ -67,20 +88,7 @@ func ListenPacket(ctx context.Context, network, address string, options ...Optio
return lc.ListenPacket(ctx, network, address)
}
func dialContext(ctx context.Context, network string, destination net.IP, port string, options []Option) (net.Conn, error) {
opt := &option{
interfaceName: DefaultInterface.Load(),
routingMark: int(DefaultRoutingMark.Load()),
}
for _, o := range DefaultOptions {
o(opt)
}
for _, o := range options {
o(opt)
}
func dialContext(ctx context.Context, network string, destination net.IP, port string, opt *option) (net.Conn, error) {
dialer := &net.Dialer{}
if opt.interfaceName != "" {
if err := bindIfaceToDialer(opt.interfaceName, dialer, network, destination); err != nil {
@ -94,7 +102,7 @@ func dialContext(ctx context.Context, network string, destination net.IP, port s
return dialer.DialContext(ctx, network, net.JoinHostPort(destination.String(), port))
}
func dualStackDialContext(ctx context.Context, network, address string, options []Option) (net.Conn, error) {
func dualStackDialContext(ctx context.Context, network, address string, opt *option) (net.Conn, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return nil, err
@ -127,16 +135,24 @@ func dualStackDialContext(ctx context.Context, network, address string, options
var ip net.IP
if ipv6 {
ip, result.error = resolver.ResolveIPv6(host)
if opt.interfaceName != "" {
ip, result.error = resolver.ResolveIPv6WithMain(host)
} else {
ip, result.error = resolver.ResolveIPv6(host)
}
} else {
ip, result.error = resolver.ResolveIPv4(host)
if opt.interfaceName != "" {
ip, result.error = resolver.ResolveIPv4WithMain(host)
} else {
ip, result.error = resolver.ResolveIPv4(host)
}
}
if result.error != nil {
return
}
result.resolved = true
result.Conn, result.error = dialContext(ctx, network, ip, port, options)
result.Conn, result.error = dialContext(ctx, network, ip, port, opt)
}
go startRacer(ctx, network+"4", host, false)

View File

@ -0,0 +1,30 @@
package geodata
import (
"github.com/Dreamacro/clash/component/geodata/router"
)
func LoadGeoSiteMatcher(countryCode string) (*router.DomainMatcher, int, error) {
geoLoaderName := "standard"
geoLoader, err := GetGeoDataLoader(geoLoaderName)
if err != nil {
return nil, 0, err
}
domains, err := geoLoader.LoadGeoSite(countryCode)
if err != nil {
return nil, 0, err
}
/**
linear: linear algorithm
matcher, err := router.NewDomainMatcher(domains)
mphminimal perfect hash algorithm
*/
matcher, err := router.NewMphMatcherGroup(domains)
if err != nil {
return nil, 0, err
}
return matcher, len(domains), nil
}

View File

@ -15,6 +15,9 @@ var (
// DefaultResolver aim to resolve ip
DefaultResolver Resolver
// MainResolver resolve ip with main domain server
MainResolver Resolver
// DisableIPv6 means don't resolve ipv6 host
// default value is true
DisableIPv6 = true
@ -40,6 +43,14 @@ type Resolver interface {
// ResolveIPv4 with a host, return ipv4
func ResolveIPv4(host string) (net.IP, error) {
return ResolveIPv4WithResolver(host, DefaultResolver)
}
func ResolveIPv4WithMain(host string) (net.IP, error) {
return ResolveIPv4WithResolver(host, MainResolver)
}
func ResolveIPv4WithResolver(host string, r Resolver) (net.IP, error) {
if node := DefaultHosts.Search(host); node != nil {
if ip := node.Data.(net.IP).To4(); ip != nil {
return ip, nil
@ -54,8 +65,8 @@ func ResolveIPv4(host string) (net.IP, error) {
return nil, ErrIPVersion
}
if DefaultResolver != nil {
return DefaultResolver.ResolveIPv4(host)
if r != nil {
return r.ResolveIPv4(host)
}
ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout)
@ -72,6 +83,14 @@ func ResolveIPv4(host string) (net.IP, error) {
// ResolveIPv6 with a host, return ipv6
func ResolveIPv6(host string) (net.IP, error) {
return ResolveIPv6WithResolver(host, DefaultResolver)
}
func ResolveIPv6WithMain(host string) (net.IP, error) {
return ResolveIPv6WithResolver(host, MainResolver)
}
func ResolveIPv6WithResolver(host string, r Resolver) (net.IP, error) {
if DisableIPv6 {
return nil, ErrIPv6Disabled
}
@ -90,8 +109,8 @@ func ResolveIPv6(host string) (net.IP, error) {
return nil, ErrIPVersion
}
if DefaultResolver != nil {
return DefaultResolver.ResolveIPv6(host)
if r != nil {
return r.ResolveIPv6(host)
}
ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout)
@ -138,3 +157,8 @@ func ResolveIPWithResolver(host string, r Resolver) (net.IP, error) {
func ResolveIP(host string) (net.IP, error) {
return ResolveIPWithResolver(host, DefaultResolver)
}
// ResolveIPWithMainResolver with a host, use main resolver, return ip
func ResolveIPWithMainResolver(host string) (net.IP, error) {
return ResolveIPWithResolver(host, MainResolver)
}