mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-09-06 16:29:19 +03:00
* 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>
102 lines
3.6 KiB
Go
102 lines
3.6 KiB
Go
package command
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/xtls/xray-core/common/net"
|
|
"github.com/xtls/xray-core/features/routing"
|
|
)
|
|
|
|
// routingContext is an wrapper of protobuf RoutingContext as implementation of routing.Context and routing.Route.
|
|
type routingContext struct {
|
|
*RoutingContext
|
|
}
|
|
|
|
func (c routingContext) GetSourceIPs() []net.IP {
|
|
return mapBytesToIPs(c.RoutingContext.GetSourceIPs())
|
|
}
|
|
|
|
func (c routingContext) GetSourcePort() net.Port {
|
|
return net.Port(c.RoutingContext.GetSourcePort())
|
|
}
|
|
|
|
func (c routingContext) GetTargetIPs() []net.IP {
|
|
return mapBytesToIPs(c.RoutingContext.GetTargetIPs())
|
|
}
|
|
|
|
func (c routingContext) GetTargetPort() net.Port {
|
|
return net.Port(c.RoutingContext.GetTargetPort())
|
|
}
|
|
|
|
// GetSkipDNSResolve is a mock implementation here to match the interface,
|
|
// SkipDNSResolve is set from dns module, no use if coming from a protobuf object?
|
|
// TODO: please confirm @Vigilans
|
|
func (c routingContext) GetSkipDNSResolve() bool {
|
|
return false
|
|
}
|
|
|
|
// AsRoutingContext converts a protobuf RoutingContext into an implementation of routing.Context.
|
|
func AsRoutingContext(r *RoutingContext) routing.Context {
|
|
return routingContext{r}
|
|
}
|
|
|
|
// AsRoutingRoute converts a protobuf RoutingContext into an implementation of routing.Route.
|
|
func AsRoutingRoute(r *RoutingContext) routing.Route {
|
|
return routingContext{r}
|
|
}
|
|
|
|
var fieldMap = map[string]func(*RoutingContext, routing.Route){
|
|
"inbound": func(s *RoutingContext, r routing.Route) { s.InboundTag = r.GetInboundTag() },
|
|
"network": func(s *RoutingContext, r routing.Route) { s.Network = r.GetNetwork() },
|
|
"ip_source": func(s *RoutingContext, r routing.Route) { s.SourceIPs = mapIPsToBytes(r.GetSourceIPs()) },
|
|
"ip_target": func(s *RoutingContext, r routing.Route) { s.TargetIPs = mapIPsToBytes(r.GetTargetIPs()) },
|
|
"port_source": func(s *RoutingContext, r routing.Route) { s.SourcePort = uint32(r.GetSourcePort()) },
|
|
"port_target": func(s *RoutingContext, r routing.Route) { s.TargetPort = uint32(r.GetTargetPort()) },
|
|
"domain": func(s *RoutingContext, r routing.Route) { s.TargetDomain = r.GetTargetDomain() },
|
|
"protocol": func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
|
|
"user": func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
|
|
"attributes": func(s *RoutingContext, r routing.Route) { s.Attributes = r.GetAttributes() },
|
|
"outbound_group": func(s *RoutingContext, r routing.Route) { s.OutboundGroupTags = r.GetOutboundGroupTags() },
|
|
"outbound": func(s *RoutingContext, r routing.Route) { s.OutboundTag = r.GetOutboundTag() },
|
|
}
|
|
|
|
// AsProtobufMessage takes selectors of fields and returns a function to convert routing.Route to protobuf RoutingContext.
|
|
func AsProtobufMessage(fieldSelectors []string) func(routing.Route) *RoutingContext {
|
|
initializers := []func(*RoutingContext, routing.Route){}
|
|
for field, init := range fieldMap {
|
|
if len(fieldSelectors) == 0 { // If selectors not set, retrieve all fields
|
|
initializers = append(initializers, init)
|
|
continue
|
|
}
|
|
for _, selector := range fieldSelectors {
|
|
if strings.HasPrefix(field, selector) {
|
|
initializers = append(initializers, init)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return func(ctx routing.Route) *RoutingContext {
|
|
message := new(RoutingContext)
|
|
for _, init := range initializers {
|
|
init(message, ctx)
|
|
}
|
|
return message
|
|
}
|
|
}
|
|
|
|
func mapBytesToIPs(bytes [][]byte) []net.IP {
|
|
var ips []net.IP
|
|
for _, rawIP := range bytes {
|
|
ips = append(ips, net.IP(rawIP))
|
|
}
|
|
return ips
|
|
}
|
|
|
|
func mapIPsToBytes(ips []net.IP) [][]byte {
|
|
var bytes [][]byte
|
|
for _, ip := range ips {
|
|
bytes = append(bytes, []byte(ip))
|
|
}
|
|
return bytes
|
|
}
|