Feature: add custom DNS support (#56)
This commit is contained in:
@ -10,9 +10,9 @@ type Mode int
|
||||
var (
|
||||
// ModeMapping is a mapping for Mode enum
|
||||
ModeMapping = map[string]Mode{
|
||||
"Global": Global,
|
||||
"Rule": Rule,
|
||||
"Direct": Direct,
|
||||
Global.String(): Global,
|
||||
Rule.String(): Rule,
|
||||
Direct.String(): Direct,
|
||||
}
|
||||
)
|
||||
|
||||
@ -34,6 +34,18 @@ func (m *Mode) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalYAML unserialize Mode with yaml
|
||||
func (m *Mode) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var tp string
|
||||
unmarshal(&tp)
|
||||
mode, exist := ModeMapping[tp]
|
||||
if !exist {
|
||||
return errors.New("invalid mode")
|
||||
}
|
||||
*m = mode
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON serialize Mode
|
||||
func (m Mode) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(m.String())
|
||||
|
@ -1,11 +1,13 @@
|
||||
package tunnel
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
InboundAdapter "github.com/Dreamacro/clash/adapters/inbound"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/dns"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
|
||||
"gopkg.in/eapache/channels.v1"
|
||||
@ -23,6 +25,7 @@ type Tunnel struct {
|
||||
proxies map[string]C.Proxy
|
||||
configLock *sync.RWMutex
|
||||
traffic *C.Traffic
|
||||
resolver *dns.Resolver
|
||||
|
||||
// Outbound Rule
|
||||
mode Mode
|
||||
@ -72,6 +75,11 @@ func (t *Tunnel) SetMode(mode Mode) {
|
||||
t.mode = mode
|
||||
}
|
||||
|
||||
// SetResolver change the resolver of tunnel
|
||||
func (t *Tunnel) SetResolver(resolver *dns.Resolver) {
|
||||
t.resolver = resolver
|
||||
}
|
||||
|
||||
func (t *Tunnel) process() {
|
||||
queue := t.queue.Out()
|
||||
for {
|
||||
@ -81,10 +89,41 @@ func (t *Tunnel) process() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tunnel) resolveIP(host string) (net.IP, error) {
|
||||
if t.resolver == nil {
|
||||
ipAddr, err := net.ResolveIPAddr("ip", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ipAddr.IP, nil
|
||||
}
|
||||
|
||||
return t.resolver.ResolveIP(host)
|
||||
}
|
||||
|
||||
func (t *Tunnel) handleConn(localConn C.ServerAdapter) {
|
||||
defer localConn.Close()
|
||||
metadata := localConn.Metadata()
|
||||
|
||||
if metadata.Source == C.REDIR && t.resolver != nil {
|
||||
host, exist := t.resolver.IPToHost(*metadata.IP)
|
||||
if exist {
|
||||
metadata.Host = host
|
||||
metadata.AddrType = C.AtypDomainName
|
||||
}
|
||||
} else if metadata.IP == nil && metadata.AddrType == C.AtypDomainName {
|
||||
ip, err := t.resolveIP(metadata.Host)
|
||||
if err != nil {
|
||||
log.Debugln("[DNS] resolve %s error: %s", metadata.Host, err.Error())
|
||||
} else {
|
||||
log.Debugln("[DNS] %s --> %s", metadata.Host, ip.String())
|
||||
metadata.IP = &ip
|
||||
}
|
||||
} else {
|
||||
log.Debugln("[DNS] unknown%#v", metadata)
|
||||
}
|
||||
|
||||
var proxy C.Proxy
|
||||
switch t.mode {
|
||||
case Direct:
|
||||
|
Reference in New Issue
Block a user