Skip to content

Commit dcde524

Browse files
authored
Merge pull request #7 from GreyNoise-Intelligence/use-community-endpoint
Use community endpoint, cleanup auth log, fix stats script
2 parents 35d7a36 + f9c109d commit dcde524

File tree

7 files changed

+10063
-983
lines changed

7 files changed

+10063
-983
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-include env
1+
-include .env
22

33
CONTAINER := gn-fluentbit
44
WORKDIR := /app

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ This example watches reads a log file in and watches for new lines.
7474
[`conf/rewrite.conf`](https://github.com/GreyNoise-Intelligence/greynoise-fluentbit-lua/tree/main/conf/rewrite.conf)
7575

7676
This is the same as #2 except this leverages [rewrite_tag](https://docs.fluentbit.io/manual/pipeline/filters/rewrite-tag) filter to drop records.
77-
This config drops invalid IPv4 records, bogon address space, GreyNoise RIOT records, and GreyNoise Quick records.
77+
This config drops invalid IPv4 records, bogon address space, GreyNoise RIOT records, and GreyNoise Noise records.
7878
1. Run `make run-rewrite`
7979
1. Run `make stats` in another terminal to see metrics (note the drop rates)
8080

conf/parsers.conf

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
[PARSER]
22
Name regex
33
Format regex
4-
Regex /(?<host>(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/
4+
Regex /^(?<original_time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$/
5+
Time_Key original_time
6+
Time_Keep On
7+
Time_Format %b %d %H:%M:%S
58

69
[PARSER]
710
Name dummy

conf/rewrite.conf

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
[FILTER]
2424
Name rewrite_tag
2525
Match rewrite.*
26-
Rule $gn_quick ^(true)$ from.rewrite.gn_quick false
27-
Emitter_Name gn_quick
26+
Rule $gn_noise ^(true)$ from.rewrite.gn_noise false
27+
Emitter_Name gn_noise
2828

2929
[FILTER]
3030
Name rewrite_tag
@@ -44,8 +44,17 @@
4444
Rule $gn_invalid ^(true)$ from.rewrite.gn_invalid false
4545
Emitter_Name gn_invalid
4646

47+
[FILTER]
48+
Name record_modifier
49+
Match rewrite.*
50+
Remove_key gn_noise
51+
Remove_key gn_riot
52+
Remove_key gn_bogon
53+
Remove_key gn_invalid
54+
4755
[OUTPUT]
4856
Name file
49-
Format plain
57+
Format template
58+
Template {original_time} {host} {ident}[{pid}]: {message}
5059
Match rewrite.*
5160
Path /app/output

examples/auth.log

Lines changed: 10000 additions & 900 deletions
Large diffs are not rendered by default.

greynoise/src/greynoise.lua

Lines changed: 28 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ local cache = lru.new(cache_size)
2222

2323
local useragent = string.format('GreyNoiseFluentBit/%s', greynoise._version)
2424
local auth = requests.HTTPBasicAuth('none', gn_api_key)
25+
2526
local headers = {['User-Agent'] = useragent, ['Accept'] = 'application/json'}
2627

2728
local function has_value(tab, val)
@@ -41,7 +42,7 @@ end
4142
-- @table record
4243
-- @return table
4344
local function convert_record_bools(record)
44-
local gn_keys = {"gn_quick", "gn_riot", "gn_bogon", "gn_invalid"}
45+
local gn_keys = {"gn_noise", "gn_riot", "gn_bogon", "gn_invalid"}
4546
for k, v in pairs(record) do
4647
if has_value(gn_keys, k) then
4748
if (v == true) then record[k] = "true" end
@@ -100,60 +101,38 @@ local function check_ip(record, ip)
100101
return new_record
101102
end
102103

103-
-- Lookup a source_ip against `/v2/riot/` endpoint
104+
-- Lookup a source_ip against `/v3/community` endpoint
104105
--
105106
-- @string ip
106-
-- @return boolean
107-
local function gn_riot_check(ip)
108-
local url = string.format('https://api.greynoise.io/v2/riot/%s', ip)
107+
-- @return boolean, boolean
108+
local function gn_community_lookup(ip)
109+
local url = string.format('https://api.greynoise.io/v3/community/%s', ip)
109110
local response = requests.get {url, headers = headers, auth = auth}
110111
if (not response) then
111-
log.warn('no response from /v2/riot/ endpoint')
112-
return nil
112+
log.warn('no response from /v3/community endpoint')
113+
return nil, nil
113114
end
114115
if response.status_code == 200 then
115116
local body, error = response.json()
116117
if error ~= nil then
117118
log.warn('%v', error)
118-
return nil
119+
return nil, nil
119120
end
120-
if body.riot == true then return true end
121-
return false
122-
elseif response.status_code == 404 then
123-
-- RIOT uses a soft 404 to represent that resource is not in RIOT.
124-
-- This interface differs from the `v2/noise/quick` endpoint that returns 200 for all requested IPs.
125-
return false
121+
return body.noise, body.riot
126122
end
127-
128-
log.warn(string.format('Received %d status code from %s',
129-
response.status_code, url))
130-
return nil
131-
end
132-
133-
-- Lookup a source_ip against `/v2/noise/quick/` endpoint
134-
--
135-
-- @string ip
136-
-- @return boolean
137-
local function gn_quick_check(ip)
138-
local url = string.format('https://api.greynoise.io/v2/noise/quick/%s', ip)
139-
local response = requests.get {url, headers = headers, auth = auth}
140-
if (not response) then
141-
log.warn('no response from /v2/noise/quick/ endpoint')
142-
return nil
143-
end
144-
if response.status_code == 200 then
145-
local body, error = response.json()
146-
if error ~= nil then
147-
log.warn('%v', error)
148-
return nil
149-
end
150-
if body.noise == true then return true end
151-
return false
123+
if response.status_code == 404 then
124+
local body, error = response.json()
125+
if error ~= nil then
126+
log.warn('%v', error)
127+
return nil, nil
128+
end
129+
log.debug(string.format('%s, %s',url, body.message))
130+
return false, false
152131
end
153132

154133
log.warn(string.format('Received %d status code from %s',
155134
response.status_code, url))
156-
return nil
135+
return nil, nil
157136
end
158137

159138
-- Main filter handler
@@ -163,18 +142,19 @@ end
163142
-- @table record
164143
-- @return number, number, table
165144
function gn_filter(_, timestamp, record)
166-
local ip = record[ip_field]
145+
-- Extract IPv4 from message
146+
local ip = record[ip_field]:match("(%d+%.%d+%.%d+%.%d+)")
167147
local new_record = record
168148
new_record.gn_riot = nil
169-
new_record.gn_quick = nil
149+
new_record.gn_noise = nil
170150
new_record.gn_invalid = nil
171151
new_record.gn_bogon = nil
172152
if ip then
173153
local cache_record = cache:get(ip)
174154
if cache_record then
175155
log.debug(string.format('cache hit: %s', ip))
176156
new_record.gn_riot = cache_record['r']
177-
new_record.gn_quick = cache_record['q']
157+
new_record.gn_noise = cache_record['q']
178158
new_record.gn_invalid = cache_record['i']
179159
new_record.gn_bogon = cache_record['b']
180160
local final_record = convert_record_bools(new_record)
@@ -184,11 +164,13 @@ function gn_filter(_, timestamp, record)
184164
log.debug(string.format('lookup: %s', ip))
185165
if (not validated_record.gn_invalid and not validated_record.gn_bogon) then
186166
-- Make GN API calls for valid non-bogon IPv4 records
187-
validated_record.gn_riot = gn_riot_check(ip)
188-
validated_record.gn_quick = gn_quick_check(ip)
167+
validated_record.gn_noise, validated_record.gn_riot = gn_community_lookup(ip)
168+
if not validated_record.gn_noise == nil or not validated_record.gn_riot == nil then
169+
return -1, timestamp, record
170+
end
189171
cache:set(ip, {
190172
r = validated_record.gn_riot,
191-
q = validated_record.gn_quick,
173+
q = validated_record.gn_noise,
192174
i = validated_record.gn_invalid,
193175
b = validated_record.gn_bogon
194176
})

scripts/stats.sh

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,25 @@ then
1111
exit 1;
1212
fi
1313

14-
process_raw_log () {
15-
log=$1
16-
echo "## Stats for: $log"
17-
total=$(cat $log | wc -l)
18-
quick=$(jq -c '. | select(.gn_quick == true)' $log | wc -l)
19-
riot=$(jq -c '. | select(.gn_riot == true)' $log | wc -l)
20-
bogon=$(jq -c '. | select(.gn_bogon == true)' $log | wc -l)
21-
invalid=$(jq -c '. | select(.gn_invalid == true)' $log | wc -l)
22-
noise_percent=$(echo "scale=4; $quick/$total" | bc -l)
23-
riot_percent=$(echo "scale=4; $riot/$total" | bc -l)
24-
bogon_percent=$(echo "scale=4; $bogon/$total" | bc -l)
25-
invalid_percent=$(echo "scale=4; $invalid/$total" | bc -l)
26-
27-
echo "--Line Counts--"
28-
echo "Total: $total"
29-
echo "Noise: $quick"
30-
echo "RIOT: $riot"
31-
echo "Bogon: $bogon"
32-
echo "Invalid: $invalid"
33-
echo "--Percentages--"
34-
echo "Noise: $noise_percent"
35-
echo "RIOT: $riot_percent"
36-
echo "Bogon: $bogon_percent"
37-
echo "Invalid: $invalid_percent"
38-
printf "\n"
39-
}
40-
4114
get_fb_stats () {
4215
curl -s http://127.0.0.1:2020/api/v1/metrics | jq '.input'
4316
}
4417

18+
res=$(get_fb_stats)
19+
records=$(echo $res | jq '.rewrite_input.records')
20+
noise=$(echo $res | jq '.gn_noise.records')
21+
riot=$(echo $res | jq '.gn_riot.records')
22+
bogon=$(echo $res | jq '.gn_bogon.records')
23+
invalid=$(echo $res | jq '.gn_invalid.records')
24+
25+
total_invalid=$(echo "scale=4; $bogon + $invalid" | bc -l)
26+
total_noise=$(echo "scale=4; $noise + $riot" | bc -l)
27+
noise_percentage=$(echo "scale=2; $total_noise/$records" | bc -l | cut -c 2-)
4528

46-
get_fb_stats
47-
# for log in output/*; do
48-
# process_log $log
49-
# done
29+
echo "GreyNoise Fluentbit Filter Stats"
30+
echo "================================"
31+
echo ""
32+
echo "Total Records: ${records}"
33+
echo "All Noise Records: ${total_noise} (Noise, RIOT)"
34+
echo "All Invalid Records: ${total_invalid} (Bogon, Invalid)"
35+
echo "Noise Percentage: ${noise_percentage}%"

0 commit comments

Comments
 (0)