diff --git a/constant/dns.go b/constant/dns.go index 4d94ad6d..be8b4a17 100644 --- a/constant/dns.go +++ b/constant/dns.go @@ -16,6 +16,7 @@ const ( DNSNormal DNSMode = iota DNSFakeIP DNSMapping + DNSHosts ) type DNSMode int @@ -64,6 +65,8 @@ func (e DNSMode) String() string { return "fake-ip" case DNSMapping: return "redir-host" + case DNSHosts: + return "hosts" default: return "unknown" } diff --git a/constant/metadata.go b/constant/metadata.go index b58847ff..f248cd21 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -145,7 +145,7 @@ func (m *Metadata) Resolved() bool { // Pure is used to solve unexpected behavior // when dialing proxy connection in DNSMapping mode. func (m *Metadata) Pure() *Metadata { - if m.DNSMode == DNSMapping && m.DstIP.IsValid() { + if (m.DNSMode == DNSMapping || m.DNSMode == DNSHosts) && m.DstIP.IsValid() { copyM := *m copyM.Host = "" if copyM.DstIP.Is4() { diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 2aa072ec..5473b2c6 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -331,9 +331,18 @@ func handleTCPConn(connCtx C.ConnContext) { return } + dialMetadata := metadata + if len(metadata.Host) > 0 { + if node := resolver.DefaultHosts.Search(metadata.Host); node != nil { + dialMetadata.DstIP = node.Data + dialMetadata.DNSMode = C.DNSHosts + dialMetadata = dialMetadata.Pure() + } + } + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTCPTimeout) defer cancel() - remoteConn, err := proxy.DialContext(ctx, metadata) + remoteConn, err := proxy.DialContext(ctx, dialMetadata) if err != nil { if rule == nil { log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error())