blacklist.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package blacklist
  2. import (
  3. "bytes"
  4. "errors"
  5. "net"
  6. "strconv"
  7. "strings"
  8. db "imuslab.com/arozos/mod/database"
  9. )
  10. /*
  11. ArozOS Blacklist Module
  12. Author: tobychui
  13. This module record the IP blacklist of users trying to enter the
  14. system without permission
  15. */
  16. type BlackList struct {
  17. Enabled bool
  18. database *db.Database
  19. }
  20. func NewBlacklistManager(sysdb *db.Database) *BlackList {
  21. sysdb.NewTable("ipblacklist")
  22. return &BlackList{
  23. Enabled: true,
  24. database: sysdb,
  25. }
  26. }
  27. //Check if a given IP is banned
  28. func (bl *BlackList) IsBanned(ip string) bool {
  29. if bl.Enabled == false {
  30. return false
  31. }
  32. if bl.database.KeyExists("ipblacklist", ip) {
  33. return true
  34. }
  35. //The ip might be inside as a range. Do a range search.
  36. //Need optimization, current implementation is O(N)
  37. for _, thisIpRange := range bl.ListBannedIpRanges() {
  38. if ipInRange(ip, thisIpRange) {
  39. return true
  40. }
  41. }
  42. return false
  43. }
  44. func (bl *BlackList) ListBannedIpRanges() []string {
  45. entries, err := bl.database.ListTable("ipblacklist")
  46. if err != nil {
  47. return []string{}
  48. }
  49. results := []string{}
  50. for _, keypairs := range entries {
  51. thisIpRange := keypairs[0]
  52. results = append(results, string(thisIpRange))
  53. }
  54. return results
  55. }
  56. //Set the ban state of a ip or ip range
  57. func (bl *BlackList) Ban(ipRange string) error {
  58. //Check if the IP range is correct
  59. err := validateIpRange(ipRange)
  60. if err != nil {
  61. return err
  62. }
  63. //Push it to the ban list
  64. ipRange = strings.TrimSpace(ipRange)
  65. ipRange = strings.ReplaceAll(ipRange, " ", "")
  66. return bl.database.Write("ipblacklist", ipRange, true)
  67. }
  68. //Unban an IP or IP range
  69. func (bl *BlackList) UnBan(ipRange string) error {
  70. //Check if the IP range is correct
  71. err := validateIpRange(ipRange)
  72. if err != nil {
  73. return err
  74. }
  75. //Check if the ip range is banned
  76. if !bl.database.KeyExists("ipblacklist", ipRange) {
  77. return errors.New("invalid IP range given")
  78. }
  79. //Ip range exists, remove it from database
  80. return bl.database.Delete("ipblacklist", ipRange)
  81. }
  82. //Break an ip range text into independent ip strings
  83. func breakdownIpRange(ipRange string) []string {
  84. ipRange = strings.ReplaceAll(ipRange, " ", "")
  85. err := validateIpRange(ipRange)
  86. if err != nil {
  87. return []string{}
  88. }
  89. if !strings.Contains(ipRange, "-") {
  90. //This is not an ip range but a single ip
  91. return []string{ipRange}
  92. }
  93. //Break down the IP range
  94. results := []string{}
  95. ips := strings.Split(ipRange, "-")
  96. subnet := ips[0][:strings.LastIndex(ips[0], ".")]
  97. startD := ips[0][strings.LastIndex(ips[0], ".")+1:]
  98. if err != nil {
  99. return []string{}
  100. }
  101. endD := ips[1][strings.LastIndex(ips[0], ".")+1:]
  102. if err != nil {
  103. return []string{}
  104. }
  105. startDInt, err := strconv.Atoi(startD)
  106. endDInt, err := strconv.Atoi(endD)
  107. currentDInt := startDInt
  108. for currentDInt < endDInt+1 {
  109. results = append(results, subnet+"."+strconv.Itoa(currentDInt))
  110. currentDInt++
  111. }
  112. return results
  113. }
  114. //Check if an given ip in the given range
  115. func ipInRange(ip string, ipRange string) bool {
  116. ip = strings.TrimSpace(ip)
  117. ipRange = strings.ReplaceAll(ipRange, " ", "")
  118. if ip == ipRange {
  119. //For fields that the ipRange is the ip itself
  120. return true
  121. }
  122. //Try matching range
  123. if strings.Contains(ipRange, "-") {
  124. //Parse the source IP
  125. trial := net.ParseIP(ip)
  126. //Parse the IP range
  127. ips := strings.Split(ipRange, "-")
  128. ip1 := net.ParseIP(ips[0])
  129. if ip1 == nil {
  130. return false
  131. }
  132. ip2 := net.ParseIP(ips[1])
  133. if ip2 == nil {
  134. return false
  135. }
  136. if trial.To4() == nil {
  137. return false
  138. }
  139. if bytes.Compare(trial, ip1) >= 0 && bytes.Compare(trial, ip2) <= 0 {
  140. return true
  141. }
  142. return false
  143. }
  144. return false
  145. }
  146. //Check if the given IP Range string is actually an IP range
  147. func validateIpRange(ipRange string) error {
  148. ipRange = strings.TrimSpace(ipRange)
  149. ipRange = strings.ReplaceAll(ipRange, " ", "")
  150. if strings.Contains(ipRange, "-") {
  151. //This is a range
  152. if strings.Count(ipRange, "-") != 1 {
  153. //Invalid range defination
  154. return errors.New("Invalid ip range defination")
  155. }
  156. ips := strings.Split(ipRange, "-")
  157. //Check if the starting IP and ending IP are both valid
  158. if net.ParseIP(ips[0]) == nil {
  159. return errors.New("Starting ip is invalid")
  160. }
  161. if net.ParseIP(ips[1]) == nil {
  162. return errors.New("Ending ip is invalid")
  163. }
  164. //Check if the ending IP is larger than the starting IP
  165. startingIpInt, _ := strconv.Atoi(strings.ReplaceAll(ips[0], ".", ""))
  166. endingIpInt, _ := strconv.Atoi(strings.ReplaceAll(ips[1], ".", ""))
  167. if startingIpInt >= endingIpInt {
  168. return errors.New("Invalid ip range: Starting IP is larger or equal to ending ip")
  169. }
  170. //Check if they are in the same subnet
  171. startSubnet := ips[0][:strings.LastIndex(ips[0], ".")]
  172. endSubnet := ips[1][:strings.LastIndex(ips[1], ".")]
  173. if startSubnet != endSubnet {
  174. //They are not in the same subnet
  175. return errors.New("IP range subnet mismatch")
  176. }
  177. } else {
  178. //This is a single IP instead of range. Check if it is a valid IP addr
  179. if net.ParseIP(ipRange) != nil {
  180. //Ok
  181. return nil
  182. } else {
  183. return errors.New("Invalid ip given")
  184. }
  185. }
  186. return nil
  187. }