Add resolver for inbound

This commit is contained in:
世界 2022-07-07 23:36:32 +08:00
parent 538a1f5909
commit 9c256afc1a
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
22 changed files with 261 additions and 173 deletions

View file

@ -56,6 +56,7 @@ type Router struct {
dnsClient adapter.DNSClient
defaultDomainStrategy C.DomainStrategy
dnsRules []adapter.Rule
defaultTransport adapter.DNSTransport
transports []adapter.DNSTransport
@ -69,9 +70,11 @@ func NewRouter(ctx context.Context, logger log.Logger, options option.RouteOptio
dnsLogger: logger.WithPrefix("dns: "),
outboundByTag: make(map[string]adapter.Outbound),
rules: make([]adapter.Rule, 0, len(options.Rules)),
dnsRules: make([]adapter.Rule, 0, len(dnsOptions.Rules)),
needGeoIPDatabase: hasGeoRule(options.Rules, isGeoIPRule) || hasGeoDNSRule(dnsOptions.Rules, isGeoIPDNSRule),
needGeositeDatabase: hasGeoRule(options.Rules, isGeositeRule) || hasGeoDNSRule(dnsOptions.Rules, isGeositeDNSRule),
geoIPOptions: common.PtrValueOrDefault(options.GeoIP),
geositeOptions: common.PtrValueOrDefault(options.Geosite),
defaultDetour: options.Final,
dnsClient: dns.NewClient(dnsOptions.DNSClientOptions),
defaultDomainStrategy: C.DomainStrategy(dnsOptions.Strategy),
@ -88,7 +91,7 @@ func NewRouter(ctx context.Context, logger log.Logger, options option.RouteOptio
if err != nil {
return nil, E.Cause(err, "parse dns rule[", i, "]")
}
router.rules = append(router.rules, dnsRule)
router.dnsRules = append(router.dnsRules, dnsRule)
}
transports := make([]adapter.DNSTransport, len(dnsOptions.Servers))
dummyTransportMap := make(map[string]adapter.DNSTransport)
@ -259,6 +262,12 @@ func (r *Router) Start() error {
return err
}
}
for _, rule := range r.dnsRules {
err := rule.Start()
if err != nil {
return err
}
}
if r.needGeositeDatabase {
for _, rule := range r.rules {
err := rule.UpdateGeosite()
@ -266,6 +275,12 @@ func (r *Router) Start() error {
r.logger.Error("failed to initialize geosite: ", err)
}
}
for _, rule := range r.dnsRules {
err := rule.UpdateGeosite()
if err != nil {
r.logger.Error("failed to initialize geosite: ", err)
}
}
err := common.Close(r.geositeReader)
if err != nil {
return err
@ -275,6 +290,18 @@ func (r *Router) Start() error {
}
func (r *Router) Close() error {
for _, rule := range r.rules {
err := rule.Close()
if err != nil {
return err
}
}
for _, rule := range r.dnsRules {
err := rule.Close()
if err != nil {
return err
}
}
return common.Close(
common.PtrOrNil(r.geoIPReader),
)
@ -325,12 +352,20 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
conn = bufio.NewCachedConn(conn, buffer)
}
}
if metadata.Destination.IsFqdn() && metadata.DomainStrategy != C.DomainStrategyAsIS {
addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, metadata.DomainStrategy)
if err != nil {
return err
}
metadata.DestinationAddresses = addresses
r.dnsLogger.WithContext(ctx).Info("resolved [", strings.Join(common.Map(metadata.DestinationAddresses, F.ToString0[netip.Addr]), " "), "]")
}
detour := r.match(ctx, metadata, r.defaultOutboundForConnection)
if !common.Contains(detour.Network(), C.NetworkTCP) {
conn.Close()
return E.New("missing supported outbound, closing connection")
}
return detour.NewConnection(adapter.WithContext(ctx, &metadata), conn, metadata.Destination)
return detour.NewConnection(ctx, conn, metadata)
}
func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
@ -359,12 +394,20 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
}
conn = bufio.NewCachedPacketConn(conn, buffer, originDestination)
}
if metadata.Destination.IsFqdn() && metadata.DomainStrategy != C.DomainStrategyAsIS {
addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, metadata.DomainStrategy)
if err != nil {
return err
}
metadata.DestinationAddresses = addresses
r.dnsLogger.WithContext(ctx).Info("resolved [", strings.Join(common.Map(metadata.DestinationAddresses, F.ToString0[netip.Addr]), " "), "]")
}
detour := r.match(ctx, metadata, r.defaultOutboundForPacketConnection)
if !common.Contains(detour.Network(), C.NetworkUDP) {
conn.Close()
return E.New("missing supported outbound, closing packet connection")
}
return detour.NewPacketConnection(adapter.WithContext(ctx, &metadata), conn, metadata.Destination)
return detour.NewPacketConnection(ctx, conn, metadata)
}
func (r *Router) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
@ -397,10 +440,10 @@ func (r *Router) match(ctx context.Context, metadata adapter.InboundContext, def
func (r *Router) matchDNS(ctx context.Context) adapter.DNSTransport {
metadata := adapter.ContextFrom(ctx)
if metadata == nil {
r.dnsLogger.WithContext(ctx).Info("no context")
r.dnsLogger.WithContext(ctx).Warn("no context")
return r.defaultTransport
}
for i, rule := range r.rules {
for i, rule := range r.dnsRules {
if rule.Match(metadata) {
detour := rule.Outbound()
r.dnsLogger.WithContext(ctx).Info("match[", i, "] ", rule.String(), " => ", detour)