Skip to content

Commit

Permalink
add world-map example
Browse files Browse the repository at this point in the history
  • Loading branch information
superstes committed Oct 18, 2024
1 parent d443950 commit 33d5af4
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
visualization/*.json
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ By flagging clients originating from these sources you can achieve a nice securi

The databases created from the gathered data will be and stay open-source!

<a href="https://github.com/O-X-L/risk-db/blob/latest/visualization">
<img src="https://raw.githubusercontent.com/O-X-L/risk-db/refs/heads/latest/visualization/world_map_example.webp" alt="World Map Example" width="800"/>
</a>

----

## Contribute
Expand Down
37 changes: 37 additions & 0 deletions visualization/world_map.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/svg" href="https://files.oxl.at/img/oxl3_sm.png">

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/svg-pan-zoom.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/StephanWagner/[email protected]/dist/svgMap.min.js"></script>
<link href="https://cdn.jsdelivr.net/gh/StephanWagner/[email protected]/dist/svgMap.min.css" rel="stylesheet">
</head>
<body>
<!-- see: https://stephanwagner.me/create-world-map-charts-with-svgmap#svgMapDemoGDP -->
<div id="svgMap"></div>
<script>
// start test webserver: 'python3 world_map_test.py'
const RISK_DB_MAP_DATA = 'http://localhost:8000/world_map.json';

function createMap(resp) {
console.log(resp);
new svgMap(resp);
}

function fetchMapData() {
var http = new XMLHttpRequest();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
createMap(JSON.parse(this.responseText));
}
};
http.open("GET", RISK_DB_MAP_DATA, true);
http.send();
}
fetchMapData();
</script>
</body>
</html>
83 changes: 83 additions & 0 deletions visualization/world_map_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3

# data to visualize with svgmap: https://stephanwagner.me/create-world-map-charts-with-svgmap#svgMapDemoGDP

from argparse import ArgumentParser
from json import loads as json_loads
from json import dumps as json_dumps
from pathlib import Path

from maxminddb import open_database as mmdb_database

SRC_PATH = Path(__file__).resolve().parent
HIGHLIGHT_TOP_N = 20
CATEGORIES = ['all', 'bot', 'probe', 'rate', 'attack', 'crawler']

# todo: add change to last month
DATA = {
'targetElementID': 'svgMap',
'data': {
'applyData': 'all',
'data': {
'all': {
'name': 'Reported abuse originating from this country',
'format': '{0}',
'thousandSeparator': '.',
'thresholdMax': 2_000,
'thresholdMin': 500
},
'bot': {
'name': 'Reported bots',
'format': '{0}',
},
'probe': {
'name': 'Reported probes/scanners',
'format': '{0}',
},
'rate': {
'name': 'Reported rate-limit hits',
'format': '{0}',
},
'attack': {
'name': 'Reported attacks',
'format': '{0}',
},
'crawler': {
'name': 'Reported crawlers',
'format': '{0}',
},
},
'values': {},
}
}


def main():
with open(args.file, 'r', encoding='utf-8') as f:
raw = json_loads(f.read())

with mmdb_database(args.country_db) as m:
for asn, ips in raw.items():
for ip, reports in ips.items():
ip_md = m.get(ip)
if ip_md['country'] not in DATA['data']['values']:
DATA['data']['values'][ip_md['country']] = {c: 0 for c in CATEGORIES}

for c in CATEGORIES:
if c in reports:
DATA['data']['values'][ip_md['country']][c] += reports[c]

DATA['data']['values'] = dict(sorted(DATA['data']['values'].items(), key=lambda item: item[1]['all'], reverse=True))
with open(SRC_PATH / 'world_map.json', 'w', encoding='utf-8') as f:
top_country_values = list(DATA['data']['values'].values())
DATA['data']['data']['all']['thresholdMax'] = top_country_values[0]['all']
DATA['data']['data']['all']['thresholdMin'] = top_country_values[HIGHLIGHT_TOP_N]['all']
f.write(json_dumps(DATA, indent=4))


if __name__ == '__main__':
parser = ArgumentParser()
parser.add_argument('-f', '--file', help='JSON file to parse', default='risk_ip4_med.json')
parser.add_argument('-c', '--country-db', help='MMDB country data to use (IPInfo)', default='country_asn.mmdb')
args = parser.parse_args()
main()
Binary file added visualization/world_map_example.webp
Binary file not shown.
13 changes: 13 additions & 0 deletions visualization/world_map_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env python3

from http.server import HTTPServer, SimpleHTTPRequestHandler, test


class CORSRequestHandler (SimpleHTTPRequestHandler):
def end_headers (self):
self.send_header('Access-Control-Allow-Origin', '*')
SimpleHTTPRequestHandler.end_headers(self)


if __name__ == '__main__':
test(CORSRequestHandler, HTTPServer, port=8000)

0 comments on commit 33d5af4

Please sign in to comment.