defender_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. package common
  2. import (
  3. "crypto/rand"
  4. "encoding/hex"
  5. "encoding/json"
  6. "fmt"
  7. "net"
  8. "os"
  9. "path/filepath"
  10. "runtime"
  11. "testing"
  12. "time"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. "github.com/yl2chen/cidranger"
  16. )
  17. func TestBasicDefender(t *testing.T) {
  18. bl := HostListFile{
  19. IPAddresses: []string{"172.16.1.1", "172.16.1.2"},
  20. CIDRNetworks: []string{"10.8.0.0/24"},
  21. }
  22. sl := HostListFile{
  23. IPAddresses: []string{"172.16.1.3", "172.16.1.4"},
  24. CIDRNetworks: []string{"192.168.8.0/24"},
  25. }
  26. blFile := filepath.Join(os.TempDir(), "bl.json")
  27. slFile := filepath.Join(os.TempDir(), "sl.json")
  28. data, err := json.Marshal(bl)
  29. assert.NoError(t, err)
  30. err = os.WriteFile(blFile, data, os.ModePerm)
  31. assert.NoError(t, err)
  32. data, err = json.Marshal(sl)
  33. assert.NoError(t, err)
  34. err = os.WriteFile(slFile, data, os.ModePerm)
  35. assert.NoError(t, err)
  36. config := &DefenderConfig{
  37. Enabled: true,
  38. BanTime: 10,
  39. BanTimeIncrement: 2,
  40. Threshold: 5,
  41. ScoreInvalid: 2,
  42. ScoreValid: 1,
  43. ScoreLimitExceeded: 3,
  44. ObservationTime: 15,
  45. EntriesSoftLimit: 1,
  46. EntriesHardLimit: 2,
  47. SafeListFile: "slFile",
  48. BlockListFile: "blFile",
  49. }
  50. _, err = newInMemoryDefender(config)
  51. assert.Error(t, err)
  52. config.BlockListFile = blFile
  53. _, err = newInMemoryDefender(config)
  54. assert.Error(t, err)
  55. config.SafeListFile = slFile
  56. d, err := newInMemoryDefender(config)
  57. assert.NoError(t, err)
  58. defender := d.(*memoryDefender)
  59. assert.True(t, defender.IsBanned("172.16.1.1"))
  60. assert.False(t, defender.IsBanned("172.16.1.10"))
  61. assert.False(t, defender.IsBanned("10.8.2.3"))
  62. assert.True(t, defender.IsBanned("10.8.0.3"))
  63. assert.False(t, defender.IsBanned("invalid ip"))
  64. assert.Equal(t, 0, defender.countBanned())
  65. assert.Equal(t, 0, defender.countHosts())
  66. hosts, err := defender.GetHosts()
  67. assert.NoError(t, err)
  68. assert.Len(t, hosts, 0)
  69. _, err = defender.GetHost("10.8.0.4")
  70. assert.Error(t, err)
  71. defender.AddEvent("172.16.1.4", HostEventLoginFailed)
  72. defender.AddEvent("192.168.8.4", HostEventUserNotFound)
  73. defender.AddEvent("172.16.1.3", HostEventLimitExceeded)
  74. assert.Equal(t, 0, defender.countHosts())
  75. testIP := "12.34.56.78"
  76. defender.AddEvent(testIP, HostEventLoginFailed)
  77. assert.Equal(t, 1, defender.countHosts())
  78. assert.Equal(t, 0, defender.countBanned())
  79. score, err := defender.GetScore(testIP)
  80. assert.NoError(t, err)
  81. assert.Equal(t, 1, score)
  82. hosts, err = defender.GetHosts()
  83. assert.NoError(t, err)
  84. if assert.Len(t, hosts, 1) {
  85. assert.Equal(t, 1, hosts[0].Score)
  86. assert.True(t, hosts[0].BanTime.IsZero())
  87. assert.Empty(t, hosts[0].GetBanTime())
  88. }
  89. host, err := defender.GetHost(testIP)
  90. assert.NoError(t, err)
  91. assert.Equal(t, 1, host.Score)
  92. assert.Empty(t, host.GetBanTime())
  93. banTime, err := defender.GetBanTime(testIP)
  94. assert.NoError(t, err)
  95. assert.Nil(t, banTime)
  96. defender.AddEvent(testIP, HostEventLimitExceeded)
  97. assert.Equal(t, 1, defender.countHosts())
  98. assert.Equal(t, 0, defender.countBanned())
  99. score, err = defender.GetScore(testIP)
  100. assert.NoError(t, err)
  101. assert.Equal(t, 4, score)
  102. hosts, err = defender.GetHosts()
  103. assert.NoError(t, err)
  104. if assert.Len(t, hosts, 1) {
  105. assert.Equal(t, 4, hosts[0].Score)
  106. assert.True(t, hosts[0].BanTime.IsZero())
  107. assert.Empty(t, hosts[0].GetBanTime())
  108. }
  109. defender.AddEvent(testIP, HostEventNoLoginTried)
  110. defender.AddEvent(testIP, HostEventNoLoginTried)
  111. assert.Equal(t, 0, defender.countHosts())
  112. assert.Equal(t, 1, defender.countBanned())
  113. score, err = defender.GetScore(testIP)
  114. assert.NoError(t, err)
  115. assert.Equal(t, 0, score)
  116. banTime, err = defender.GetBanTime(testIP)
  117. assert.NoError(t, err)
  118. assert.NotNil(t, banTime)
  119. hosts, err = defender.GetHosts()
  120. assert.NoError(t, err)
  121. if assert.Len(t, hosts, 1) {
  122. assert.Equal(t, 0, hosts[0].Score)
  123. assert.False(t, hosts[0].BanTime.IsZero())
  124. assert.NotEmpty(t, hosts[0].GetBanTime())
  125. assert.Equal(t, hex.EncodeToString([]byte(testIP)), hosts[0].GetID())
  126. }
  127. host, err = defender.GetHost(testIP)
  128. assert.NoError(t, err)
  129. assert.Equal(t, 0, host.Score)
  130. assert.NotEmpty(t, host.GetBanTime())
  131. // now test cleanup, testIP is already banned
  132. testIP1 := "12.34.56.79"
  133. testIP2 := "12.34.56.80"
  134. testIP3 := "12.34.56.81"
  135. defender.AddEvent(testIP1, HostEventNoLoginTried)
  136. defender.AddEvent(testIP2, HostEventNoLoginTried)
  137. assert.Equal(t, 2, defender.countHosts())
  138. time.Sleep(20 * time.Millisecond)
  139. defender.AddEvent(testIP3, HostEventNoLoginTried)
  140. assert.Equal(t, defender.config.EntriesSoftLimit, defender.countHosts())
  141. // testIP1 and testIP2 should be removed
  142. assert.Equal(t, defender.config.EntriesSoftLimit, defender.countHosts())
  143. score, err = defender.GetScore(testIP1)
  144. assert.NoError(t, err)
  145. assert.Equal(t, 0, score)
  146. score, err = defender.GetScore(testIP2)
  147. assert.NoError(t, err)
  148. assert.Equal(t, 0, score)
  149. score, err = defender.GetScore(testIP3)
  150. assert.NoError(t, err)
  151. assert.Equal(t, 2, score)
  152. defender.AddEvent(testIP3, HostEventNoLoginTried)
  153. defender.AddEvent(testIP3, HostEventNoLoginTried)
  154. // IP3 is now banned
  155. banTime, err = defender.GetBanTime(testIP3)
  156. assert.NoError(t, err)
  157. assert.NotNil(t, banTime)
  158. assert.Equal(t, 0, defender.countHosts())
  159. time.Sleep(20 * time.Millisecond)
  160. for i := 0; i < 3; i++ {
  161. defender.AddEvent(testIP1, HostEventNoLoginTried)
  162. }
  163. assert.Equal(t, 0, defender.countHosts())
  164. assert.Equal(t, config.EntriesSoftLimit, defender.countBanned())
  165. banTime, err = defender.GetBanTime(testIP)
  166. assert.NoError(t, err)
  167. assert.Nil(t, banTime)
  168. banTime, err = defender.GetBanTime(testIP3)
  169. assert.NoError(t, err)
  170. assert.Nil(t, banTime)
  171. banTime, err = defender.GetBanTime(testIP1)
  172. assert.NoError(t, err)
  173. assert.NotNil(t, banTime)
  174. for i := 0; i < 3; i++ {
  175. defender.AddEvent(testIP, HostEventNoLoginTried)
  176. time.Sleep(10 * time.Millisecond)
  177. defender.AddEvent(testIP3, HostEventNoLoginTried)
  178. }
  179. assert.Equal(t, 0, defender.countHosts())
  180. assert.Equal(t, defender.config.EntriesSoftLimit, defender.countBanned())
  181. banTime, err = defender.GetBanTime(testIP3)
  182. assert.NoError(t, err)
  183. if assert.NotNil(t, banTime) {
  184. assert.True(t, defender.IsBanned(testIP3))
  185. // ban time should increase
  186. newBanTime, err := defender.GetBanTime(testIP3)
  187. assert.NoError(t, err)
  188. assert.True(t, newBanTime.After(*banTime))
  189. }
  190. assert.True(t, defender.DeleteHost(testIP3))
  191. assert.False(t, defender.DeleteHost(testIP3))
  192. err = os.Remove(slFile)
  193. assert.NoError(t, err)
  194. err = os.Remove(blFile)
  195. assert.NoError(t, err)
  196. }
  197. func TestExpiredHostBans(t *testing.T) {
  198. config := &DefenderConfig{
  199. Enabled: true,
  200. BanTime: 10,
  201. BanTimeIncrement: 2,
  202. Threshold: 5,
  203. ScoreInvalid: 2,
  204. ScoreValid: 1,
  205. ScoreLimitExceeded: 3,
  206. ObservationTime: 15,
  207. EntriesSoftLimit: 1,
  208. EntriesHardLimit: 2,
  209. }
  210. d, err := newInMemoryDefender(config)
  211. assert.NoError(t, err)
  212. defender := d.(*memoryDefender)
  213. testIP := "1.2.3.4"
  214. defender.banned[testIP] = time.Now().Add(-24 * time.Hour)
  215. // the ban is expired testIP should not be listed
  216. res, err := defender.GetHosts()
  217. assert.NoError(t, err)
  218. assert.Len(t, res, 0)
  219. assert.False(t, defender.IsBanned(testIP))
  220. _, err = defender.GetHost(testIP)
  221. assert.Error(t, err)
  222. _, ok := defender.banned[testIP]
  223. assert.True(t, ok)
  224. // now add an event for an expired banned ip, it should be removed
  225. defender.AddEvent(testIP, HostEventLoginFailed)
  226. assert.False(t, defender.IsBanned(testIP))
  227. entry, err := defender.GetHost(testIP)
  228. assert.NoError(t, err)
  229. assert.Equal(t, testIP, entry.IP)
  230. assert.Empty(t, entry.GetBanTime())
  231. assert.Equal(t, 1, entry.Score)
  232. res, err = defender.GetHosts()
  233. assert.NoError(t, err)
  234. if assert.Len(t, res, 1) {
  235. assert.Equal(t, testIP, res[0].IP)
  236. assert.Empty(t, res[0].GetBanTime())
  237. assert.Equal(t, 1, res[0].Score)
  238. }
  239. events := []hostEvent{
  240. {
  241. dateTime: time.Now().Add(-24 * time.Hour),
  242. score: 2,
  243. },
  244. {
  245. dateTime: time.Now().Add(-24 * time.Hour),
  246. score: 3,
  247. },
  248. }
  249. hs := hostScore{
  250. Events: events,
  251. TotalScore: 5,
  252. }
  253. defender.hosts[testIP] = hs
  254. // the recorded scored are too old
  255. res, err = defender.GetHosts()
  256. assert.NoError(t, err)
  257. assert.Len(t, res, 0)
  258. _, err = defender.GetHost(testIP)
  259. assert.Error(t, err)
  260. _, ok = defender.hosts[testIP]
  261. assert.True(t, ok)
  262. }
  263. func TestLoadHostListFromFile(t *testing.T) {
  264. _, err := loadHostListFromFile(".")
  265. assert.Error(t, err)
  266. hostsFilePath := filepath.Join(os.TempDir(), "hostfile")
  267. content := make([]byte, 1048576*6)
  268. _, err = rand.Read(content)
  269. assert.NoError(t, err)
  270. err = os.WriteFile(hostsFilePath, content, os.ModePerm)
  271. assert.NoError(t, err)
  272. _, err = loadHostListFromFile(hostsFilePath)
  273. assert.Error(t, err)
  274. hl := HostListFile{
  275. IPAddresses: []string{},
  276. CIDRNetworks: []string{},
  277. }
  278. asJSON, err := json.Marshal(hl)
  279. assert.NoError(t, err)
  280. err = os.WriteFile(hostsFilePath, asJSON, os.ModePerm)
  281. assert.NoError(t, err)
  282. hostList, err := loadHostListFromFile(hostsFilePath)
  283. assert.NoError(t, err)
  284. assert.Nil(t, hostList)
  285. hl.IPAddresses = append(hl.IPAddresses, "invalidip")
  286. asJSON, err = json.Marshal(hl)
  287. assert.NoError(t, err)
  288. err = os.WriteFile(hostsFilePath, asJSON, os.ModePerm)
  289. assert.NoError(t, err)
  290. hostList, err = loadHostListFromFile(hostsFilePath)
  291. assert.NoError(t, err)
  292. assert.Len(t, hostList.IPAddresses, 0)
  293. hl.IPAddresses = nil
  294. hl.CIDRNetworks = append(hl.CIDRNetworks, "invalid net")
  295. asJSON, err = json.Marshal(hl)
  296. assert.NoError(t, err)
  297. err = os.WriteFile(hostsFilePath, asJSON, os.ModePerm)
  298. assert.NoError(t, err)
  299. hostList, err = loadHostListFromFile(hostsFilePath)
  300. assert.NoError(t, err)
  301. assert.NotNil(t, hostList)
  302. assert.Len(t, hostList.IPAddresses, 0)
  303. assert.Equal(t, 0, hostList.Ranges.Len())
  304. if runtime.GOOS != "windows" {
  305. err = os.Chmod(hostsFilePath, 0111)
  306. assert.NoError(t, err)
  307. _, err = loadHostListFromFile(hostsFilePath)
  308. assert.Error(t, err)
  309. err = os.Chmod(hostsFilePath, 0644)
  310. assert.NoError(t, err)
  311. }
  312. err = os.WriteFile(hostsFilePath, []byte("non json content"), os.ModePerm)
  313. assert.NoError(t, err)
  314. _, err = loadHostListFromFile(hostsFilePath)
  315. assert.Error(t, err)
  316. err = os.Remove(hostsFilePath)
  317. assert.NoError(t, err)
  318. }
  319. func TestDefenderCleanup(t *testing.T) {
  320. d := memoryDefender{
  321. baseDefender: baseDefender{
  322. config: &DefenderConfig{
  323. ObservationTime: 1,
  324. EntriesSoftLimit: 2,
  325. EntriesHardLimit: 3,
  326. },
  327. },
  328. banned: make(map[string]time.Time),
  329. hosts: make(map[string]hostScore),
  330. }
  331. d.banned["1.1.1.1"] = time.Now().Add(-24 * time.Hour)
  332. d.banned["1.1.1.2"] = time.Now().Add(-24 * time.Hour)
  333. d.banned["1.1.1.3"] = time.Now().Add(-24 * time.Hour)
  334. d.banned["1.1.1.4"] = time.Now().Add(-24 * time.Hour)
  335. d.cleanupBanned()
  336. assert.Equal(t, 0, d.countBanned())
  337. d.banned["2.2.2.2"] = time.Now().Add(2 * time.Minute)
  338. d.banned["2.2.2.3"] = time.Now().Add(1 * time.Minute)
  339. d.banned["2.2.2.4"] = time.Now().Add(3 * time.Minute)
  340. d.banned["2.2.2.5"] = time.Now().Add(4 * time.Minute)
  341. d.cleanupBanned()
  342. assert.Equal(t, d.config.EntriesSoftLimit, d.countBanned())
  343. banTime, err := d.GetBanTime("2.2.2.3")
  344. assert.NoError(t, err)
  345. assert.Nil(t, banTime)
  346. d.hosts["3.3.3.3"] = hostScore{
  347. TotalScore: 0,
  348. Events: []hostEvent{
  349. {
  350. dateTime: time.Now().Add(-5 * time.Minute),
  351. score: 1,
  352. },
  353. {
  354. dateTime: time.Now().Add(-3 * time.Minute),
  355. score: 1,
  356. },
  357. {
  358. dateTime: time.Now(),
  359. score: 1,
  360. },
  361. },
  362. }
  363. d.hosts["3.3.3.4"] = hostScore{
  364. TotalScore: 1,
  365. Events: []hostEvent{
  366. {
  367. dateTime: time.Now().Add(-3 * time.Minute),
  368. score: 1,
  369. },
  370. },
  371. }
  372. d.hosts["3.3.3.5"] = hostScore{
  373. TotalScore: 1,
  374. Events: []hostEvent{
  375. {
  376. dateTime: time.Now().Add(-2 * time.Minute),
  377. score: 1,
  378. },
  379. },
  380. }
  381. d.hosts["3.3.3.6"] = hostScore{
  382. TotalScore: 1,
  383. Events: []hostEvent{
  384. {
  385. dateTime: time.Now().Add(-1 * time.Minute),
  386. score: 1,
  387. },
  388. },
  389. }
  390. score, err := d.GetScore("3.3.3.3")
  391. assert.NoError(t, err)
  392. assert.Equal(t, 1, score)
  393. d.cleanupHosts()
  394. assert.Equal(t, d.config.EntriesSoftLimit, d.countHosts())
  395. score, err = d.GetScore("3.3.3.4")
  396. assert.NoError(t, err)
  397. assert.Equal(t, 0, score)
  398. }
  399. func TestDefenderConfig(t *testing.T) {
  400. c := DefenderConfig{}
  401. err := c.validate()
  402. require.NoError(t, err)
  403. c.Enabled = true
  404. c.Threshold = 10
  405. c.ScoreInvalid = 10
  406. err = c.validate()
  407. require.Error(t, err)
  408. c.ScoreInvalid = 2
  409. c.ScoreLimitExceeded = 10
  410. err = c.validate()
  411. require.Error(t, err)
  412. c.ScoreLimitExceeded = 2
  413. c.ScoreValid = 10
  414. err = c.validate()
  415. require.Error(t, err)
  416. c.ScoreValid = 1
  417. c.BanTime = 0
  418. err = c.validate()
  419. require.Error(t, err)
  420. c.BanTime = 30
  421. c.BanTimeIncrement = 0
  422. err = c.validate()
  423. require.Error(t, err)
  424. c.BanTimeIncrement = 50
  425. c.ObservationTime = 0
  426. err = c.validate()
  427. require.Error(t, err)
  428. c.ObservationTime = 30
  429. err = c.validate()
  430. require.Error(t, err)
  431. c.EntriesSoftLimit = 10
  432. err = c.validate()
  433. require.Error(t, err)
  434. c.EntriesHardLimit = 10
  435. err = c.validate()
  436. require.Error(t, err)
  437. c.EntriesHardLimit = 20
  438. err = c.validate()
  439. require.NoError(t, err)
  440. }
  441. func BenchmarkDefenderBannedSearch(b *testing.B) {
  442. d := getDefenderForBench()
  443. ip, ipnet, err := net.ParseCIDR("10.8.0.0/12") // 1048574 ip addresses
  444. if err != nil {
  445. panic(err)
  446. }
  447. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
  448. d.banned[ip.String()] = time.Now().Add(10 * time.Minute)
  449. }
  450. b.ResetTimer()
  451. for i := 0; i < b.N; i++ {
  452. d.IsBanned("192.168.1.1")
  453. }
  454. }
  455. func BenchmarkCleanup(b *testing.B) {
  456. d := getDefenderForBench()
  457. ip, ipnet, err := net.ParseCIDR("192.168.4.0/24")
  458. if err != nil {
  459. panic(err)
  460. }
  461. b.ResetTimer()
  462. for i := 0; i < b.N; i++ {
  463. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
  464. d.AddEvent(ip.String(), HostEventLoginFailed)
  465. if d.countHosts() > d.config.EntriesHardLimit {
  466. panic("too many hosts")
  467. }
  468. if d.countBanned() > d.config.EntriesSoftLimit {
  469. panic("too many ip banned")
  470. }
  471. }
  472. }
  473. }
  474. func BenchmarkDefenderBannedSearchWithBlockList(b *testing.B) {
  475. d := getDefenderForBench()
  476. d.blockList = &HostList{
  477. IPAddresses: make(map[string]bool),
  478. Ranges: cidranger.NewPCTrieRanger(),
  479. }
  480. ip, ipnet, err := net.ParseCIDR("129.8.0.0/12") // 1048574 ip addresses
  481. if err != nil {
  482. panic(err)
  483. }
  484. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
  485. d.banned[ip.String()] = time.Now().Add(10 * time.Minute)
  486. d.blockList.IPAddresses[ip.String()] = true
  487. }
  488. for i := 0; i < 255; i++ {
  489. cidr := fmt.Sprintf("10.8.%v.1/24", i)
  490. _, network, _ := net.ParseCIDR(cidr)
  491. if err := d.blockList.Ranges.Insert(cidranger.NewBasicRangerEntry(*network)); err != nil {
  492. panic(err)
  493. }
  494. }
  495. b.ResetTimer()
  496. for i := 0; i < b.N; i++ {
  497. d.IsBanned("192.168.1.1")
  498. }
  499. }
  500. func BenchmarkHostListSearch(b *testing.B) {
  501. hostlist := &HostList{
  502. IPAddresses: make(map[string]bool),
  503. Ranges: cidranger.NewPCTrieRanger(),
  504. }
  505. ip, ipnet, _ := net.ParseCIDR("172.16.0.0/16")
  506. for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
  507. hostlist.IPAddresses[ip.String()] = true
  508. }
  509. for i := 0; i < 255; i++ {
  510. cidr := fmt.Sprintf("10.8.%v.1/24", i)
  511. _, network, _ := net.ParseCIDR(cidr)
  512. if err := hostlist.Ranges.Insert(cidranger.NewBasicRangerEntry(*network)); err != nil {
  513. panic(err)
  514. }
  515. }
  516. b.ResetTimer()
  517. for i := 0; i < b.N; i++ {
  518. if hostlist.isListed("192.167.1.2") {
  519. panic("should not be listed")
  520. }
  521. }
  522. }
  523. func BenchmarkCIDRanger(b *testing.B) {
  524. ranger := cidranger.NewPCTrieRanger()
  525. for i := 0; i < 255; i++ {
  526. cidr := fmt.Sprintf("192.168.%v.1/24", i)
  527. _, network, _ := net.ParseCIDR(cidr)
  528. if err := ranger.Insert(cidranger.NewBasicRangerEntry(*network)); err != nil {
  529. panic(err)
  530. }
  531. }
  532. ipToMatch := net.ParseIP("192.167.1.2")
  533. b.ResetTimer()
  534. for i := 0; i < b.N; i++ {
  535. if _, err := ranger.Contains(ipToMatch); err != nil {
  536. panic(err)
  537. }
  538. }
  539. }
  540. func BenchmarkNetContains(b *testing.B) {
  541. var nets []*net.IPNet
  542. for i := 0; i < 255; i++ {
  543. cidr := fmt.Sprintf("192.168.%v.1/24", i)
  544. _, network, _ := net.ParseCIDR(cidr)
  545. nets = append(nets, network)
  546. }
  547. ipToMatch := net.ParseIP("192.167.1.1")
  548. b.ResetTimer()
  549. for i := 0; i < b.N; i++ {
  550. for _, n := range nets {
  551. n.Contains(ipToMatch)
  552. }
  553. }
  554. }
  555. func getDefenderForBench() *memoryDefender {
  556. config := &DefenderConfig{
  557. Enabled: true,
  558. BanTime: 30,
  559. BanTimeIncrement: 50,
  560. Threshold: 10,
  561. ScoreInvalid: 2,
  562. ScoreValid: 2,
  563. ObservationTime: 30,
  564. EntriesSoftLimit: 50,
  565. EntriesHardLimit: 100,
  566. }
  567. return &memoryDefender{
  568. baseDefender: baseDefender{
  569. config: config,
  570. },
  571. hosts: make(map[string]hostScore),
  572. banned: make(map[string]time.Time),
  573. }
  574. }
  575. func inc(ip net.IP) {
  576. for j := len(ip) - 1; j >= 0; j-- {
  577. ip[j]++
  578. if ip[j] > 0 {
  579. break
  580. }
  581. }
  582. }