1
0

rule_port_range.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package route
  2. import (
  3. "strconv"
  4. "strings"
  5. "github.com/sagernet/sing-box/adapter"
  6. E "github.com/sagernet/sing/common/exceptions"
  7. )
  8. var ErrBadPortRange = E.New("bad port range")
  9. var _ RuleItem = (*PortRangeItem)(nil)
  10. type PortRangeItem struct {
  11. isSource bool
  12. portRanges []string
  13. portRangeList []rangeItem
  14. }
  15. type rangeItem struct {
  16. start uint16
  17. end uint16
  18. }
  19. func NewPortRangeItem(isSource bool, rangeList []string) (*PortRangeItem, error) {
  20. portRangeList := make([]rangeItem, 0, len(rangeList))
  21. for _, portRange := range rangeList {
  22. if !strings.Contains(portRange, ":") {
  23. return nil, E.Extend(ErrBadPortRange, portRange)
  24. }
  25. subIndex := strings.Index(portRange, ":")
  26. var start, end uint64
  27. var err error
  28. if subIndex > 0 {
  29. start, err = strconv.ParseUint(portRange[:subIndex], 10, 16)
  30. if err != nil {
  31. return nil, E.Cause(err, E.Extend(ErrBadPortRange, portRange))
  32. }
  33. }
  34. if subIndex == len(portRange)-1 {
  35. end = 0xFF
  36. } else {
  37. end, err = strconv.ParseUint(portRange[subIndex+1:], 10, 16)
  38. if err != nil {
  39. return nil, E.Cause(err, E.Extend(ErrBadPortRange, portRange))
  40. }
  41. }
  42. portRangeList = append(portRangeList, rangeItem{uint16(start), uint16(end)})
  43. }
  44. return &PortRangeItem{
  45. isSource: isSource,
  46. portRanges: rangeList,
  47. portRangeList: portRangeList,
  48. }, nil
  49. }
  50. func (r *PortRangeItem) Match(metadata *adapter.InboundContext) bool {
  51. var port uint16
  52. if r.isSource {
  53. port = metadata.Source.Port
  54. } else {
  55. port = metadata.Destination.Port
  56. }
  57. for _, portRange := range r.portRangeList {
  58. if port >= portRange.start && port <= portRange.end {
  59. return true
  60. }
  61. }
  62. return false
  63. }
  64. func (r *PortRangeItem) String() string {
  65. var description string
  66. if r.isSource {
  67. description = "source_port_range="
  68. } else {
  69. description = "port_range="
  70. }
  71. pLen := len(r.portRanges)
  72. if pLen == 1 {
  73. description += r.portRanges[0]
  74. } else {
  75. description += "[" + strings.Join(r.portRanges, " ") + "]"
  76. }
  77. return description
  78. }