condition.go 6.8 KB

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