|
@@ -10,10 +10,11 @@ import (
|
|
|
|
|
|
|
|
"v2ray.com/core/common/net"
|
|
"v2ray.com/core/common/net"
|
|
|
"v2ray.com/core/common/strmatcher"
|
|
"v2ray.com/core/common/strmatcher"
|
|
|
|
|
+ "v2ray.com/core/features/routing"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
type Condition interface {
|
|
type Condition interface {
|
|
|
- Apply(ctx *Context) bool
|
|
|
|
|
|
|
+ Apply(ctx routing.Context) bool
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type ConditionChan []Condition
|
|
type ConditionChan []Condition
|
|
@@ -28,7 +29,8 @@ func (v *ConditionChan) Add(cond Condition) *ConditionChan {
|
|
|
return v
|
|
return v
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (v *ConditionChan) Apply(ctx *Context) bool {
|
|
|
|
|
|
|
+// Apply applies all conditions registered in this chan.
|
|
|
|
|
+func (v *ConditionChan) Apply(ctx routing.Context) bool {
|
|
|
for _, cond := range *v {
|
|
for _, cond := range *v {
|
|
|
if !cond.Apply(ctx) {
|
|
if !cond.Apply(ctx) {
|
|
|
return false
|
|
return false
|
|
@@ -85,36 +87,18 @@ func (m *DomainMatcher) ApplyDomain(domain string) bool {
|
|
|
return len(m.matchers.Match(domain)) > 0
|
|
return len(m.matchers.Match(domain)) > 0
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m *DomainMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
|
|
|
|
+ domain := ctx.GetTargetDomain()
|
|
|
|
|
+ if len(domain) == 0 {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
- dest := ctx.Outbound.Target
|
|
|
|
|
- if !dest.Address.Family().IsDomain() {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- return m.ApplyDomain(dest.Address.Domain())
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func getIPsFromSource(ctx *Context) []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()}
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func getIPsFromTarget(ctx *Context) []net.IP {
|
|
|
|
|
- return ctx.GetTargetIPs()
|
|
|
|
|
|
|
+ return m.ApplyDomain(domain)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type MultiGeoIPMatcher struct {
|
|
type MultiGeoIPMatcher struct {
|
|
|
matchers []*GeoIPMatcher
|
|
matchers []*GeoIPMatcher
|
|
|
- ipFunc func(*Context) []net.IP
|
|
|
|
|
|
|
+ onSource bool
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
|
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
|
@@ -129,20 +113,20 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, e
|
|
|
|
|
|
|
|
matcher := &MultiGeoIPMatcher{
|
|
matcher := &MultiGeoIPMatcher{
|
|
|
matchers: matchers,
|
|
matchers: matchers,
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if onSource {
|
|
|
|
|
- matcher.ipFunc = getIPsFromSource
|
|
|
|
|
- } else {
|
|
|
|
|
- matcher.ipFunc = getIPsFromTarget
|
|
|
|
|
|
|
+ onSource: onSource,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return matcher, nil
|
|
return matcher, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m *MultiGeoIPMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- ips := m.ipFunc(ctx)
|
|
|
|
|
-
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
|
|
|
|
+ var ips []net.IP
|
|
|
|
|
+ if m.onSource {
|
|
|
|
|
+ ips = ctx.GetSourceIPs()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ips = ctx.GetTargetIPs()
|
|
|
|
|
+ }
|
|
|
for _, ip := range ips {
|
|
for _, ip := range ips {
|
|
|
for _, matcher := range m.matchers {
|
|
for _, matcher := range m.matchers {
|
|
|
if matcher.Match(ip) {
|
|
if matcher.Match(ip) {
|
|
@@ -166,20 +150,13 @@ func NewPortMatcher(list *net.PortList, onSource bool) *PortMatcher {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (v *PortMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- var port net.Port
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (v *PortMatcher) Apply(ctx routing.Context) bool {
|
|
|
if v.onSource {
|
|
if v.onSource {
|
|
|
- if ctx.Inbound == nil || !ctx.Inbound.Source.IsValid() {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- port = ctx.Inbound.Source.Port
|
|
|
|
|
|
|
+ return v.port.Contains(ctx.GetSourcePort())
|
|
|
} else {
|
|
} else {
|
|
|
- if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- port = ctx.Outbound.Target.Port
|
|
|
|
|
|
|
+ return v.port.Contains(ctx.GetTargetPort())
|
|
|
}
|
|
}
|
|
|
- return v.port.Contains(port)
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type NetworkMatcher struct {
|
|
type NetworkMatcher struct {
|
|
@@ -194,11 +171,9 @@ func NewNetworkMatcher(network []net.Network) NetworkMatcher {
|
|
|
return matcher
|
|
return matcher
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (v NetworkMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- return v.list[int(ctx.Outbound.Target.Network)]
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (v NetworkMatcher) Apply(ctx routing.Context) bool {
|
|
|
|
|
+ return v.list[int(ctx.GetNetwork())]
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
type UserMatcher struct {
|
|
type UserMatcher struct {
|
|
@@ -217,17 +192,14 @@ func NewUserMatcher(users []string) *UserMatcher {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (v *UserMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- if ctx.Inbound == nil {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- user := ctx.Inbound.User
|
|
|
|
|
- if user == nil {
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (v *UserMatcher) Apply(ctx routing.Context) bool {
|
|
|
|
|
+ user := ctx.GetUser()
|
|
|
|
|
+ if len(user) == 0 {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
for _, u := range v.user {
|
|
for _, u := range v.user {
|
|
|
- if u == user.Email {
|
|
|
|
|
|
|
+ if u == user {
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -250,11 +222,12 @@ func NewInboundTagMatcher(tags []string) *InboundTagMatcher {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (v *InboundTagMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- if ctx.Inbound == nil || len(ctx.Inbound.Tag) == 0 {
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (v *InboundTagMatcher) Apply(ctx routing.Context) bool {
|
|
|
|
|
+ tag := ctx.GetInboundTag()
|
|
|
|
|
+ if len(tag) == 0 {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
- tag := ctx.Inbound.Tag
|
|
|
|
|
for _, t := range v.tags {
|
|
for _, t := range v.tags {
|
|
|
if t == tag {
|
|
if t == tag {
|
|
|
return true
|
|
return true
|
|
@@ -281,18 +254,17 @@ func NewProtocolMatcher(protocols []string) *ProtocolMatcher {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m *ProtocolMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- if ctx.Content == nil {
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (m *ProtocolMatcher) Apply(ctx routing.Context) bool {
|
|
|
|
|
+ protocol := ctx.GetProtocol()
|
|
|
|
|
+ if len(protocol) == 0 {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- protocol := ctx.Content.Protocol
|
|
|
|
|
for _, p := range m.protocols {
|
|
for _, p := range m.protocols {
|
|
|
if strings.HasPrefix(protocol, p) {
|
|
if strings.HasPrefix(protocol, p) {
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -343,9 +315,11 @@ func (m *AttributeMatcher) Match(attrs map[string]interface{}) bool {
|
|
|
return satisfied != nil && bool(satisfied.Truth())
|
|
return satisfied != nil && bool(satisfied.Truth())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m *AttributeMatcher) Apply(ctx *Context) bool {
|
|
|
|
|
- if ctx.Content == nil {
|
|
|
|
|
|
|
+// Apply implements Condition.
|
|
|
|
|
+func (m *AttributeMatcher) Apply(ctx routing.Context) bool {
|
|
|
|
|
+ attributes := ctx.GetAttributes()
|
|
|
|
|
+ if attributes == nil {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
- return m.Match(ctx.Content.Attributes)
|
|
|
|
|
|
|
+ return m.Match(attributes)
|
|
|
}
|
|
}
|