condition.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. package router
  2. import (
  3. "regexp"
  4. "strings"
  5. "github.com/xtls/xray-core/common/errors"
  6. "github.com/xtls/xray-core/common/net"
  7. "github.com/xtls/xray-core/common/strmatcher"
  8. "github.com/xtls/xray-core/features/routing"
  9. )
  10. type Condition interface {
  11. Apply(ctx routing.Context) bool
  12. }
  13. type ConditionChan []Condition
  14. func NewConditionChan() *ConditionChan {
  15. var condChan ConditionChan = make([]Condition, 0, 8)
  16. return &condChan
  17. }
  18. func (v *ConditionChan) Add(cond Condition) *ConditionChan {
  19. *v = append(*v, cond)
  20. return v
  21. }
  22. // Apply applies all conditions registered in this chan.
  23. func (v *ConditionChan) Apply(ctx routing.Context) bool {
  24. for _, cond := range *v {
  25. if !cond.Apply(ctx) {
  26. return false
  27. }
  28. }
  29. return true
  30. }
  31. func (v *ConditionChan) Len() int {
  32. return len(*v)
  33. }
  34. var matcherTypeMap = map[Domain_Type]strmatcher.Type{
  35. Domain_Plain: strmatcher.Substr,
  36. Domain_Regex: strmatcher.Regex,
  37. Domain_Domain: strmatcher.Domain,
  38. Domain_Full: strmatcher.Full,
  39. }
  40. func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) {
  41. matcherType, f := matcherTypeMap[domain.Type]
  42. if !f {
  43. return nil, errors.New("unsupported domain type", domain.Type)
  44. }
  45. matcher, err := matcherType.New(domain.Value)
  46. if err != nil {
  47. return nil, errors.New("failed to create domain matcher").Base(err)
  48. }
  49. return matcher, nil
  50. }
  51. type DomainMatcher struct {
  52. matchers strmatcher.IndexMatcher
  53. }
  54. func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
  55. g := strmatcher.NewMphMatcherGroup()
  56. for _, d := range domains {
  57. matcherType, f := matcherTypeMap[d.Type]
  58. if !f {
  59. return nil, errors.New("unsupported domain type", d.Type)
  60. }
  61. _, err := g.AddPattern(d.Value, matcherType)
  62. if err != nil {
  63. return nil, err
  64. }
  65. }
  66. g.Build()
  67. return &DomainMatcher{
  68. matchers: g,
  69. }, nil
  70. }
  71. func (m *DomainMatcher) ApplyDomain(domain string) bool {
  72. return len(m.matchers.Match(strings.ToLower(domain))) > 0
  73. }
  74. // Apply implements Condition.
  75. func (m *DomainMatcher) Apply(ctx routing.Context) bool {
  76. domain := ctx.GetTargetDomain()
  77. if len(domain) == 0 {
  78. return false
  79. }
  80. return m.ApplyDomain(domain)
  81. }
  82. type MultiGeoIPMatcher struct {
  83. matchers []*GeoIPMatcher
  84. asType string // local, source, target
  85. }
  86. func NewMultiGeoIPMatcher(geoips []*GeoIP, asType string) (*MultiGeoIPMatcher, error) {
  87. var matchers []*GeoIPMatcher
  88. for _, geoip := range geoips {
  89. matcher, err := GlobalGeoIPContainer.Add(geoip)
  90. if err != nil {
  91. return nil, err
  92. }
  93. matchers = append(matchers, matcher)
  94. }
  95. matcher := &MultiGeoIPMatcher{
  96. matchers: matchers,
  97. asType: asType,
  98. }
  99. return matcher, nil
  100. }
  101. // Apply implements Condition.
  102. func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
  103. var ips []net.IP
  104. switch m.asType {
  105. case "local":
  106. ips = ctx.GetLocalIPs()
  107. case "source":
  108. ips = ctx.GetSourceIPs()
  109. case "target":
  110. ips = ctx.GetTargetIPs()
  111. default:
  112. panic("unreachable, asType should be local or source or target")
  113. }
  114. for _, ip := range ips {
  115. for _, matcher := range m.matchers {
  116. if matcher.Match(ip) {
  117. return true
  118. }
  119. }
  120. }
  121. return false
  122. }
  123. type PortMatcher struct {
  124. port net.MemoryPortList
  125. asType string // local, source, target
  126. }
  127. // NewPortMatcher create a new port matcher that can match source or local or destination port
  128. func NewPortMatcher(list *net.PortList, asType string) *PortMatcher {
  129. return &PortMatcher{
  130. port: net.PortListFromProto(list),
  131. asType: asType,
  132. }
  133. }
  134. // Apply implements Condition.
  135. func (v *PortMatcher) Apply(ctx routing.Context) bool {
  136. switch v.asType {
  137. case "local":
  138. return v.port.Contains(ctx.GetLocalPort())
  139. case "source":
  140. return v.port.Contains(ctx.GetSourcePort())
  141. case "target":
  142. return v.port.Contains(ctx.GetTargetPort())
  143. case "vlessRoute":
  144. return v.port.Contains(ctx.GetVlessRoute())
  145. default:
  146. panic("unreachable, asType should be local or source or target")
  147. }
  148. }
  149. type NetworkMatcher struct {
  150. list [8]bool
  151. }
  152. func NewNetworkMatcher(network []net.Network) NetworkMatcher {
  153. var matcher NetworkMatcher
  154. for _, n := range network {
  155. matcher.list[int(n)] = true
  156. }
  157. return matcher
  158. }
  159. // Apply implements Condition.
  160. func (v NetworkMatcher) Apply(ctx routing.Context) bool {
  161. return v.list[int(ctx.GetNetwork())]
  162. }
  163. type UserMatcher struct {
  164. user []string
  165. pattern []*regexp.Regexp
  166. }
  167. func NewUserMatcher(users []string) *UserMatcher {
  168. usersCopy := make([]string, 0, len(users))
  169. patternsCopy := make([]*regexp.Regexp, 0, len(users))
  170. for _, user := range users {
  171. if len(user) > 0 {
  172. if len(user) > 7 && strings.HasPrefix(user, "regexp:") {
  173. if re, err := regexp.Compile(user[7:]); err == nil {
  174. patternsCopy = append(patternsCopy, re)
  175. }
  176. // Items of users slice with an invalid regexp syntax are ignored.
  177. continue
  178. }
  179. usersCopy = append(usersCopy, user)
  180. }
  181. }
  182. return &UserMatcher{
  183. user: usersCopy,
  184. pattern: patternsCopy,
  185. }
  186. }
  187. // Apply implements Condition.
  188. func (v *UserMatcher) Apply(ctx routing.Context) bool {
  189. user := ctx.GetUser()
  190. if len(user) == 0 {
  191. return false
  192. }
  193. for _, u := range v.user {
  194. if u == user {
  195. return true
  196. }
  197. }
  198. for _, re := range v.pattern {
  199. if re.MatchString(user) {
  200. return true
  201. }
  202. }
  203. return false
  204. }
  205. type InboundTagMatcher struct {
  206. tags []string
  207. }
  208. func NewInboundTagMatcher(tags []string) *InboundTagMatcher {
  209. tagsCopy := make([]string, 0, len(tags))
  210. for _, tag := range tags {
  211. if len(tag) > 0 {
  212. tagsCopy = append(tagsCopy, tag)
  213. }
  214. }
  215. return &InboundTagMatcher{
  216. tags: tagsCopy,
  217. }
  218. }
  219. // Apply implements Condition.
  220. func (v *InboundTagMatcher) Apply(ctx routing.Context) bool {
  221. tag := ctx.GetInboundTag()
  222. if len(tag) == 0 {
  223. return false
  224. }
  225. for _, t := range v.tags {
  226. if t == tag {
  227. return true
  228. }
  229. }
  230. return false
  231. }
  232. type ProtocolMatcher struct {
  233. protocols []string
  234. }
  235. func NewProtocolMatcher(protocols []string) *ProtocolMatcher {
  236. pCopy := make([]string, 0, len(protocols))
  237. for _, p := range protocols {
  238. if len(p) > 0 {
  239. pCopy = append(pCopy, p)
  240. }
  241. }
  242. return &ProtocolMatcher{
  243. protocols: pCopy,
  244. }
  245. }
  246. // Apply implements Condition.
  247. func (m *ProtocolMatcher) Apply(ctx routing.Context) bool {
  248. protocol := ctx.GetProtocol()
  249. if len(protocol) == 0 {
  250. return false
  251. }
  252. for _, p := range m.protocols {
  253. if strings.HasPrefix(protocol, p) {
  254. return true
  255. }
  256. }
  257. return false
  258. }
  259. type AttributeMatcher struct {
  260. configuredKeys map[string]*regexp.Regexp
  261. }
  262. // Match implements attributes matching.
  263. func (m *AttributeMatcher) Match(attrs map[string]string) bool {
  264. // header keys are case insensitive most likely. So we do a convert
  265. httpHeaders := make(map[string]string)
  266. for key, value := range attrs {
  267. httpHeaders[strings.ToLower(key)] = value
  268. }
  269. for key, regex := range m.configuredKeys {
  270. if a, ok := httpHeaders[key]; !ok || !regex.MatchString(a) {
  271. return false
  272. }
  273. }
  274. return true
  275. }
  276. // Apply implements Condition.
  277. func (m *AttributeMatcher) Apply(ctx routing.Context) bool {
  278. attributes := ctx.GetAttributes()
  279. if attributes == nil {
  280. return false
  281. }
  282. return m.Match(attributes)
  283. }