rule_geoip.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package route
  2. import (
  3. "strings"
  4. "github.com/sagernet/sing-box/adapter"
  5. "github.com/sagernet/sing-box/log"
  6. )
  7. var _ RuleItem = (*GeoIPItem)(nil)
  8. type GeoIPItem struct {
  9. router adapter.Router
  10. logger log.Logger
  11. isSource bool
  12. codes []string
  13. codeMap map[string]bool
  14. }
  15. func NewGeoIPItem(router adapter.Router, logger log.Logger, isSource bool, codes []string) *GeoIPItem {
  16. codeMap := make(map[string]bool)
  17. for _, code := range codes {
  18. codeMap[code] = true
  19. }
  20. return &GeoIPItem{
  21. router: router,
  22. logger: logger,
  23. codes: codes,
  24. isSource: isSource,
  25. codeMap: codeMap,
  26. }
  27. }
  28. func (r *GeoIPItem) Match(metadata *adapter.InboundContext) bool {
  29. geoReader := r.router.GeoIPReader()
  30. if geoReader == nil {
  31. return false
  32. }
  33. if r.isSource {
  34. if metadata.SourceGeoIPCode == "" {
  35. metadata.SourceGeoIPCode = geoReader.Lookup(metadata.Source.Addr)
  36. }
  37. return r.codeMap[metadata.SourceGeoIPCode]
  38. } else {
  39. if metadata.Destination.IsIP() {
  40. if metadata.GeoIPCode == "" {
  41. metadata.GeoIPCode = geoReader.Lookup(metadata.Destination.Addr)
  42. }
  43. return r.codeMap[metadata.GeoIPCode]
  44. }
  45. for _, address := range metadata.DestinationAddresses {
  46. if r.codeMap[geoReader.Lookup(address)] {
  47. return true
  48. }
  49. }
  50. return false
  51. }
  52. }
  53. func (r *GeoIPItem) String() string {
  54. var description string
  55. if r.isSource {
  56. description = "source_geoip="
  57. } else {
  58. description = "geoip="
  59. }
  60. cLen := len(r.codes)
  61. if cLen == 1 {
  62. description += r.codes[0]
  63. } else if cLen > 3 {
  64. description += "[" + strings.Join(r.codes[:3], " ") + "...]"
  65. } else {
  66. description += "[" + strings.Join(r.codes, " ") + "]"
  67. }
  68. return description
  69. }