router.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package rules
  2. import (
  3. "errors"
  4. "time"
  5. "github.com/v2ray/v2ray-core/app"
  6. "github.com/v2ray/v2ray-core/app/dns"
  7. "github.com/v2ray/v2ray-core/app/router"
  8. "github.com/v2ray/v2ray-core/common/collect"
  9. "github.com/v2ray/v2ray-core/common/log"
  10. v2net "github.com/v2ray/v2ray-core/common/net"
  11. )
  12. var (
  13. ErrorInvalidRule = errors.New("Invalid Rule")
  14. ErrorNoRuleApplicable = errors.New("No rule applicable")
  15. )
  16. type cacheEntry struct {
  17. tag string
  18. err error
  19. validUntil time.Time
  20. }
  21. func newCacheEntry(tag string, err error) *cacheEntry {
  22. this := &cacheEntry{
  23. tag: tag,
  24. err: err,
  25. }
  26. this.Extend()
  27. return this
  28. }
  29. func (this *cacheEntry) IsValid() bool {
  30. return this.validUntil.Before(time.Now())
  31. }
  32. func (this *cacheEntry) Extend() {
  33. this.validUntil = time.Now().Add(time.Hour)
  34. }
  35. func (this *cacheEntry) Release() {
  36. }
  37. type Router struct {
  38. config *RouterRuleConfig
  39. cache *collect.ValidityMap
  40. dnsServer dns.Server
  41. }
  42. func NewRouter(config *RouterRuleConfig, space app.Space) *Router {
  43. r := &Router{
  44. config: config,
  45. cache: collect.NewValidityMap(3600),
  46. }
  47. space.InitializeApplication(func() error {
  48. if !space.HasApp(dns.APP_ID) {
  49. log.Error("DNS: Router is not found in the space.")
  50. return app.ErrorMissingApplication
  51. }
  52. r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
  53. return nil
  54. })
  55. return r
  56. }
  57. func (this *Router) Release() {
  58. }
  59. // @Private
  60. func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
  61. ips := this.dnsServer.Get(dest.Address().Domain())
  62. if len(ips) == 0 {
  63. return nil
  64. }
  65. dests := make([]v2net.Destination, len(ips))
  66. for idx, ip := range ips {
  67. if dest.IsTCP() {
  68. dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port())
  69. } else {
  70. dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port())
  71. }
  72. }
  73. return dests
  74. }
  75. func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, error) {
  76. for _, rule := range this.config.Rules {
  77. if rule.Apply(dest) {
  78. return rule.Tag, nil
  79. }
  80. }
  81. if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address().IsDomain() {
  82. log.Info("Router: Looking up IP for ", dest)
  83. ipDests := this.ResolveIP(dest)
  84. if ipDests != nil {
  85. for _, ipDest := range ipDests {
  86. log.Info("Router: Trying IP ", ipDest)
  87. for _, rule := range this.config.Rules {
  88. if rule.Apply(ipDest) {
  89. return rule.Tag, nil
  90. }
  91. }
  92. }
  93. }
  94. }
  95. return "", ErrorNoRuleApplicable
  96. }
  97. func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
  98. destStr := dest.String()
  99. rawEntry := this.cache.Get(destStr)
  100. if rawEntry == nil {
  101. tag, err := this.takeDetourWithoutCache(dest)
  102. this.cache.Set(destStr, newCacheEntry(tag, err))
  103. return tag, err
  104. }
  105. entry := rawEntry.(*cacheEntry)
  106. return entry.tag, entry.err
  107. }
  108. type RouterFactory struct {
  109. }
  110. func (this *RouterFactory) Create(rawConfig interface{}, space app.Space) (router.Router, error) {
  111. return NewRouter(rawConfig.(*RouterRuleConfig), space), nil
  112. }
  113. func init() {
  114. router.RegisterRouter("rules", &RouterFactory{})
  115. }