router.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. type Router struct {
  36. config *RouterRuleConfig
  37. cache *collect.ValidityMap
  38. dnsServer dns.Server
  39. }
  40. func NewRouter(config *RouterRuleConfig, space app.Space) *Router {
  41. r := &Router{
  42. config: config,
  43. cache: collect.NewValidityMap(3600),
  44. }
  45. space.InitializeApplication(func() error {
  46. if !space.HasApp(dns.APP_ID) {
  47. log.Error("DNS: Router is not found in the space.")
  48. return app.ErrorMissingApplication
  49. }
  50. r.dnsServer = space.GetApp(dns.APP_ID).(dns.Server)
  51. return nil
  52. })
  53. return r
  54. }
  55. func (this *Router) Release() {
  56. }
  57. // @Private
  58. func (this *Router) ResolveIP(dest v2net.Destination) []v2net.Destination {
  59. ips := this.dnsServer.Get(dest.Address().Domain())
  60. if len(ips) == 0 {
  61. return nil
  62. }
  63. dests := make([]v2net.Destination, len(ips))
  64. for idx, ip := range ips {
  65. if dest.IsTCP() {
  66. dests[idx] = v2net.TCPDestination(v2net.IPAddress(ip), dest.Port())
  67. } else {
  68. dests[idx] = v2net.UDPDestination(v2net.IPAddress(ip), dest.Port())
  69. }
  70. }
  71. return dests
  72. }
  73. func (this *Router) takeDetourWithoutCache(dest v2net.Destination) (string, error) {
  74. for _, rule := range this.config.Rules {
  75. if rule.Apply(dest) {
  76. return rule.Tag, nil
  77. }
  78. }
  79. if this.config.DomainStrategy == UseIPIfNonMatch && dest.Address().IsDomain() {
  80. log.Info("Router: Looking up IP for ", dest)
  81. ipDests := this.ResolveIP(dest)
  82. if ipDests != nil {
  83. for _, ipDest := range ipDests {
  84. log.Info("Router: Trying IP ", ipDest)
  85. for _, rule := range this.config.Rules {
  86. if rule.Apply(ipDest) {
  87. return rule.Tag, nil
  88. }
  89. }
  90. }
  91. }
  92. }
  93. return "", ErrorNoRuleApplicable
  94. }
  95. func (this *Router) TakeDetour(dest v2net.Destination) (string, error) {
  96. rawEntry := this.cache.Get(dest)
  97. if rawEntry == nil {
  98. tag, err := this.takeDetourWithoutCache(dest)
  99. this.cache.Set(dest, newCacheEntry(tag, err))
  100. return tag, err
  101. }
  102. entry := rawEntry.(*cacheEntry)
  103. return entry.tag, entry.err
  104. }
  105. type RouterFactory struct {
  106. }
  107. func (this *RouterFactory) Create(rawConfig interface{}, space app.Space) (router.Router, error) {
  108. return NewRouter(rawConfig.(*RouterRuleConfig), space), nil
  109. }
  110. func init() {
  111. router.RegisterRouter("rules", &RouterFactory{})
  112. }