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 +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
|