dynamic_lists.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package firewall
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "os/exec"
  8. "strconv"
  9. "strings"
  10. )
  11. func dynamicEntryID(name, address string) string {
  12. b, _ := json.Marshal([]string{name, address})
  13. return "dynamic-" + base64.RawURLEncoding.EncodeToString(b)
  14. }
  15. func deleteDynamicEntry(id string) error {
  16. b, err := base64.RawURLEncoding.DecodeString(strings.TrimPrefix(id, "dynamic-"))
  17. if err != nil {
  18. return fmt.Errorf("invalid dynamic entry ID")
  19. }
  20. var fields []string
  21. if json.Unmarshal(b, &fields) != nil || len(fields) != 2 || net.ParseIP(fields[1]) == nil {
  22. return fmt.Errorf("invalid dynamic entry ID")
  23. }
  24. if err := validateListName(fields[0]); err != nil {
  25. return err
  26. }
  27. name := GetDynamicIPSetName(fields[0])
  28. if net.ParseIP(fields[1]).To4() == nil {
  29. name += "_v6"
  30. }
  31. return runIPSet("del", name, fields[1], "-exist")
  32. }
  33. func (m *FirewallManager) addressListReferences() []string {
  34. var refs []string
  35. for _, r := range m.filterRules {
  36. if !r.Disabled {
  37. refs = append(refs, r.SrcAddressList, r.DstAddressList, r.AddressList)
  38. }
  39. }
  40. for _, r := range m.natRules {
  41. if !r.Disabled {
  42. refs = append(refs, r.SrcAddressList, r.DstAddressList, r.AddressList)
  43. }
  44. }
  45. for _, r := range m.mangleRules {
  46. if !r.Disabled {
  47. refs = append(refs, r.SrcAddressList, r.DstAddressList, r.AddressList)
  48. }
  49. }
  50. return refs
  51. }
  52. func (m *FirewallManager) dynamicEntries() []AddressListEntry {
  53. names := map[string]bool{}
  54. for _, e := range m.addressLists {
  55. names[e.Name] = true
  56. }
  57. for _, name := range m.addressListReferences() {
  58. name = strings.TrimPrefix(name, "!")
  59. if name != "" && !strings.HasPrefix(name, "geo:") && !strings.HasPrefix(name, "geo_") {
  60. names[name] = true
  61. }
  62. }
  63. var result []AddressListEntry
  64. for name := range names {
  65. for _, suffix := range []string{"", "_v6"} {
  66. set := GetDynamicIPSetName(name) + suffix
  67. out, err := exec.Command("ipset", "save", set).Output()
  68. if err != nil {
  69. continue
  70. }
  71. for _, line := range strings.Split(string(out), "\n") {
  72. parts := strings.Fields(line)
  73. if len(parts) < 3 || parts[0] != "add" {
  74. continue
  75. }
  76. ip := net.ParseIP(parts[2])
  77. if ip == nil {
  78. continue
  79. }
  80. remaining := 0
  81. for i := 3; i+1 < len(parts); i++ {
  82. if parts[i] == "timeout" {
  83. remaining, _ = strconv.Atoi(parts[i+1])
  84. }
  85. }
  86. result = append(result, AddressListEntry{ID: dynamicEntryID(name, ip.String()), Name: name, Address: ip.String(), Dynamic: true, Timeout: remaining})
  87. if len(result) >= 2000 {
  88. return result
  89. }
  90. }
  91. }
  92. }
  93. return result
  94. }