rule_network_interface_address.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package rule
  2. import (
  3. "net/netip"
  4. "strings"
  5. "github.com/sagernet/sing-box/adapter"
  6. C "github.com/sagernet/sing-box/constant"
  7. "github.com/sagernet/sing-box/option"
  8. "github.com/sagernet/sing/common"
  9. "github.com/sagernet/sing/common/json/badjson"
  10. "github.com/sagernet/sing/common/json/badoption"
  11. )
  12. var _ RuleItem = (*NetworkInterfaceAddressItem)(nil)
  13. type NetworkInterfaceAddressItem struct {
  14. networkManager adapter.NetworkManager
  15. interfaceAddresses map[C.InterfaceType][]netip.Prefix
  16. description string
  17. }
  18. func NewNetworkInterfaceAddressItem(networkManager adapter.NetworkManager, interfaceAddresses *badjson.TypedMap[option.InterfaceType, badoption.Listable[*badoption.Prefixable]]) *NetworkInterfaceAddressItem {
  19. item := &NetworkInterfaceAddressItem{
  20. networkManager: networkManager,
  21. interfaceAddresses: make(map[C.InterfaceType][]netip.Prefix, interfaceAddresses.Size()),
  22. }
  23. var entryDescriptions []string
  24. for _, entry := range interfaceAddresses.Entries() {
  25. prefixes := make([]netip.Prefix, 0, len(entry.Value))
  26. for _, prefixable := range entry.Value {
  27. prefixes = append(prefixes, prefixable.Build(netip.Prefix{}))
  28. }
  29. item.interfaceAddresses[entry.Key.Build()] = prefixes
  30. entryDescriptions = append(entryDescriptions, entry.Key.Build().String()+"="+strings.Join(common.Map(prefixes, netip.Prefix.String), ","))
  31. }
  32. item.description = "network_interface_address=[" + strings.Join(entryDescriptions, " ") + "]"
  33. return item
  34. }
  35. func (r *NetworkInterfaceAddressItem) Match(metadata *adapter.InboundContext) bool {
  36. interfaces := r.networkManager.NetworkInterfaces()
  37. match:
  38. for ifType, addresses := range r.interfaceAddresses {
  39. for _, networkInterface := range interfaces {
  40. if networkInterface.Type != ifType {
  41. continue
  42. }
  43. if common.Any(networkInterface.Addresses, func(it netip.Prefix) bool {
  44. return common.Any(addresses, func(prefix netip.Prefix) bool {
  45. return prefix.Overlaps(it)
  46. })
  47. }) {
  48. continue match
  49. }
  50. }
  51. return false
  52. }
  53. return true
  54. }
  55. func (r *NetworkInterfaceAddressItem) String() string {
  56. return r.description
  57. }