This commit is contained in:
RPRX 2020-11-25 19:01:53 +08:00
parent 47d23e9972
commit c7f7c08ead
711 changed files with 82154 additions and 2 deletions

View file

@ -0,0 +1,40 @@
package routing
import (
"github.com/xtls/xray-core/v1/common/net"
)
// Context is a feature to store connection information for routing.
//
// xray:api:stable
type Context interface {
// GetInboundTag returns the tag of the inbound the connection was from.
GetInboundTag() string
// GetSourcesIPs returns the source IPs bound to the connection.
GetSourceIPs() []net.IP
// GetSourcePort returns the source port of the connection.
GetSourcePort() net.Port
// GetTargetIPs returns the target IP of the connection or resolved IPs of target domain.
GetTargetIPs() []net.IP
// GetTargetPort returns the target port of the connection.
GetTargetPort() net.Port
// GetTargetDomain returns the target domain of the connection, if exists.
GetTargetDomain() string
// GetNetwork returns the network type of the connection.
GetNetwork() net.Network
// GetProtocol returns the protocol from the connection content, if sniffed out.
GetProtocol() string
// GetUser returns the user email from the connection content, if exists.
GetUser() string
// GetAttributes returns extra attributes from the conneciont content.
GetAttributes() map[string]string
}

View file

@ -0,0 +1,27 @@
package routing
import (
"context"
"github.com/xtls/xray-core/v1/common/net"
"github.com/xtls/xray-core/v1/features"
"github.com/xtls/xray-core/v1/transport"
)
// Dispatcher is a feature that dispatches inbound requests to outbound handlers based on rules.
// Dispatcher is required to be registered in a Xray instance to make Xray function properly.
//
// xray:api:stable
type Dispatcher interface {
features.Feature
// Dispatch returns a Ray for transporting data for the given request.
Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error)
}
// DispatcherType returns the type of Dispatcher interface. Can be used to implement common.HasType.
//
// xray:api:stable
func DispatcherType() interface{} {
return (*Dispatcher)(nil)
}

View file

@ -0,0 +1,44 @@
package dns
//go:generate go run github.com/xtls/xray-core/v1/common/errors/errorgen
import (
"github.com/xtls/xray-core/v1/common/net"
"github.com/xtls/xray-core/v1/features/dns"
"github.com/xtls/xray-core/v1/features/routing"
)
// ResolvableContext is an implementation of routing.Context, with domain resolving capability.
type ResolvableContext struct {
routing.Context
dnsClient dns.Client
resolvedIPs []net.IP
}
// GetTargetIPs overrides original routing.Context's implementation.
func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
if ips := ctx.Context.GetTargetIPs(); len(ips) != 0 {
return ips
}
if len(ctx.resolvedIPs) > 0 {
return ctx.resolvedIPs
}
if domain := ctx.GetTargetDomain(); len(domain) != 0 {
ips, err := ctx.dnsClient.LookupIP(domain)
if err == nil {
ctx.resolvedIPs = ips
return ips
}
newError("resolve ip for ", domain).Base(err).WriteToLog()
}
return nil
}
// ContextWithDNSClient creates a new routing context with domain resolving capability.
// Resolved domain IPs can be retrieved by GetTargetIPs().
func ContextWithDNSClient(ctx routing.Context, client dns.Client) routing.Context {
return &ResolvableContext{Context: ctx, dnsClient: client}
}

View file

@ -0,0 +1,9 @@
package dns
import "github.com/xtls/xray-core/v1/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -0,0 +1,60 @@
package routing
import (
"github.com/xtls/xray-core/v1/common"
"github.com/xtls/xray-core/v1/features"
)
// Router is a feature to choose an outbound tag for the given request.
//
// xray:api:stable
type Router interface {
features.Feature
// PickRoute returns a route decision based on the given routing context.
PickRoute(ctx Context) (Route, error)
}
// Route is the routing result of Router feature.
//
// xray:api:stable
type Route interface {
// A Route is also a routing context.
Context
// GetOutboundGroupTags returns the detoured outbound group tags in sequence before a final outbound is chosen.
GetOutboundGroupTags() []string
// GetOutboundTag returns the tag of the outbound the connection was dispatched to.
GetOutboundTag() string
}
// RouterType return the type of Router interface. Can be used to implement common.HasType.
//
// xray:api:stable
func RouterType() interface{} {
return (*Router)(nil)
}
// DefaultRouter is an implementation of Router, which always returns ErrNoClue for routing decisions.
type DefaultRouter struct{}
// Type implements common.HasType.
func (DefaultRouter) Type() interface{} {
return RouterType()
}
// PickRoute implements Router.
func (DefaultRouter) PickRoute(ctx Context) (Route, error) {
return nil, common.ErrNoClue
}
// Start implements common.Runnable.
func (DefaultRouter) Start() error {
return nil
}
// Close implements common.Closable.
func (DefaultRouter) Close() error {
return nil
}

View file

@ -0,0 +1,119 @@
package session
import (
"context"
"github.com/xtls/xray-core/v1/common/net"
"github.com/xtls/xray-core/v1/common/session"
"github.com/xtls/xray-core/v1/features/routing"
)
// Context is an implementation of routing.Context, which is a wrapper of context.context with session info.
type Context struct {
Inbound *session.Inbound
Outbound *session.Outbound
Content *session.Content
}
// GetInboundTag implements routing.Context.
func (ctx *Context) GetInboundTag() string {
if ctx.Inbound == nil {
return ""
}
return ctx.Inbound.Tag
}
// GetSourceIPs implements routing.Context.
func (ctx *Context) GetSourceIPs() []net.IP {
if ctx.Inbound == nil || !ctx.Inbound.Source.IsValid() {
return nil
}
dest := ctx.Inbound.Source
if dest.Address.Family().IsDomain() {
return nil
}
return []net.IP{dest.Address.IP()}
}
// GetSourcePort implements routing.Context.
func (ctx *Context) GetSourcePort() net.Port {
if ctx.Inbound == nil || !ctx.Inbound.Source.IsValid() {
return 0
}
return ctx.Inbound.Source.Port
}
// GetTargetIPs implements routing.Context.
func (ctx *Context) GetTargetIPs() []net.IP {
if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
return nil
}
if ctx.Outbound.Target.Address.Family().IsIP() {
return []net.IP{ctx.Outbound.Target.Address.IP()}
}
return nil
}
// GetTargetPort implements routing.Context.
func (ctx *Context) GetTargetPort() net.Port {
if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
return 0
}
return ctx.Outbound.Target.Port
}
// GetTargetDomain implements routing.Context.
func (ctx *Context) GetTargetDomain() string {
if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
return ""
}
dest := ctx.Outbound.Target
if !dest.Address.Family().IsDomain() {
return ""
}
return dest.Address.Domain()
}
// GetNetwork implements routing.Context.
func (ctx *Context) GetNetwork() net.Network {
if ctx.Outbound == nil {
return net.Network_Unknown
}
return ctx.Outbound.Target.Network
}
// GetProtocol implements routing.Context.
func (ctx *Context) GetProtocol() string {
if ctx.Content == nil {
return ""
}
return ctx.Content.Protocol
}
// GetUser implements routing.Context.
func (ctx *Context) GetUser() string {
if ctx.Inbound == nil || ctx.Inbound.User == nil {
return ""
}
return ctx.Inbound.User.Email
}
// GetAttributes implements routing.Context.
func (ctx *Context) GetAttributes() map[string]string {
if ctx.Content == nil {
return nil
}
return ctx.Content.Attributes
}
// AsRoutingContext creates a context from context.context with session info.
func AsRoutingContext(ctx context.Context) routing.Context {
return &Context{
Inbound: session.InboundFromContext(ctx),
Outbound: session.OutboundFromContext(ctx),
Content: session.ContentFromContext(ctx),
}
}