wafris 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05707fe625f71f24a02f26585d89356156b1dc83887195f1042a47856d3c86cf
4
- data.tar.gz: 05e798e3298518a0310f1cdf6a68426b2b12f9c066acc74e78833987e26f2e31
3
+ metadata.gz: 2da3a1b92fba96e01f65433a9388d7dbeb8f24225b352e1958f392cd82fc8522
4
+ data.tar.gz: c8a72dcb1459454890d11d5ba0190f2b4a7f0d13cc63ce9d7038e87cb8ca7af7
5
5
  SHA512:
6
- metadata.gz: b41d4ee2190f5a88e263ef6905ffe43e6727923df4f3f1a600f203d10ea2010409e95c02c965cc2161fce47d5d541aaa1217beeb05097134fcaecdcfcd4305f1
7
- data.tar.gz: dd940d846b7892a4607c78767f2ca364c62ab33782deb76b863d8b393f1a5c82134f0b3f6c76a438f9993e7d7702df67899d9e6485bc5491e03fcc3e02a38c1e
6
+ metadata.gz: ef4e1b43b6ae8f9060e8ba936ebffed084288e3a0df798c487141dd608f9f136e4cde74babc9ed9ab9c908f96a558fd674dcc9b579f94cc0bc95da581a973a20
7
+ data.tar.gz: a252ddc02c510c14c011c23d3127a5f17d7dc97dc6b44a46e889b85b4130e9897c4d9623fb6ad144e6cc32f21524ad5d58f008d9d1b6376c47884c2f42c94008
@@ -60,28 +60,42 @@ local function add_to_HLL_request_count(timebucket, request_id)
60
60
  end
61
61
 
62
62
  -- For: Leaderboard of IPs with Request count as score
63
- local function increment_timebucket_for_ip(timebucket, ip)
64
- redis.call("ZINCRBY", "ip-leader-sset:" .. timebucket, 1, ip)
63
+ local function increment_timebucket_for(type, timebucket, property)
64
+ -- TODO: breaking change will to switch to client_ip: prefix
65
+ type = type or "ip-"
66
+ redis.call("ZINCRBY", type .. "leader-sset:" .. timebucket, 1, property)
65
67
  end
66
68
 
67
69
  -- Configuration
68
70
  local max_requests = 100000
69
71
  local max_requests_per_ip = 10000
70
72
 
71
- local ip = ARGV[1]
73
+ local client_ip = ARGV[1]
72
74
  local ip_to_decimal = ARGV[2]
73
75
  local unix_time_milliseconds = ARGV[3]
74
76
  local unix_time = ARGV[3] / 1000
77
+ local proxy_ip = ARGV[4]
78
+ local user_agent = ARGV[5]
79
+ local request_path = ARGV[6]
80
+ local host = ARGV[7]
75
81
 
76
82
  -- Initialize local variables
77
- local request_id = get_request_id(nil, ip, max_requests)
83
+ local request_id = get_request_id(nil, client_ip, max_requests)
78
84
  local current_timebucket = get_time_bucket_from_timestamp(unix_time_milliseconds)
79
85
 
80
86
  -- GRAPH DATA COLLECTION
81
87
  add_to_HLL_request_count(current_timebucket, request_id)
82
88
 
83
89
  -- LEADERBOARD DATA COLLECTION
84
- increment_timebucket_for_ip(current_timebucket, ip)
90
+ -- TODO: breaking change will to switch to client_ip: prefix
91
+ increment_timebucket_for(nil, current_timebucket, client_ip)
92
+ if proxy_ip ~= nil then
93
+ increment_timebucket_for(nil, current_timebucket, proxy_ip)
94
+ end
95
+ increment_timebucket_for("proxy_ip:", current_timebucket, proxy_ip)
96
+ increment_timebucket_for("user_agent:", current_timebucket, user_agent)
97
+ increment_timebucket_for("request_path:", current_timebucket, request_path)
98
+ increment_timebucket_for("host:", current_timebucket, host)
85
99
 
86
100
  -- BLOCKING LOGIC
87
101
  -- Safelist Range Check
@@ -36,14 +36,6 @@ module Wafris
36
36
  read_lua_dist("wafris_core")
37
37
  end
38
38
 
39
- def graph_sha
40
- @graph_sha ||= redis.script(:load, wafris_graph)
41
- end
42
-
43
- def wafris_graph
44
- read_lua_dist("get_graph_data")
45
- end
46
-
47
39
  private
48
40
 
49
41
  def read_lua_dist(filename)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wafris
4
- VERSION = "0.1.2"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/wafris.rb CHANGED
@@ -32,12 +32,18 @@ module Wafris
32
32
  def allow_request?(request)
33
33
  configuration.connection_pool.with do |conn|
34
34
  time = Time.now.to_f * 1000
35
+ puts "WAF LOG: Client IP #{client_ip(request)}"
36
+ puts "WAF LOG: Proxy IP #{proxy_ip(request)}"
35
37
  status = conn.evalsha(
36
38
  configuration.core_sha,
37
39
  argv: [
38
- request.ip,
40
+ client_ip(request),
39
41
  IPAddr.new(request.ip).to_i,
40
- time.to_i
42
+ time.to_i,
43
+ proxy_ip(request),
44
+ request.user_agent,
45
+ request.path,
46
+ request.host
41
47
  ]
42
48
  )
43
49
 
@@ -49,60 +55,18 @@ module Wafris
49
55
  end
50
56
  end
51
57
 
52
- def add_block(ip)
53
- configuration.connection_pool.with do |conn|
54
- conn.zadd(
55
- 'blocked_ranges',
56
- IPAddr.new(ip).to_i,
57
- ip
58
- )
59
- end
60
- end
61
-
62
- def remove_block(ip)
63
- configuration.connection_pool.with do |conn|
64
- conn.zrem(
65
- 'blocked_ranges',
66
- ip
67
- )
68
- end
69
- end
70
-
71
- def request_buckets(_now)
72
- graph_data = []
73
- configuration.connection_pool.with do |conn|
74
- time = Time.now.to_f * 1000
75
- graph_data = conn.evalsha(
76
- configuration.graph_sha,
77
- argv: [
78
- time.to_i
79
- ]
80
- )
81
- end
58
+ private
82
59
 
83
- return graph_data
84
- end
60
+ def client_ip(request)
61
+ return request.ip if request.headers['x-forwarded-for'].nil?
85
62
 
86
- def ips_with_num_requests
87
- configuration.connection_pool.with do |conn|
88
- return conn.zunion(
89
- *leader_timebuckets,
90
- 0, -1, with_scores: true
91
- )
92
- end
63
+ request.headers['x-forwarded-for'].split(',').first
93
64
  end
94
65
 
95
- private
96
-
97
- def leader_timebuckets
98
- timebuckets = []
99
-
100
- time = Time.now.utc
101
- 24.times do |hours|
102
- timebuckets << "ip-leader-sset:#{(time - 60 * 60 * hours).strftime("%Y-%m-%d-%H")}"
103
- end
66
+ def proxy_ip(request)
67
+ return nil if request.headers['x-forwarded-for'].nil?
104
68
 
105
- return timebuckets
69
+ request.headers['x-forwarded-for'].split(',').last
106
70
  end
107
71
  end
108
72
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wafris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micahel Buckbee
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-04-23 00:00:00.000000000 Z
12
+ date: 2023-05-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: connection_pool
@@ -185,7 +185,6 @@ executables: []
185
185
  extensions: []
186
186
  extra_rdoc_files: []
187
187
  files:
188
- - lib/lua/dist/get_graph_data.lua
189
188
  - lib/lua/dist/wafris_core.lua
190
189
  - lib/lua/src/get_time_buckets.lua
191
190
  - lib/lua/src/queries.lua
@@ -1,81 +0,0 @@
1
- -- Compiled from:
2
- -- src/get_time_buckets.lua
3
-
4
- -- Code was pulled from https://otland.net/threads/how-convert-timestamp-to-date-type.251657/
5
- -- An alternate solution is https://gist.github.com/markuman/e96d04139cd8acc33604
6
- local function get_time_bucket_from_timestamp(unix_time_milliseconds)
7
- local function calculate_years_number_of_days(yr)
8
- return (yr % 4 == 0 and (yr % 100 ~= 0 or yr % 400 == 0)) and 366 or 365
9
- end
10
-
11
- local function get_year_and_day_number(year, days)
12
- while days >= calculate_years_number_of_days(year) do
13
- days = days - calculate_years_number_of_days(year)
14
- year = year + 1
15
- end
16
- return year, days
17
- end
18
-
19
- local function get_month_and_month_day(days, year)
20
- local days_in_each_month = {
21
- 31,
22
- (calculate_years_number_of_days(year) == 366 and 29 or 28),
23
- 31,
24
- 30,
25
- 31,
26
- 30,
27
- 31,
28
- 31,
29
- 30,
30
- 31,
31
- 30,
32
- 31,
33
- }
34
-
35
- for month = 1, #days_in_each_month do
36
- if days - days_in_each_month[month] <= 0 then
37
- return month, days
38
- end
39
- days = days - days_in_each_month[month]
40
- end
41
- end
42
-
43
- local unix_time = unix_time_milliseconds / 1000
44
- local year = 1970
45
- local days = math.ceil(unix_time / 86400)
46
- local month = nil
47
-
48
- year, days = get_year_and_day_number(year, days)
49
- month, days = get_month_and_month_day(days, year)
50
- local hours = math.floor(unix_time / 3600 % 24)
51
- -- local minutes, seconds = math.floor(unix_time / 60 % 60), math.floor(unix_time % 60)
52
- -- hours = hours > 12 and hours - 12 or hours == 0 and 12 or hours
53
- return string.format("%04d-%02d-%02d-%02d", year, month, days, hours)
54
- end
55
-
56
- local function get_time_buckets(unix_time_milliseconds)
57
- local time_buckets = {}
58
-
59
- for i = 23, 0, -1 do
60
- table.insert(time_buckets, get_time_bucket_from_timestamp(unix_time_milliseconds - (1000 * 60 * 60 * i)))
61
- end
62
- return time_buckets
63
- end
64
-
65
- local function num_requests(time_bucket)
66
- local request_keys = redis.call("KEYS", "unique-requests:" .. time_bucket)
67
- redis.call("PFMERGE", "merged_unique-requests", unpack(request_keys))
68
- return redis.call("PFCOUNT", "merged_unique-requests")
69
- end
70
-
71
- local graph_data = {}
72
- local unix_time_milliseconds = ARGV[1]
73
- local time_buckets = get_time_buckets(unix_time_milliseconds)
74
- -- use the get_time_buckets method to get each time bucket and
75
- -- the associated count for that bucket
76
- for bucket in pairs(time_buckets) do
77
- table.insert(graph_data, time_buckets[bucket])
78
- table.insert(graph_data, num_requests(time_buckets[bucket]))
79
- end
80
-
81
- return graph_data