mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-04-30 17:38:41 +00:00
Merge dns (#722)
* DNS: add clientip for specific nameserver * Refactoring: DNS App * DNS: add DNS over QUIC support * Feat: add disableCache option for DNS * Feat: add queryStrategy option for DNS * Feat: add disableFallback & skipFallback option for DNS * Feat: DNS hosts support multiple addresses * Feat: DNS transport over TCP * DNS: fix typo & refine code * DNS: refine code * Add disableFallbackIfMatch dns option * Feat: routing and freedom outbound ignore Fake DNS Turn off fake DNS for request sent from Routing and Freedom outbound. Fake DNS now only apply to DNS outbound. This is important for Android, where VPN service take over all system DNS traffic and pass it to core. "UseIp" option can be used in Freedom outbound to avoid getting fake IP and fail connection. * Fix test * Fix dns return * Fix local dns return empty * Apply timeout to dns outbound * Update app/dns/config.go Co-authored-by: Loyalsoldier <10487845+loyalsoldier@users.noreply.github.com> Co-authored-by: Ye Zhihao <vigilans@foxmail.com> Co-authored-by: maskedeken <52683904+maskedeken@users.noreply.github.com> Co-authored-by: V2Fly Team <51714622+vcptr@users.noreply.github.com> Co-authored-by: CalmLong <37164399+calmlong@users.noreply.github.com> Co-authored-by: Shelikhoo <xiaokangwang@outlook.com> Co-authored-by: 秋のかえで <autmaple@protonmail.com> Co-authored-by: 朱聖黎 <digglife@gmail.com> Co-authored-by: rurirei <72071920+rurirei@users.noreply.github.com> Co-authored-by: yuhan6665 <1588741+yuhan6665@users.noreply.github.com> Co-authored-by: Arthur Morgan <4637240+badO1a5A90@users.noreply.github.com>
This commit is contained in:
parent
5e606169f1
commit
cd4631ce99
33 changed files with 2252 additions and 880 deletions
|
@ -14,25 +14,6 @@ type StaticHosts struct {
|
|||
matchers *strmatcher.MatcherGroup
|
||||
}
|
||||
|
||||
var typeMap = map[DomainMatchingType]strmatcher.Type{
|
||||
DomainMatchingType_Full: strmatcher.Full,
|
||||
DomainMatchingType_Subdomain: strmatcher.Domain,
|
||||
DomainMatchingType_Keyword: strmatcher.Substr,
|
||||
DomainMatchingType_Regex: strmatcher.Regex,
|
||||
}
|
||||
|
||||
func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Matcher, error) {
|
||||
strMType, f := typeMap[t]
|
||||
if !f {
|
||||
return nil, newError("unknown mapping type", t).AtWarning()
|
||||
}
|
||||
matcher, err := strMType.New(domain)
|
||||
if err != nil {
|
||||
return nil, newError("failed to create str matcher").Base(err)
|
||||
}
|
||||
return matcher, nil
|
||||
}
|
||||
|
||||
// NewStaticHosts creates a new StaticHosts instance.
|
||||
func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDomain) (*StaticHosts, error) {
|
||||
g := new(strmatcher.MatcherGroup)
|
||||
|
@ -66,6 +47,8 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
|||
id := g.Add(matcher)
|
||||
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
||||
switch {
|
||||
case len(mapping.ProxiedDomain) > 0:
|
||||
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
||||
case len(mapping.Ip) > 0:
|
||||
for _, ip := range mapping.Ip {
|
||||
addr := net.IPAddress(ip)
|
||||
|
@ -74,19 +57,10 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
|||
}
|
||||
ips = append(ips, addr)
|
||||
}
|
||||
|
||||
case len(mapping.ProxiedDomain) > 0:
|
||||
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
||||
|
||||
default:
|
||||
return nil, newError("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
|
||||
}
|
||||
|
||||
// Special handling for localhost IPv6. This is a dirty workaround as JSON config supports only single IP mapping.
|
||||
if len(ips) == 1 && ips[0] == net.LocalHostIP {
|
||||
ips = append(ips, net.LocalHostIPv6)
|
||||
}
|
||||
|
||||
sh.ips[id] = ips
|
||||
}
|
||||
|
||||
|
@ -100,24 +74,36 @@ func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
|||
filtered = append(filtered, ip)
|
||||
}
|
||||
}
|
||||
if len(filtered) == 0 {
|
||||
return nil
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
// LookupIP returns IP address for the given domain, if exists in this StaticHosts.
|
||||
func (h *StaticHosts) LookupIP(domain string, option dns.IPOption) []net.Address {
|
||||
indices := h.matchers.Match(domain)
|
||||
if len(indices) == 0 {
|
||||
return nil
|
||||
}
|
||||
ips := []net.Address{}
|
||||
for _, id := range indices {
|
||||
func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
||||
var ips []net.Address
|
||||
for _, id := range h.matchers.Match(domain) {
|
||||
ips = append(ips, h.ips[id]...)
|
||||
}
|
||||
if len(ips) == 1 && ips[0].Family().IsDomain() {
|
||||
return ips
|
||||
}
|
||||
return filterIP(ips, option)
|
||||
return ips
|
||||
}
|
||||
|
||||
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address {
|
||||
switch addrs := h.lookupInternal(domain); {
|
||||
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
||||
return nil
|
||||
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
|
||||
newError("found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it").AtDebug().WriteToLog()
|
||||
if maxDepth > 0 {
|
||||
unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1)
|
||||
if unwrapped != nil {
|
||||
return unwrapped
|
||||
}
|
||||
}
|
||||
return addrs
|
||||
default: // IP record found, return a non-nil IP array
|
||||
return filterIP(addrs, option)
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
||||
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) []net.Address {
|
||||
return h.lookup(domain, option, 5)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue