condition.go 6.4 KB

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