wafris 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/lua/dist/wafris_core.lua +19 -5
- data/lib/wafris/configuration.rb +0 -8
- data/lib/wafris/version.rb +1 -1
- data/lib/wafris.rb +15 -51
- metadata +2 -3
- data/lib/lua/dist/get_graph_data.lua +0 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2da3a1b92fba96e01f65433a9388d7dbeb8f24225b352e1958f392cd82fc8522
|
4
|
+
data.tar.gz: c8a72dcb1459454890d11d5ba0190f2b4a7f0d13cc63ce9d7038e87cb8ca7af7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
64
|
-
|
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
|
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,
|
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
|
-
|
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
|
data/lib/wafris/configuration.rb
CHANGED
data/lib/wafris/version.rb
CHANGED
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
|
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
|
-
|
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
|
-
|
84
|
-
|
60
|
+
def client_ip(request)
|
61
|
+
return request.ip if request.headers['x-forwarded-for'].nil?
|
85
62
|
|
86
|
-
|
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
|
-
|
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
|
-
|
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.
|
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-
|
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
|