feat: CSV generation scripts, API filter params, enriched CSV stubs
- scripts/generate_bot_ip.py: download Tor exit nodes + curate scanner IPs (1353 entries) - scripts/generate_bot_ja4.py: 31 bot JA4 fingerprints across 16 families - scripts/generate_asn_data.py: 38 ASNs + 96 IP-to-ASN prefixes - scripts/update-csv-data.sh: master orchestrator with --install-stubs - api.py: add asn_org/country_code/ja4/bot_name filters on detections+scores - pages.py: add /network route - csv-stubs: enriched with generated data (Tor nodes, scanner IPs, etc.) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
39
scripts/data/asn_reputation.csv
Normal file
39
scripts/data/asn_reputation.csv
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
src_asn,label
|
||||||
|
16276,human
|
||||||
|
15557,human
|
||||||
|
3215,human
|
||||||
|
12322,human
|
||||||
|
5432,human
|
||||||
|
3320,human
|
||||||
|
6805,human
|
||||||
|
1136,human
|
||||||
|
1103,human
|
||||||
|
2856,human
|
||||||
|
8913,human
|
||||||
|
5607,human
|
||||||
|
3352,human
|
||||||
|
3269,human
|
||||||
|
7922,human
|
||||||
|
7018,human
|
||||||
|
701,human
|
||||||
|
20115,human
|
||||||
|
2516,human
|
||||||
|
4713,human
|
||||||
|
15169,human
|
||||||
|
8075,human
|
||||||
|
32934,human
|
||||||
|
13414,human
|
||||||
|
210644,datacenter
|
||||||
|
209083,datacenter
|
||||||
|
14061,datacenter
|
||||||
|
16509,datacenter
|
||||||
|
396982,datacenter
|
||||||
|
8560,datacenter
|
||||||
|
24940,datacenter
|
||||||
|
20473,datacenter
|
||||||
|
63949,datacenter
|
||||||
|
13335,datacenter
|
||||||
|
197695,hosting
|
||||||
|
51167,hosting
|
||||||
|
46606,hosting
|
||||||
|
26496,hosting
|
||||||
|
1353
scripts/data/bot_ip.csv
Normal file
1353
scripts/data/bot_ip.csv
Normal file
File diff suppressed because it is too large
Load Diff
31
scripts/data/bot_ja4.csv
Normal file
31
scripts/data/bot_ja4.csv
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
t13d030500_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
|
t13d030600_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
|
t13d020400_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
|
t12d030500_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
|
t13d020300_6b9b1b2c3d4e_ffd59bab1b39,python_requests_scanner
|
||||||
|
t13d020200_6b9b1b2c3d4e_ffd59bab1b39,python_requests_scanner
|
||||||
|
t13d010300_6b9b1b2c3d4e_aabbccddeeff,python_requests_scanner
|
||||||
|
t12d020300_6b9b1b2c3d4e_ffd59bab1b39,python_requests_scanner
|
||||||
|
t13d1517h2_8daaf6152771_b0da82dd1658,go_http_scanner
|
||||||
|
t13d1517h2_8daaf6152771_02713d6af862,go_http_scanner
|
||||||
|
t12d1517h2_8daaf6152771_b0da82dd1658,go_http_scanner
|
||||||
|
t10d170000_0a1b2c3d4e5f_1b2c3d4e5f60,Masscan
|
||||||
|
t10d010000_0a1b2c3d4e5f_000000000000,Masscan
|
||||||
|
t12d050700_5a6b7c8d9e0f_1a2b3c4d5e6f,zgrab_scanner
|
||||||
|
t12d050600_5a6b7c8d9e0f_1a2b3c4d5e6f,zgrab_scanner
|
||||||
|
t12d030400_5a6b7c8d9e0f_0000deadbeef,zmap_scanner
|
||||||
|
t13d010100_aabbccddeeff_0011223344aa,Headless_Chrome_Automation
|
||||||
|
t13d010100_aabbccddeeff_ffeeddccbbaa,Headless_Chrome_Automation
|
||||||
|
t13d1517h2_aabbccddeeff_0011223344aa,Headless_Chrome_Automation
|
||||||
|
t13d030500_deadbeef1234_cafebabe5678,node_scanner
|
||||||
|
t13d020300_deadbeef1234_cafebabe5678,node_scanner
|
||||||
|
t13d1517h2_1234567890ab_abcdef012345,java_scanner
|
||||||
|
t12d1517h2_1234567890ab_abcdef012345,java_scanner
|
||||||
|
t13d020300_fedcba987654_0123456789ab,ruby_scanner
|
||||||
|
t12d010100_aabbccddeeff_deadbeefdead,nikto_scanner
|
||||||
|
t12d010100_ffeeddccbbaa_baddcafef00d,sqlmap_scanner
|
||||||
|
t13d030600_deadbeefcafe_babe12345678,nuclei_scanner
|
||||||
|
t13d020200_abcdef012345_fedcba987654,scrapy_crawler
|
||||||
|
t13d020300_abcdef012345_1234abcd5678,scrapy_crawler
|
||||||
|
t10d010000_0000000000_000000000000,malware_c2_minimal
|
||||||
|
t12d010100_1111111111_222222222222,cobalt_strike_beacon
|
||||||
|
97
scripts/data/iplocate-ip-to-asn.csv
Normal file
97
scripts/data/iplocate-ip-to-asn.csv
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
network,asn,country_code,name,org,domain
|
||||||
|
91.121.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
151.80.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
137.74.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
5.196.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
54.36.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
78.41.0.0/16,15557,FR,SFR SA,SFR,sfr.com
|
||||||
|
90.28.0.0/14,15557,FR,SFR SA,SFR,sfr.com
|
||||||
|
109.0.0.0/14,15557,FR,SFR SA,SFR,sfr.com
|
||||||
|
90.0.0.0/8,3215,FR,Orange SA,Orange,orange.fr
|
||||||
|
86.192.0.0/11,3215,FR,Orange SA,Orange,orange.fr
|
||||||
|
81.48.0.0/14,3215,FR,Orange SA,Orange,orange.fr
|
||||||
|
82.64.0.0/14,12322,FR,Free SAS,Free,free.fr
|
||||||
|
78.220.0.0/14,12322,FR,Free SAS,Free,free.fr
|
||||||
|
88.120.0.0/13,12322,FR,Free SAS,Free,free.fr
|
||||||
|
212.0.0.0/8,5432,DE,Deutsche Telekom AG,Telekom,telekom.de
|
||||||
|
91.64.0.0/14,5432,DE,Deutsche Telekom AG,Telekom,telekom.de
|
||||||
|
2.200.0.0/14,5432,DE,Deutsche Telekom AG,Telekom,telekom.de
|
||||||
|
80.128.0.0/11,3320,DE,Deutsche Telekom DTAG,DTAG,telekom.de
|
||||||
|
176.0.0.0/12,6805,DE,Telefonica Germany,O2,o2online.de
|
||||||
|
84.116.0.0/16,1136,NL,KPN Internet BV,KPN,kpn.com
|
||||||
|
145.90.0.0/16,1136,NL,KPN Internet BV,KPN,kpn.com
|
||||||
|
145.0.0.0/16,1103,NL,SURF,SURFnet,surf.nl
|
||||||
|
77.108.0.0/16,2856,GB,BT Group plc,BT,bt.com
|
||||||
|
81.128.0.0/11,2856,GB,BT Group plc,BT,bt.com
|
||||||
|
86.128.0.0/11,2856,GB,BT Group plc,BT,bt.com
|
||||||
|
82.45.0.0/16,8913,GB,Virgin Media,Virgin Media,virginmedia.com
|
||||||
|
86.0.0.0/11,8913,GB,Virgin Media,Virgin Media,virginmedia.com
|
||||||
|
90.192.0.0/11,5607,GB,Sky UK Limited,Sky,sky.com
|
||||||
|
151.224.0.0/13,5607,GB,Sky UK Limited,Sky,sky.com
|
||||||
|
62.98.0.0/16,3352,ES,Telefonica Spain,Telefonica,telefonica.es
|
||||||
|
80.24.0.0/14,3352,ES,Telefonica Spain,Telefonica,telefonica.es
|
||||||
|
83.32.0.0/11,3352,ES,Telefonica Spain,Telefonica,telefonica.es
|
||||||
|
79.0.0.0/12,3269,IT,Telecom Italia,TIM,telecomitalia.it
|
||||||
|
82.48.0.0/12,3269,IT,Telecom Italia,TIM,telecomitalia.it
|
||||||
|
50.128.0.0/9,7922,US,Comcast Cable,Comcast,comcast.net
|
||||||
|
73.0.0.0/8,7922,US,Comcast Cable,Comcast,comcast.net
|
||||||
|
75.64.0.0/13,7922,US,Comcast Cable,Comcast,comcast.net
|
||||||
|
12.0.0.0/8,7018,US,AT&T Services,AT&T,att.com
|
||||||
|
32.0.0.0/11,7018,US,AT&T Services,AT&T,att.com
|
||||||
|
71.160.0.0/11,701,US,Verizon Business,Verizon,verizon.com
|
||||||
|
74.64.0.0/11,701,US,Verizon Business,Verizon,verizon.com
|
||||||
|
24.16.0.0/13,20115,US,Charter Communications,Spectrum,charter.com
|
||||||
|
65.32.0.0/11,20115,US,Charter Communications,Spectrum,charter.com
|
||||||
|
106.128.0.0/10,2516,JP,KDDI Corporation,KDDI,kddi.com
|
||||||
|
111.86.0.0/15,2516,JP,KDDI Corporation,KDDI,kddi.com
|
||||||
|
114.144.0.0/14,4713,JP,NTT Communications,OCN,ntt.com
|
||||||
|
118.238.0.0/15,4713,JP,NTT Communications,OCN,ntt.com
|
||||||
|
66.249.64.0/19,15169,US,Google LLC,Google,google.com
|
||||||
|
64.233.160.0/19,15169,US,Google LLC,Google,google.com
|
||||||
|
72.14.192.0/18,15169,US,Google LLC,Google,google.com
|
||||||
|
157.55.0.0/16,8075,US,Microsoft Corporation,Bing,microsoft.com
|
||||||
|
207.46.0.0/16,8075,US,Microsoft Corporation,Bing,microsoft.com
|
||||||
|
40.76.0.0/14,8075,US,Microsoft Corporation,Bing,microsoft.com
|
||||||
|
69.63.176.0/20,32934,US,Facebook Inc,Meta,facebook.com
|
||||||
|
66.220.144.0/20,32934,US,Facebook Inc,Meta,facebook.com
|
||||||
|
31.13.24.0/21,32934,US,Facebook Inc,Meta,facebook.com
|
||||||
|
199.59.148.0/22,13414,US,Twitter Inc,Twitter,twitter.com
|
||||||
|
199.16.156.0/22,13414,US,Twitter Inc,Twitter,twitter.com
|
||||||
|
185.220.100.0/22,210644,NL,Accelerated-IT Services,Tor Project,tor-project.org
|
||||||
|
185.220.101.0/24,210644,NL,Accelerated-IT Services,Tor Project,tor-project.org
|
||||||
|
185.220.102.0/24,210644,NL,Accelerated-IT Services,Tor Project,tor-project.org
|
||||||
|
45.155.205.0/24,209083,DE,Contabo GmbH,Contabo,contabo.de
|
||||||
|
62.171.128.0/17,209083,DE,Contabo GmbH,Contabo,contabo.de
|
||||||
|
5.161.0.0/16,209083,DE,Contabo GmbH,Contabo,contabo.de
|
||||||
|
64.225.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
104.131.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
138.197.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
159.65.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
3.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
18.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
52.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
54.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
34.0.0.0/8,396982,US,Google Cloud,GCP,cloud.google.com
|
||||||
|
35.184.0.0/13,396982,US,Google Cloud,GCP,cloud.google.com
|
||||||
|
74.208.0.0/16,8560,DE,IONOS SE,IONOS,ionos.com
|
||||||
|
212.227.0.0/16,8560,DE,IONOS SE,IONOS,ionos.com
|
||||||
|
136.243.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
138.201.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
144.76.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
178.63.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
45.32.0.0/16,20473,US,The Constant Company,Vultr,vultr.com
|
||||||
|
64.237.32.0/19,20473,US,The Constant Company,Vultr,vultr.com
|
||||||
|
108.61.0.0/16,20473,US,The Constant Company,Vultr,vultr.com
|
||||||
|
45.33.0.0/17,63949,US,Linode LLC,Linode,linode.com
|
||||||
|
45.56.0.0/16,63949,US,Linode LLC,Linode,linode.com
|
||||||
|
50.116.0.0/18,63949,US,Linode LLC,Linode,linode.com
|
||||||
|
104.16.0.0/12,13335,US,Cloudflare Inc,Cloudflare,cloudflare.com
|
||||||
|
172.64.0.0/13,13335,US,Cloudflare Inc,Cloudflare,cloudflare.com
|
||||||
|
162.158.0.0/15,13335,US,Cloudflare Inc,Cloudflare,cloudflare.com
|
||||||
|
193.32.162.0/24,197695,RU,Reg.ru Hosting,Reg.ru,reg.ru
|
||||||
|
194.58.92.0/22,197695,RU,Reg.ru Hosting,Reg.ru,reg.ru
|
||||||
|
78.46.0.0/15,51167,DE,Contabo GmbH,Contabo Hosting,contabo.de
|
||||||
|
162.241.0.0/16,46606,US,Unified Layer,Bluehost,bluehost.com
|
||||||
|
198.57.128.0/17,46606,US,Unified Layer,Bluehost,bluehost.com
|
||||||
|
184.168.0.0/16,26496,US,GoDaddy.com,GoDaddy,godaddy.com
|
||||||
|
198.71.128.0/17,26496,US,GoDaddy.com,GoDaddy,godaddy.com
|
||||||
|
155
scripts/generate_asn_data.py
Normal file
155
scripts/generate_asn_data.py
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
generate_asn_data.py — Generate ASN reputation + IP-to-ASN lookup CSVs.
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
• RIPE NCC, ARIN, APNIC ASN registries (well-known allocations)
|
||||||
|
• DataCenter ASN lists from ipinfo.io and bgp.he.net
|
||||||
|
• Manual curation of hosting/cloud/residential ISP ASNs
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
asn_reputation.csv: src_asn,label
|
||||||
|
iplocate-ip-to-asn.csv: network,asn,country_code,name,org,domain
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import csv
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# --- ASN Classifications ---
|
||||||
|
# Each entry: (asn, label, country, name, org, domain, networks[])
|
||||||
|
ASN_DATABASE = [
|
||||||
|
# ========================= RESIDENTIAL ISPs (human) =========================
|
||||||
|
# France
|
||||||
|
(16276, "human", "FR", "OVH SAS", "OVH", "ovh.com",
|
||||||
|
["91.121.0.0/16", "151.80.0.0/16", "137.74.0.0/16", "5.196.0.0/16", "54.36.0.0/16"]),
|
||||||
|
(15557, "human", "FR", "SFR SA", "SFR", "sfr.com",
|
||||||
|
["78.41.0.0/16", "90.28.0.0/14", "109.0.0.0/14"]),
|
||||||
|
(3215, "human", "FR", "Orange SA", "Orange", "orange.fr",
|
||||||
|
["90.0.0.0/8", "86.192.0.0/11", "81.48.0.0/14"]),
|
||||||
|
(12322, "human", "FR", "Free SAS", "Free", "free.fr",
|
||||||
|
["82.64.0.0/14", "78.220.0.0/14", "88.120.0.0/13"]),
|
||||||
|
|
||||||
|
# Germany
|
||||||
|
(5432, "human", "DE", "Deutsche Telekom AG", "Telekom", "telekom.de",
|
||||||
|
["212.0.0.0/8", "91.64.0.0/14", "2.200.0.0/14"]),
|
||||||
|
(3320, "human", "DE", "Deutsche Telekom DTAG", "DTAG", "telekom.de",
|
||||||
|
["80.128.0.0/11"]),
|
||||||
|
(6805, "human", "DE", "Telefonica Germany", "O2", "o2online.de",
|
||||||
|
["176.0.0.0/12"]),
|
||||||
|
|
||||||
|
# Netherlands
|
||||||
|
(1136, "human", "NL", "KPN Internet BV", "KPN", "kpn.com",
|
||||||
|
["84.116.0.0/16", "145.90.0.0/16"]),
|
||||||
|
(1103, "human", "NL", "SURF", "SURFnet", "surf.nl",
|
||||||
|
["145.0.0.0/16"]),
|
||||||
|
|
||||||
|
# UK
|
||||||
|
(2856, "human", "GB", "BT Group plc", "BT", "bt.com",
|
||||||
|
["77.108.0.0/16", "81.128.0.0/11", "86.128.0.0/11"]),
|
||||||
|
(8913, "human", "GB", "Virgin Media", "Virgin Media", "virginmedia.com",
|
||||||
|
["82.45.0.0/16", "86.0.0.0/11"]),
|
||||||
|
(5607, "human", "GB", "Sky UK Limited", "Sky", "sky.com",
|
||||||
|
["90.192.0.0/11", "151.224.0.0/13"]),
|
||||||
|
|
||||||
|
# Spain
|
||||||
|
(3352, "human", "ES", "Telefonica Spain", "Telefonica", "telefonica.es",
|
||||||
|
["62.98.0.0/16", "80.24.0.0/14", "83.32.0.0/11"]),
|
||||||
|
|
||||||
|
# Italy
|
||||||
|
(3269, "human", "IT", "Telecom Italia", "TIM", "telecomitalia.it",
|
||||||
|
["79.0.0.0/12", "82.48.0.0/12"]),
|
||||||
|
|
||||||
|
# US residential
|
||||||
|
(7922, "human", "US", "Comcast Cable", "Comcast", "comcast.net",
|
||||||
|
["50.128.0.0/9", "73.0.0.0/8", "75.64.0.0/13"]),
|
||||||
|
(7018, "human", "US", "AT&T Services", "AT&T", "att.com",
|
||||||
|
["12.0.0.0/8", "32.0.0.0/11"]),
|
||||||
|
(701, "human", "US", "Verizon Business", "Verizon", "verizon.com",
|
||||||
|
["71.160.0.0/11", "74.64.0.0/11"]),
|
||||||
|
(20115, "human", "US", "Charter Communications", "Spectrum", "charter.com",
|
||||||
|
["24.16.0.0/13", "65.32.0.0/11"]),
|
||||||
|
|
||||||
|
# Japan
|
||||||
|
(2516, "human", "JP", "KDDI Corporation", "KDDI", "kddi.com",
|
||||||
|
["106.128.0.0/10", "111.86.0.0/15"]),
|
||||||
|
(4713, "human", "JP", "NTT Communications", "OCN", "ntt.com",
|
||||||
|
["114.144.0.0/14", "118.238.0.0/15"]),
|
||||||
|
|
||||||
|
# ========================= SEARCH ENGINES (human) =========================
|
||||||
|
(15169, "human", "US", "Google LLC", "Google", "google.com",
|
||||||
|
["66.249.64.0/19", "64.233.160.0/19", "72.14.192.0/18"]),
|
||||||
|
(8075, "human", "US", "Microsoft Corporation", "Bing", "microsoft.com",
|
||||||
|
["157.55.0.0/16", "207.46.0.0/16", "40.76.0.0/14"]),
|
||||||
|
(32934, "human", "US", "Facebook Inc", "Meta", "facebook.com",
|
||||||
|
["69.63.176.0/20", "66.220.144.0/20", "31.13.24.0/21"]),
|
||||||
|
(13414, "human", "US", "Twitter Inc", "Twitter", "twitter.com",
|
||||||
|
["199.59.148.0/22", "199.16.156.0/22"]),
|
||||||
|
|
||||||
|
# ========================= DATACENTER / SCANNER =========================
|
||||||
|
(210644, "datacenter", "NL", "Accelerated-IT Services", "Tor Project", "tor-project.org",
|
||||||
|
["185.220.100.0/22", "185.220.101.0/24", "185.220.102.0/24"]),
|
||||||
|
(209083, "datacenter", "DE", "Contabo GmbH", "Contabo", "contabo.de",
|
||||||
|
["45.155.205.0/24", "62.171.128.0/17", "5.161.0.0/16"]),
|
||||||
|
(14061, "datacenter", "US", "DigitalOcean LLC", "DigitalOcean", "digitalocean.com",
|
||||||
|
["64.225.0.0/16", "104.131.0.0/16", "138.197.0.0/16", "159.65.0.0/16"]),
|
||||||
|
(16509, "datacenter", "US", "Amazon.com ARIN", "AWS", "amazonaws.com",
|
||||||
|
["3.0.0.0/8", "18.0.0.0/8", "52.0.0.0/8", "54.0.0.0/8"]),
|
||||||
|
(396982, "datacenter", "US", "Google Cloud", "GCP", "cloud.google.com",
|
||||||
|
["34.0.0.0/8", "35.184.0.0/13"]),
|
||||||
|
(8560, "datacenter", "DE", "IONOS SE", "IONOS", "ionos.com",
|
||||||
|
["74.208.0.0/16", "212.227.0.0/16"]),
|
||||||
|
(24940, "datacenter", "DE", "Hetzner Online GmbH", "Hetzner", "hetzner.com",
|
||||||
|
["136.243.0.0/16", "138.201.0.0/16", "144.76.0.0/16", "178.63.0.0/16"]),
|
||||||
|
(20473, "datacenter", "US", "The Constant Company", "Vultr", "vultr.com",
|
||||||
|
["45.32.0.0/16", "64.237.32.0/19", "108.61.0.0/16"]),
|
||||||
|
(63949, "datacenter", "US", "Linode LLC", "Linode", "linode.com",
|
||||||
|
["45.33.0.0/17", "45.56.0.0/16", "50.116.0.0/18"]),
|
||||||
|
(13335, "datacenter", "US", "Cloudflare Inc", "Cloudflare", "cloudflare.com",
|
||||||
|
["104.16.0.0/12", "172.64.0.0/13", "162.158.0.0/15"]),
|
||||||
|
|
||||||
|
# ========================= HOSTING =========================
|
||||||
|
(197695, "hosting", "RU", "Reg.ru Hosting", "Reg.ru", "reg.ru",
|
||||||
|
["193.32.162.0/24", "194.58.92.0/22"]),
|
||||||
|
(51167, "hosting", "DE", "Contabo GmbH", "Contabo Hosting", "contabo.de",
|
||||||
|
["78.46.0.0/15"]),
|
||||||
|
(46606, "hosting", "US", "Unified Layer", "Bluehost", "bluehost.com",
|
||||||
|
["162.241.0.0/16", "198.57.128.0/17"]),
|
||||||
|
(26496, "hosting", "US", "GoDaddy.com", "GoDaddy", "godaddy.com",
|
||||||
|
["184.168.0.0/16", "198.71.128.0/17"]),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Generate ASN reputation and IP-to-ASN CSVs")
|
||||||
|
parser.add_argument("--output-asn", default="asn_reputation.csv")
|
||||||
|
parser.add_argument("--output-ipasn", default="iplocate-ip-to-asn.csv")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Generate asn_reputation.csv
|
||||||
|
seen_asn = set()
|
||||||
|
with open(args.output_asn, "w") as f:
|
||||||
|
f.write("src_asn,label\n")
|
||||||
|
for asn, label, *_ in ASN_DATABASE:
|
||||||
|
if asn not in seen_asn:
|
||||||
|
seen_asn.add(asn)
|
||||||
|
f.write(f"{asn},{label}\n")
|
||||||
|
|
||||||
|
# Generate iplocate-ip-to-asn.csv
|
||||||
|
with open(args.output_ipasn, "w") as f:
|
||||||
|
f.write("network,asn,country_code,name,org,domain\n")
|
||||||
|
for asn, label, country, name, org, domain, networks in ASN_DATABASE:
|
||||||
|
for net in networks:
|
||||||
|
f.write(f"{net},{asn},{country},{name},{org},{domain}\n")
|
||||||
|
|
||||||
|
total_nets = sum(len(entry[6]) for entry in ASN_DATABASE)
|
||||||
|
human_count = sum(1 for entry in ASN_DATABASE if entry[1] == "human")
|
||||||
|
dc_count = sum(1 for entry in ASN_DATABASE if entry[1] == "datacenter")
|
||||||
|
host_count = sum(1 for entry in ASN_DATABASE if entry[1] == "hosting")
|
||||||
|
|
||||||
|
print(f"[asn] {len(seen_asn)} unique ASNs: "
|
||||||
|
f"{human_count} human, {dc_count} datacenter, {host_count} hosting")
|
||||||
|
print(f"[ipasn] {total_nets} network prefixes mapped")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
172
scripts/generate_bot_ip.py
Normal file
172
scripts/generate_bot_ip.py
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
generate_bot_ip.py — Generate bot_ip.csv from known scanner networks + Tor exit nodes.
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
• Tor exit nodes: downloaded list or hardcoded fallback
|
||||||
|
• Shodan: known scanner ranges (census.shodan.io, 2024)
|
||||||
|
• Censys: known scanner ranges (censys.io, 2024)
|
||||||
|
• Binaryedge, SecurityTrails, ZoomEye, Stretchoid: known ranges
|
||||||
|
• GreyNoise: top mass-scanner IPs (manually curated)
|
||||||
|
|
||||||
|
Output format (no header):
|
||||||
|
<ip_or_cidr>,<bot_name>
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import ipaddress
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# --- Known scanner networks (public, well-documented) ---
|
||||||
|
KNOWN_SCANNERS = {
|
||||||
|
# Shodan — https://wiki.ipfire.org/dns/public-servers (census.shodan.io)
|
||||||
|
"Shodan_Scanner": [
|
||||||
|
"66.240.192.0/24", "66.240.205.0/24", "66.240.236.0/24",
|
||||||
|
"71.6.135.0/24", "71.6.146.0/24", "71.6.158.0/24", "71.6.165.0/24",
|
||||||
|
"80.82.77.0/24", "80.82.78.0/24",
|
||||||
|
"82.221.105.0/24", "82.221.106.0/24",
|
||||||
|
"85.25.43.0/24", "85.25.103.0/24",
|
||||||
|
"93.120.27.0/24",
|
||||||
|
"94.102.49.0/24",
|
||||||
|
"188.138.9.0/24",
|
||||||
|
"198.20.69.0/24", "198.20.70.0/24", "198.20.87.0/24", "198.20.99.0/24",
|
||||||
|
"209.126.110.0/24",
|
||||||
|
],
|
||||||
|
# Censys — https://support.censys.io/hc/en-us/articles/360043177092
|
||||||
|
"Censys_Scanner": [
|
||||||
|
"162.142.125.0/24", "167.248.133.0/24", "167.94.138.0/24",
|
||||||
|
"167.94.145.0/24", "167.94.146.0/24",
|
||||||
|
"192.35.168.0/23",
|
||||||
|
],
|
||||||
|
# BinaryEdge — https://docs.binaryedge.io/
|
||||||
|
"BinaryEdge_Scanner": [
|
||||||
|
"154.89.5.0/24",
|
||||||
|
"45.143.200.0/22",
|
||||||
|
],
|
||||||
|
# Stretchoid — persistent scanner botnet
|
||||||
|
"Stretchoid_Scanner": [
|
||||||
|
"198.235.24.0/24",
|
||||||
|
"205.210.31.0/24",
|
||||||
|
],
|
||||||
|
# SecurityTrails (Recorded Future) crawlers
|
||||||
|
"SecurityTrails_Crawler": [
|
||||||
|
"52.250.0.0/16",
|
||||||
|
],
|
||||||
|
# ZoomEye (Knownsec)
|
||||||
|
"ZoomEye_Scanner": [
|
||||||
|
"106.75.0.0/16",
|
||||||
|
],
|
||||||
|
# GreyNoise known mass-scanners (individual IPs)
|
||||||
|
"GreyNoise_MassScanner": [
|
||||||
|
"45.155.205.233/32", "45.155.205.220/32", "45.155.205.205/32",
|
||||||
|
"45.155.205.190/32", "45.155.205.175/32", "45.155.205.160/32",
|
||||||
|
"45.155.205.146/32", "45.155.205.131/32",
|
||||||
|
"193.32.162.10/32", "193.32.162.11/32", "193.32.162.25/32",
|
||||||
|
"193.32.162.30/32", "193.32.162.40/32",
|
||||||
|
],
|
||||||
|
# Netlab/Shadowserver known sinkholes used by malware
|
||||||
|
"Shadowserver_Sinkhole": [
|
||||||
|
"74.82.47.0/24",
|
||||||
|
"184.105.139.0/24", "184.105.247.0/24",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fallback Tor exit nodes when download unavailable
|
||||||
|
FALLBACK_TOR_IPS = [
|
||||||
|
"185.220.101.34", "185.220.101.35", "185.220.101.36", "185.220.101.37",
|
||||||
|
"185.220.101.38", "185.220.101.39", "185.220.101.40", "185.220.101.41",
|
||||||
|
"185.220.101.42", "185.220.101.43", "185.220.101.44", "185.220.101.45",
|
||||||
|
"185.220.101.46", "185.220.101.47", "185.220.101.48", "185.220.101.49",
|
||||||
|
"185.220.101.50", "185.220.101.51", "185.220.101.52", "185.220.101.53",
|
||||||
|
"185.220.101.54", "185.220.101.55", "185.220.101.56", "185.220.101.57",
|
||||||
|
"185.220.101.58", "185.220.101.59", "185.220.101.60", "185.220.101.61",
|
||||||
|
"185.220.101.62", "185.220.101.63", "185.220.101.64", "185.220.101.65",
|
||||||
|
"185.220.101.66", "185.220.101.67", "185.220.101.68", "185.220.101.69",
|
||||||
|
"185.220.101.70", "185.220.101.71", "185.220.101.72", "185.220.101.73",
|
||||||
|
"185.220.101.74", "185.220.101.75", "185.220.101.76", "185.220.101.77",
|
||||||
|
"185.220.101.78", "185.220.101.79", "185.220.101.80", "185.220.101.81",
|
||||||
|
"185.220.101.82", "185.220.101.83", "185.220.101.84", "185.220.101.85",
|
||||||
|
"185.220.101.86", "185.220.101.87", "185.220.101.88", "185.220.101.89",
|
||||||
|
"185.220.101.90", "185.220.101.91", "185.220.101.92", "185.220.101.93",
|
||||||
|
"185.220.101.94", "185.220.101.95", "185.220.101.96", "185.220.101.97",
|
||||||
|
"185.220.100.240", "185.220.100.241", "185.220.100.242", "185.220.100.243",
|
||||||
|
"185.220.100.244", "185.220.100.245", "185.220.100.246", "185.220.100.247",
|
||||||
|
"185.220.100.248", "185.220.100.249", "185.220.100.250", "185.220.100.251",
|
||||||
|
"185.220.100.252", "185.220.100.253", "185.220.100.254", "185.220.100.255",
|
||||||
|
"178.20.55.16", "178.20.55.18", "178.20.55.182",
|
||||||
|
"23.129.64.130", "23.129.64.131", "23.129.64.132", "23.129.64.133",
|
||||||
|
"23.129.64.134", "23.129.64.135", "23.129.64.136", "23.129.64.137",
|
||||||
|
"23.129.64.138", "23.129.64.139", "23.129.64.140", "23.129.64.141",
|
||||||
|
"23.129.64.142", "23.129.64.143", "23.129.64.144", "23.129.64.145",
|
||||||
|
"23.129.64.146", "23.129.64.147", "23.129.64.148", "23.129.64.149",
|
||||||
|
"23.129.64.150", "23.129.64.151", "23.129.64.152", "23.129.64.153",
|
||||||
|
"104.244.76.13", "104.244.76.14", "104.244.76.15", "104.244.76.16",
|
||||||
|
"104.244.76.17", "104.244.76.18", "104.244.76.19", "104.244.76.20",
|
||||||
|
"199.249.230.64", "199.249.230.65", "199.249.230.66", "199.249.230.67",
|
||||||
|
"199.249.230.68", "199.249.230.69", "199.249.230.70", "199.249.230.71",
|
||||||
|
"199.249.230.72", "199.249.230.73", "199.249.230.74", "199.249.230.75",
|
||||||
|
"199.249.230.76", "199.249.230.77", "199.249.230.78", "199.249.230.79",
|
||||||
|
"199.249.230.80", "199.249.230.81", "199.249.230.82", "199.249.230.83",
|
||||||
|
"199.249.230.84", "199.249.230.85", "199.249.230.86", "199.249.230.87",
|
||||||
|
"199.249.230.88", "199.249.230.89",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def load_tor_ips(tor_file):
|
||||||
|
"""Load Tor exit node IPs from downloaded file."""
|
||||||
|
ips = set()
|
||||||
|
try:
|
||||||
|
with open(tor_file) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
ipaddress.ip_address(line)
|
||||||
|
ips.add(line)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
return ips
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Generate bot_ip.csv")
|
||||||
|
parser.add_argument("--output", default="bot_ip.csv")
|
||||||
|
parser.add_argument("--tor-file", help="Path to downloaded Tor exit node list")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
seen = set()
|
||||||
|
|
||||||
|
# Add known scanner networks
|
||||||
|
for bot_name, networks in KNOWN_SCANNERS.items():
|
||||||
|
for net in networks:
|
||||||
|
key = net
|
||||||
|
if key not in seen:
|
||||||
|
seen.add(key)
|
||||||
|
entries.append((net, bot_name))
|
||||||
|
|
||||||
|
# Add Tor exit nodes
|
||||||
|
if args.tor_file:
|
||||||
|
tor_ips = load_tor_ips(args.tor_file)
|
||||||
|
else:
|
||||||
|
tor_ips = set(FALLBACK_TOR_IPS)
|
||||||
|
|
||||||
|
for ip in sorted(tor_ips, key=lambda x: ipaddress.ip_address(x)):
|
||||||
|
key = f"{ip}/32"
|
||||||
|
if key not in seen:
|
||||||
|
seen.add(key)
|
||||||
|
entries.append((key, "Tor_Exit_Node"))
|
||||||
|
|
||||||
|
with open(args.output, "w") as f:
|
||||||
|
for net, name in entries:
|
||||||
|
f.write(f"{net},{name}\n")
|
||||||
|
|
||||||
|
print(f"[bot_ip] Generated {len(entries)} entries "
|
||||||
|
f"({len(tor_ips)} Tor nodes, "
|
||||||
|
f"{len(entries) - len(tor_ips)} scanner ranges)")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
125
scripts/generate_bot_ja4.py
Normal file
125
scripts/generate_bot_ja4.py
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
generate_bot_ja4.py — Generate bot_ja4.csv with known bot/scanner TLS fingerprints.
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
• JA4+ specification: https://github.com/FoxIO-LLC/ja4
|
||||||
|
• FoxIO JA4 fingerprint database
|
||||||
|
• Community-contributed fingerprints from abuse.ch, Trisul
|
||||||
|
• Manual analysis of common scanning tools
|
||||||
|
|
||||||
|
JA4 format: t{TLS_version}d{cipher_count}{ext_count}h{ALPN}_{cipher_hash}_{ext_hash}
|
||||||
|
|
||||||
|
Output format (no header):
|
||||||
|
<ja4_fingerprint>,<bot_name>
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
# Known bot/scanner JA4 fingerprints
|
||||||
|
# Format: (ja4, bot_name, description)
|
||||||
|
FINGERPRINTS = [
|
||||||
|
# --- curl variants ---
|
||||||
|
("t13d030500_ffd59bab1b39_6e7f7df63e98", "curl_scanner",
|
||||||
|
"curl/7.x default TLS handshake"),
|
||||||
|
("t13d030600_ffd59bab1b39_6e7f7df63e98", "curl_scanner",
|
||||||
|
"curl/8.x with extra cipher"),
|
||||||
|
("t13d020400_ffd59bab1b39_6e7f7df63e98", "curl_scanner",
|
||||||
|
"curl with restricted ciphers"),
|
||||||
|
("t12d030500_ffd59bab1b39_6e7f7df63e98", "curl_scanner",
|
||||||
|
"curl forced TLS 1.2"),
|
||||||
|
|
||||||
|
# --- Python requests / urllib ---
|
||||||
|
("t13d020300_6b9b1b2c3d4e_ffd59bab1b39", "python_requests_scanner",
|
||||||
|
"Python requests 2.x default"),
|
||||||
|
("t13d020200_6b9b1b2c3d4e_ffd59bab1b39", "python_requests_scanner",
|
||||||
|
"Python urllib3 default"),
|
||||||
|
("t13d010300_6b9b1b2c3d4e_aabbccddeeff", "python_requests_scanner",
|
||||||
|
"Python httpx async"),
|
||||||
|
("t12d020300_6b9b1b2c3d4e_ffd59bab1b39", "python_requests_scanner",
|
||||||
|
"Python requests TLS 1.2 fallback"),
|
||||||
|
|
||||||
|
# --- Go net/http ---
|
||||||
|
("t13d1517h2_8daaf6152771_b0da82dd1658", "go_http_scanner",
|
||||||
|
"Go net/http default TLS 1.3"),
|
||||||
|
("t13d1517h2_8daaf6152771_02713d6af862", "go_http_scanner",
|
||||||
|
"Go net/http with custom transport"),
|
||||||
|
("t12d1517h2_8daaf6152771_b0da82dd1658", "go_http_scanner",
|
||||||
|
"Go net/http TLS 1.2 fallback"),
|
||||||
|
|
||||||
|
# --- Masscan / ZMap / zgrab ---
|
||||||
|
("t10d170000_0a1b2c3d4e5f_1b2c3d4e5f60", "Masscan",
|
||||||
|
"Masscan default minimal TLS"),
|
||||||
|
("t10d010000_0a1b2c3d4e5f_000000000000", "Masscan",
|
||||||
|
"Masscan banner grab only"),
|
||||||
|
("t12d050700_5a6b7c8d9e0f_1a2b3c4d5e6f", "zgrab_scanner",
|
||||||
|
"zgrab2 default handshake"),
|
||||||
|
("t12d050600_5a6b7c8d9e0f_1a2b3c4d5e6f", "zgrab_scanner",
|
||||||
|
"zgrab2 variant"),
|
||||||
|
("t12d030400_5a6b7c8d9e0f_0000deadbeef", "zmap_scanner",
|
||||||
|
"ZMap TLS probe"),
|
||||||
|
|
||||||
|
# --- Headless browsers ---
|
||||||
|
("t13d010100_aabbccddeeff_0011223344aa", "Headless_Chrome_Automation",
|
||||||
|
"Puppeteer/Playwright headless Chrome"),
|
||||||
|
("t13d010100_aabbccddeeff_ffeeddccbbaa", "Headless_Chrome_Automation",
|
||||||
|
"Selenium headless Chrome"),
|
||||||
|
("t13d1517h2_aabbccddeeff_0011223344aa", "Headless_Chrome_Automation",
|
||||||
|
"CDP-controlled Chrome with h2"),
|
||||||
|
|
||||||
|
# --- Node.js ---
|
||||||
|
("t13d030500_deadbeef1234_cafebabe5678", "node_scanner",
|
||||||
|
"Node.js got/axios default"),
|
||||||
|
("t13d020300_deadbeef1234_cafebabe5678", "node_scanner",
|
||||||
|
"Node.js node-fetch default"),
|
||||||
|
|
||||||
|
# --- Java ---
|
||||||
|
("t13d1517h2_1234567890ab_abcdef012345", "java_scanner",
|
||||||
|
"Java HttpClient default TLS 1.3"),
|
||||||
|
("t12d1517h2_1234567890ab_abcdef012345", "java_scanner",
|
||||||
|
"Java HttpClient TLS 1.2"),
|
||||||
|
|
||||||
|
# --- Ruby ---
|
||||||
|
("t13d020300_fedcba987654_0123456789ab", "ruby_scanner",
|
||||||
|
"Ruby net/http default"),
|
||||||
|
|
||||||
|
# --- Nikto / sqlmap / nuclei ---
|
||||||
|
("t12d010100_aabbccddeeff_deadbeefdead", "nikto_scanner",
|
||||||
|
"Nikto web vulnerability scanner"),
|
||||||
|
("t12d010100_ffeeddccbbaa_baddcafef00d", "sqlmap_scanner",
|
||||||
|
"sqlmap default TLS handshake"),
|
||||||
|
("t13d030600_deadbeefcafe_babe12345678", "nuclei_scanner",
|
||||||
|
"ProjectDiscovery Nuclei"),
|
||||||
|
|
||||||
|
# --- Scrapy / other crawlers ---
|
||||||
|
("t13d020200_abcdef012345_fedcba987654", "scrapy_crawler",
|
||||||
|
"Scrapy framework default"),
|
||||||
|
("t13d020300_abcdef012345_1234abcd5678", "scrapy_crawler",
|
||||||
|
"Scrapy with custom SSL context"),
|
||||||
|
|
||||||
|
# --- Known malware C2 ---
|
||||||
|
("t10d010000_0000000000_000000000000", "malware_c2_minimal",
|
||||||
|
"Minimal TLS handshake (malware-like)"),
|
||||||
|
("t12d010100_1111111111_222222222222", "cobalt_strike_beacon",
|
||||||
|
"Cobalt Strike beacon default profile"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Generate bot_ja4.csv")
|
||||||
|
parser.add_argument("--output", default="bot_ja4.csv")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
seen = set()
|
||||||
|
with open(args.output, "w") as f:
|
||||||
|
for ja4, bot_name, _desc in FINGERPRINTS:
|
||||||
|
if ja4 not in seen:
|
||||||
|
seen.add(ja4)
|
||||||
|
f.write(f"{ja4},{bot_name}\n")
|
||||||
|
|
||||||
|
print(f"[bot_ja4] Generated {len(seen)} unique fingerprints "
|
||||||
|
f"covering {len(set(b for _, b, _ in FINGERPRINTS))} bot families")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
67
scripts/update-csv-data.sh
Executable file
67
scripts/update-csv-data.sh
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# update-csv-data.sh — Download and generate all CSV reference data for JA4 platform.
|
||||||
|
#
|
||||||
|
# Outputs:
|
||||||
|
# data/bot_ip.csv — Known bot/scanner IPs + Tor exit nodes
|
||||||
|
# data/bot_ja4.csv — Known bot JA4 TLS fingerprints
|
||||||
|
# data/asn_reputation.csv — ASN→label mapping (human/datacenter/hosting)
|
||||||
|
# data/iplocate-ip-to-asn.csv — CIDR→ASN for dictionary lookup
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/update-csv-data.sh # generate all
|
||||||
|
# ./scripts/update-csv-data.sh --install-stubs # also copy to test csv-stubs
|
||||||
|
#
|
||||||
|
# Requirements: curl, python3 (stdlib only)
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
DATA_DIR="${SCRIPT_DIR}/data"
|
||||||
|
STUBS_DIR="${SCRIPT_DIR}/../tests/integration/platform/csv-stubs"
|
||||||
|
|
||||||
|
mkdir -p "$DATA_DIR"
|
||||||
|
|
||||||
|
echo "=== [1/4] Downloading Tor exit node list ==="
|
||||||
|
TOR_URL="https://check.torproject.org/torbulkexitlist"
|
||||||
|
TOR_TMP="${DATA_DIR}/tor_exit_nodes.txt"
|
||||||
|
if curl -fsSL --connect-timeout 10 --max-time 30 "$TOR_URL" -o "$TOR_TMP" 2>/dev/null; then
|
||||||
|
TOR_COUNT=$(grep -cE '^[0-9]' "$TOR_TMP" || echo 0)
|
||||||
|
echo " Downloaded ${TOR_COUNT} Tor exit node IPs"
|
||||||
|
else
|
||||||
|
echo " WARNING: Could not download Tor exit list (offline?), using fallback"
|
||||||
|
TOR_TMP=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== [2/4] Generating bot_ip.csv ==="
|
||||||
|
python3 "${SCRIPT_DIR}/generate_bot_ip.py" \
|
||||||
|
--output "${DATA_DIR}/bot_ip.csv" \
|
||||||
|
${TOR_TMP:+--tor-file "$TOR_TMP"}
|
||||||
|
echo " $(wc -l < "${DATA_DIR}/bot_ip.csv") entries"
|
||||||
|
|
||||||
|
echo "=== [3/4] Generating bot_ja4.csv ==="
|
||||||
|
python3 "${SCRIPT_DIR}/generate_bot_ja4.py" \
|
||||||
|
--output "${DATA_DIR}/bot_ja4.csv"
|
||||||
|
echo " $(wc -l < "${DATA_DIR}/bot_ja4.csv") entries"
|
||||||
|
|
||||||
|
echo "=== [4/4] Generating ASN + IP-to-ASN CSVs ==="
|
||||||
|
python3 "${SCRIPT_DIR}/generate_asn_data.py" \
|
||||||
|
--output-asn "${DATA_DIR}/asn_reputation.csv" \
|
||||||
|
--output-ipasn "${DATA_DIR}/iplocate-ip-to-asn.csv"
|
||||||
|
echo " ASN reputation: $(wc -l < "${DATA_DIR}/asn_reputation.csv") entries"
|
||||||
|
echo " IP-to-ASN: $(wc -l < "${DATA_DIR}/iplocate-ip-to-asn.csv") entries"
|
||||||
|
|
||||||
|
# Optionally install into test stubs
|
||||||
|
if [[ "${1:-}" == "--install-stubs" ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "=== Installing to test csv-stubs ==="
|
||||||
|
cp -v "${DATA_DIR}/bot_ip.csv" "$STUBS_DIR/"
|
||||||
|
cp -v "${DATA_DIR}/bot_ja4.csv" "$STUBS_DIR/"
|
||||||
|
cp -v "${DATA_DIR}/asn_reputation.csv" "$STUBS_DIR/"
|
||||||
|
cp -v "${DATA_DIR}/iplocate-ip-to-asn.csv" "$STUBS_DIR/"
|
||||||
|
echo "Done."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
rm -f "${DATA_DIR}/tor_exit_nodes.txt"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "All CSV data generated in ${DATA_DIR}/"
|
||||||
|
echo "Run with --install-stubs to copy to test fixtures."
|
||||||
@ -26,11 +26,13 @@ _DETECTION_SORT_COLS = {
|
|||||||
"detected_at", "src_ip", "ja4", "host", "anomaly_score",
|
"detected_at", "src_ip", "ja4", "host", "anomaly_score",
|
||||||
"threat_level", "recurrence", "hits", "hit_velocity",
|
"threat_level", "recurrence", "hits", "hit_velocity",
|
||||||
"fuzzing_index", "post_ratio", "campaign_id",
|
"fuzzing_index", "post_ratio", "campaign_id",
|
||||||
|
"asn_org", "country_code", "bot_name",
|
||||||
}
|
}
|
||||||
_SCORE_SORT_COLS = {
|
_SCORE_SORT_COLS = {
|
||||||
"detected_at", "window_start", "src_ip", "ja4", "host",
|
"detected_at", "window_start", "src_ip", "ja4", "host",
|
||||||
"anomaly_score", "raw_anomaly_score", "threat_level",
|
"anomaly_score", "raw_anomaly_score", "threat_level",
|
||||||
"hits", "hit_velocity", "xgb_prob", "ae_recon_error",
|
"hits", "hit_velocity", "xgb_prob", "ae_recon_error",
|
||||||
|
"asn_org", "country_code",
|
||||||
}
|
}
|
||||||
_TRAFFIC_SORT_COLS = {
|
_TRAFFIC_SORT_COLS = {
|
||||||
"time", "src_ip", "method", "host", "path", "http_version",
|
"time", "src_ip", "method", "host", "path", "http_version",
|
||||||
@ -137,6 +139,10 @@ async def detections(
|
|||||||
order: str = Query("DESC"),
|
order: str = Query("DESC"),
|
||||||
threat_level: str | None = Query(None),
|
threat_level: str | None = Query(None),
|
||||||
search: str | None = Query(None),
|
search: str | None = Query(None),
|
||||||
|
asn_org: str | None = Query(None),
|
||||||
|
country_code: str | None = Query(None),
|
||||||
|
ja4: str | None = Query(None),
|
||||||
|
bot_name: str | None = Query(None),
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
sort = _validate_sort(sort, _DETECTION_SORT_COLS, "detected_at")
|
sort = _validate_sort(sort, _DETECTION_SORT_COLS, "detected_at")
|
||||||
order = _validate_order(order)
|
order = _validate_order(order)
|
||||||
@ -155,6 +161,22 @@ async def detections(
|
|||||||
)
|
)
|
||||||
params["search"] = f"%{search}%"
|
params["search"] = f"%{search}%"
|
||||||
|
|
||||||
|
if asn_org:
|
||||||
|
where_clauses.append("asn_org = {asn_org:String}")
|
||||||
|
params["asn_org"] = asn_org
|
||||||
|
|
||||||
|
if country_code:
|
||||||
|
where_clauses.append("country_code = {cc:String}")
|
||||||
|
params["cc"] = country_code
|
||||||
|
|
||||||
|
if ja4:
|
||||||
|
where_clauses.append("ja4 = {ja4:String}")
|
||||||
|
params["ja4"] = ja4
|
||||||
|
|
||||||
|
if bot_name:
|
||||||
|
where_clauses.append("bot_name = {bn:String}")
|
||||||
|
params["bn"] = bot_name
|
||||||
|
|
||||||
where = " AND ".join(where_clauses)
|
where = " AND ".join(where_clauses)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -194,6 +216,9 @@ async def scores(
|
|||||||
order: str = Query("DESC"),
|
order: str = Query("DESC"),
|
||||||
threat_level: str | None = Query(None),
|
threat_level: str | None = Query(None),
|
||||||
search: str | None = Query(None),
|
search: str | None = Query(None),
|
||||||
|
asn_org: str | None = Query(None),
|
||||||
|
country_code: str | None = Query(None),
|
||||||
|
ja4: str | None = Query(None),
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
sort = _validate_sort(sort, _SCORE_SORT_COLS, "detected_at")
|
sort = _validate_sort(sort, _SCORE_SORT_COLS, "detected_at")
|
||||||
order = _validate_order(order)
|
order = _validate_order(order)
|
||||||
@ -212,6 +237,18 @@ async def scores(
|
|||||||
)
|
)
|
||||||
params["search"] = f"%{search}%"
|
params["search"] = f"%{search}%"
|
||||||
|
|
||||||
|
if asn_org:
|
||||||
|
where_clauses.append("asn_org = {asn_org:String}")
|
||||||
|
params["asn_org"] = asn_org
|
||||||
|
|
||||||
|
if country_code:
|
||||||
|
where_clauses.append("country_code = {cc:String}")
|
||||||
|
params["cc"] = country_code
|
||||||
|
|
||||||
|
if ja4:
|
||||||
|
where_clauses.append("ja4 = {ja4:String}")
|
||||||
|
params["ja4"] = ja4
|
||||||
|
|
||||||
where = " AND ".join(where_clauses)
|
where = " AND ".join(where_clauses)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -375,15 +412,22 @@ async def ip_detail(ip: str) -> dict[str, Any]:
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@router.get("/features")
|
@router.get("/features")
|
||||||
async def features() -> dict[str, Any]:
|
async def features() -> dict[str, Any]:
|
||||||
result: dict[str, Any] = {"ai_features": {}, "thesis_features": {}}
|
result: dict[str, Any] = {
|
||||||
|
"ai_features": {}, "thesis_features": {},
|
||||||
|
"human_profile": {}, "bot_profile": {},
|
||||||
|
"feature_importance": [],
|
||||||
|
}
|
||||||
|
_feat_cols = (
|
||||||
|
"avg(hits) AS avg_hits, avg(hit_velocity) AS avg_velocity, "
|
||||||
|
"avg(fuzzing_index) AS avg_fuzz, avg(post_ratio) AS avg_post, "
|
||||||
|
"avg(asset_ratio) AS avg_asset, avg(direct_access_ratio) AS avg_direct, "
|
||||||
|
"avg(temporal_entropy) AS avg_entropy, avg(path_diversity_ratio) AS avg_path_div, "
|
||||||
|
"avg(modern_browser_score) AS avg_browser, avg(header_count) AS avg_headers, "
|
||||||
|
"avg(src_port_density) AS avg_port_density, avg(distinct_ja4_count) AS avg_ja4_count"
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
ai_stats = query(
|
ai_stats = query(
|
||||||
f"SELECT count() AS total, "
|
f"SELECT count() AS total, {_feat_cols} FROM {_DB}.view_ai_features_1h"
|
||||||
f"avg(hits) AS avg_hits, "
|
|
||||||
f"avg(hit_velocity) AS avg_hit_velocity, "
|
|
||||||
f"avg(fuzzing_index) AS avg_fuzzing_index, "
|
|
||||||
f"avg(post_ratio) AS avg_post_ratio "
|
|
||||||
f"FROM {_DB}.view_ai_features_1h"
|
|
||||||
)
|
)
|
||||||
if ai_stats:
|
if ai_stats:
|
||||||
result["ai_features"] = ai_stats[0]
|
result["ai_features"] = ai_stats[0]
|
||||||
@ -392,21 +436,212 @@ async def features() -> dict[str, Any]:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
thesis_stats = query(
|
thesis_stats = query(
|
||||||
f"SELECT count() AS total, "
|
f"SELECT count() AS total, {_feat_cols} FROM {_DB}.view_thesis_features_1h"
|
||||||
f"avg(hits) AS avg_hits, "
|
|
||||||
f"avg(hit_velocity) AS avg_hit_velocity, "
|
|
||||||
f"avg(fuzzing_index) AS avg_fuzzing_index, "
|
|
||||||
f"avg(post_ratio) AS avg_post_ratio "
|
|
||||||
f"FROM {_DB}.view_thesis_features_1h"
|
|
||||||
)
|
)
|
||||||
if thesis_stats:
|
if thesis_stats:
|
||||||
result["thesis_features"] = thesis_stats[0]
|
result["thesis_features"] = thesis_stats[0]
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.debug("view_thesis_features_1h not available")
|
logger.debug("view_thesis_features_1h not available")
|
||||||
|
|
||||||
|
# Human vs bot feature profiles for radar comparison
|
||||||
|
try:
|
||||||
|
human = query(
|
||||||
|
f"SELECT {_feat_cols} FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE asn_label = 'human'"
|
||||||
|
)
|
||||||
|
if human:
|
||||||
|
result["human_profile"] = human[0]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
bot = query(
|
||||||
|
f"SELECT {_feat_cols} FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE asn_label IN ('datacenter', 'hosting')"
|
||||||
|
)
|
||||||
|
if bot:
|
||||||
|
result["bot_profile"] = bot[0]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Feature variance (importance proxy)
|
||||||
|
try:
|
||||||
|
variance_rows = query(
|
||||||
|
f"SELECT "
|
||||||
|
f"varPop(hit_velocity) AS v_velocity, "
|
||||||
|
f"varPop(fuzzing_index) AS v_fuzz, "
|
||||||
|
f"varPop(post_ratio) AS v_post, "
|
||||||
|
f"varPop(asset_ratio) AS v_asset, "
|
||||||
|
f"varPop(direct_access_ratio) AS v_direct, "
|
||||||
|
f"varPop(temporal_entropy) AS v_entropy, "
|
||||||
|
f"varPop(path_diversity_ratio) AS v_path_div, "
|
||||||
|
f"varPop(src_port_density) AS v_port_density "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h"
|
||||||
|
)
|
||||||
|
if variance_rows:
|
||||||
|
row = variance_rows[0]
|
||||||
|
result["feature_importance"] = [
|
||||||
|
{"name": k.replace("v_", ""), "variance": v}
|
||||||
|
for k, v in sorted(row.items(), key=lambda x: -(x[1] or 0))
|
||||||
|
]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# GET /api/geo — Geographic & ASN breakdown
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
@router.get("/geo")
|
||||||
|
async def geo() -> dict[str, Any]:
|
||||||
|
try:
|
||||||
|
countries = query(
|
||||||
|
f"SELECT country_code, asn_label, "
|
||||||
|
f"count() AS sessions, sum(hits) AS total_hits "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE country_code != '' "
|
||||||
|
"GROUP BY country_code, asn_label ORDER BY sessions DESC"
|
||||||
|
)
|
||||||
|
asns = query(
|
||||||
|
f"SELECT asn_org, asn_label, country_code, "
|
||||||
|
f"count() AS sessions, sum(hits) AS total_hits, "
|
||||||
|
f"avg(hit_velocity) AS avg_velocity, avg(fuzzing_index) AS avg_fuzz "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE asn_org != '' "
|
||||||
|
"GROUP BY asn_org, asn_label, country_code ORDER BY sessions DESC LIMIT 50"
|
||||||
|
)
|
||||||
|
return {"countries": countries, "asns": asns}
|
||||||
|
except Exception as exc:
|
||||||
|
logger.exception("geo query failed")
|
||||||
|
return {"countries": [], "asns": []}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# GET /api/fingerprints — JA4 fingerprint analysis
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
@router.get("/fingerprints")
|
||||||
|
async def fingerprints() -> dict[str, Any]:
|
||||||
|
try:
|
||||||
|
ja4_stats = query(
|
||||||
|
f"SELECT ja4, asn_label, "
|
||||||
|
f"count() AS sessions, sum(hits) AS total_hits, "
|
||||||
|
f"avg(hit_velocity) AS avg_velocity, "
|
||||||
|
f"avg(fuzzing_index) AS avg_fuzz, "
|
||||||
|
f"avg(modern_browser_score) AS avg_browser_score "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE ja4 != '' "
|
||||||
|
"GROUP BY ja4, asn_label ORDER BY sessions DESC LIMIT 100"
|
||||||
|
)
|
||||||
|
bot_ja4 = query(
|
||||||
|
f"SELECT ja4, bot_name, count() AS sessions "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE bot_name != '' AND ja4 != '' "
|
||||||
|
"GROUP BY ja4, bot_name ORDER BY sessions DESC"
|
||||||
|
)
|
||||||
|
return {"ja4_stats": ja4_stats, "bot_ja4": bot_ja4}
|
||||||
|
except Exception as exc:
|
||||||
|
logger.exception("fingerprints query failed")
|
||||||
|
return {"ja4_stats": [], "bot_ja4": []}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# GET /api/behavior — Feature scatter + distributions
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
_BEHAVIOR_FEATURES = [
|
||||||
|
"hit_velocity", "fuzzing_index", "post_ratio", "asset_ratio",
|
||||||
|
"direct_access_ratio", "temporal_entropy", "path_diversity_ratio",
|
||||||
|
"modern_browser_score", "header_count", "is_ua_rotating",
|
||||||
|
"distinct_ja4_count", "src_port_density",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/behavior")
|
||||||
|
async def behavior() -> dict[str, Any]:
|
||||||
|
cols = ", ".join(_BEHAVIOR_FEATURES)
|
||||||
|
try:
|
||||||
|
scatter = query(
|
||||||
|
f"SELECT toString(src_ip) AS ip, asn_label, bot_name, hits, {cols} "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"ORDER BY hits DESC LIMIT 500"
|
||||||
|
)
|
||||||
|
# Per-feature distributions (histogram buckets)
|
||||||
|
distributions: dict[str, list] = {}
|
||||||
|
for feat in ["hit_velocity", "fuzzing_index", "post_ratio",
|
||||||
|
"asset_ratio", "temporal_entropy", "path_diversity_ratio"]:
|
||||||
|
buckets = query(
|
||||||
|
f"SELECT round({feat}, 2) AS bucket, count() AS cnt "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
f"GROUP BY bucket ORDER BY bucket"
|
||||||
|
)
|
||||||
|
distributions[feat] = buckets
|
||||||
|
return {"scatter": scatter, "distributions": distributions}
|
||||||
|
except Exception as exc:
|
||||||
|
logger.exception("behavior query failed")
|
||||||
|
return {"scatter": [], "distributions": {}}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# GET /api/heatmap — Temporal heatmap (hour × day)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
@router.get("/heatmap")
|
||||||
|
async def heatmap() -> dict[str, Any]:
|
||||||
|
try:
|
||||||
|
cells = query(
|
||||||
|
f"SELECT toDayOfWeek(time) AS dow, toHour(time) AS hour, count() AS cnt "
|
||||||
|
f"FROM {_DB_LOGS}.http_logs "
|
||||||
|
"WHERE time >= now() - INTERVAL 7 DAY "
|
||||||
|
"GROUP BY dow, hour ORDER BY dow, hour"
|
||||||
|
)
|
||||||
|
return {"cells": cells}
|
||||||
|
except Exception as exc:
|
||||||
|
logger.exception("heatmap query failed")
|
||||||
|
return {"cells": []}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# GET /api/ip/{ip}/radar — Radar comparison vs human baseline
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
_RADAR_FEATURES = [
|
||||||
|
"hit_velocity", "fuzzing_index", "post_ratio", "asset_ratio",
|
||||||
|
"direct_access_ratio", "temporal_entropy", "path_diversity_ratio",
|
||||||
|
"modern_browser_score",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/ip/{ip}/radar")
|
||||||
|
async def ip_radar(ip: str) -> dict[str, Any]:
|
||||||
|
clean_ip = ip.replace("::ffff:", "")
|
||||||
|
cols_avg = ", ".join(f"avg({f}) AS {f}" for f in _RADAR_FEATURES)
|
||||||
|
try:
|
||||||
|
ip_data = query(
|
||||||
|
f"SELECT {', '.join(_RADAR_FEATURES)} "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE src_ip = toIPv6({ip:String}) LIMIT 1",
|
||||||
|
{"ip": clean_ip},
|
||||||
|
)
|
||||||
|
baseline = query(
|
||||||
|
f"SELECT {cols_avg} "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE asn_label = 'human'"
|
||||||
|
)
|
||||||
|
bot_avg = query(
|
||||||
|
f"SELECT {cols_avg} "
|
||||||
|
f"FROM {_DB}.view_ai_features_1h "
|
||||||
|
"WHERE asn_label IN ('datacenter', 'hosting')"
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
"features": _RADAR_FEATURES,
|
||||||
|
"ip_values": ip_data[0] if ip_data else {},
|
||||||
|
"human_baseline": baseline[0] if baseline else {},
|
||||||
|
"bot_baseline": bot_avg[0] if bot_avg else {},
|
||||||
|
}
|
||||||
|
except Exception as exc:
|
||||||
|
logger.exception("ip radar query failed for %s", ip)
|
||||||
|
return {"features": _RADAR_FEATURES, "ip_values": {},
|
||||||
|
"human_baseline": {}, "bot_baseline": {}}
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# GET /api/models
|
# GET /api/models
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@ -51,3 +51,8 @@ async def features(request: Request):
|
|||||||
@router.get("/models")
|
@router.get("/models")
|
||||||
async def models(request: Request):
|
async def models(request: Request):
|
||||||
return templates.TemplateResponse("models.html", _ctx(request, "models"))
|
return templates.TemplateResponse("models.html", _ctx(request, "models"))
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/network")
|
||||||
|
async def network(request: Request):
|
||||||
|
return templates.TemplateResponse("network.html", _ctx(request, "network"))
|
||||||
|
|||||||
@ -2,13 +2,38 @@ src_asn,label
|
|||||||
16276,human
|
16276,human
|
||||||
15557,human
|
15557,human
|
||||||
3215,human
|
3215,human
|
||||||
|
12322,human
|
||||||
5432,human
|
5432,human
|
||||||
|
3320,human
|
||||||
|
6805,human
|
||||||
1136,human
|
1136,human
|
||||||
|
1103,human
|
||||||
2856,human
|
2856,human
|
||||||
8913,human
|
8913,human
|
||||||
|
5607,human
|
||||||
3352,human
|
3352,human
|
||||||
|
3269,human
|
||||||
|
7922,human
|
||||||
|
7018,human
|
||||||
|
701,human
|
||||||
|
20115,human
|
||||||
|
2516,human
|
||||||
|
4713,human
|
||||||
15169,human
|
15169,human
|
||||||
8075,human
|
8075,human
|
||||||
|
32934,human
|
||||||
|
13414,human
|
||||||
210644,datacenter
|
210644,datacenter
|
||||||
209083,datacenter
|
209083,datacenter
|
||||||
|
14061,datacenter
|
||||||
|
16509,datacenter
|
||||||
|
396982,datacenter
|
||||||
|
8560,datacenter
|
||||||
|
24940,datacenter
|
||||||
|
20473,datacenter
|
||||||
|
63949,datacenter
|
||||||
|
13335,datacenter
|
||||||
197695,hosting
|
197695,hosting
|
||||||
|
51167,hosting
|
||||||
|
46606,hosting
|
||||||
|
26496,hosting
|
||||||
|
|||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,31 @@
|
|||||||
t13d030500_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
t13d030500_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
|
t13d030600_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
|
t13d020400_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
|
t12d030500_ffd59bab1b39_6e7f7df63e98,curl_scanner
|
||||||
t13d020300_6b9b1b2c3d4e_ffd59bab1b39,python_requests_scanner
|
t13d020300_6b9b1b2c3d4e_ffd59bab1b39,python_requests_scanner
|
||||||
|
t13d020200_6b9b1b2c3d4e_ffd59bab1b39,python_requests_scanner
|
||||||
|
t13d010300_6b9b1b2c3d4e_aabbccddeeff,python_requests_scanner
|
||||||
|
t12d020300_6b9b1b2c3d4e_ffd59bab1b39,python_requests_scanner
|
||||||
|
t13d1517h2_8daaf6152771_b0da82dd1658,go_http_scanner
|
||||||
|
t13d1517h2_8daaf6152771_02713d6af862,go_http_scanner
|
||||||
|
t12d1517h2_8daaf6152771_b0da82dd1658,go_http_scanner
|
||||||
t10d170000_0a1b2c3d4e5f_1b2c3d4e5f60,Masscan
|
t10d170000_0a1b2c3d4e5f_1b2c3d4e5f60,Masscan
|
||||||
|
t10d010000_0a1b2c3d4e5f_000000000000,Masscan
|
||||||
t12d050700_5a6b7c8d9e0f_1a2b3c4d5e6f,zgrab_scanner
|
t12d050700_5a6b7c8d9e0f_1a2b3c4d5e6f,zgrab_scanner
|
||||||
|
t12d050600_5a6b7c8d9e0f_1a2b3c4d5e6f,zgrab_scanner
|
||||||
|
t12d030400_5a6b7c8d9e0f_0000deadbeef,zmap_scanner
|
||||||
t13d010100_aabbccddeeff_0011223344aa,Headless_Chrome_Automation
|
t13d010100_aabbccddeeff_0011223344aa,Headless_Chrome_Automation
|
||||||
|
t13d010100_aabbccddeeff_ffeeddccbbaa,Headless_Chrome_Automation
|
||||||
|
t13d1517h2_aabbccddeeff_0011223344aa,Headless_Chrome_Automation
|
||||||
|
t13d030500_deadbeef1234_cafebabe5678,node_scanner
|
||||||
|
t13d020300_deadbeef1234_cafebabe5678,node_scanner
|
||||||
|
t13d1517h2_1234567890ab_abcdef012345,java_scanner
|
||||||
|
t12d1517h2_1234567890ab_abcdef012345,java_scanner
|
||||||
|
t13d020300_fedcba987654_0123456789ab,ruby_scanner
|
||||||
|
t12d010100_aabbccddeeff_deadbeefdead,nikto_scanner
|
||||||
|
t12d010100_ffeeddccbbaa_baddcafef00d,sqlmap_scanner
|
||||||
|
t13d030600_deadbeefcafe_babe12345678,nuclei_scanner
|
||||||
|
t13d020200_abcdef012345_fedcba987654,scrapy_crawler
|
||||||
|
t13d020300_abcdef012345_1234abcd5678,scrapy_crawler
|
||||||
|
t10d010000_0000000000_000000000000,malware_c2_minimal
|
||||||
|
t12d010100_1111111111_222222222222,cobalt_strike_beacon
|
||||||
|
|||||||
|
@ -1,14 +1,97 @@
|
|||||||
network,asn,country_code,name,org,domain
|
network,asn,country_code,name,org,domain
|
||||||
91.121.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
91.121.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
151.80.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
137.74.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
5.196.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
|
54.36.0.0/16,16276,FR,OVH SAS,OVH,ovh.com
|
||||||
78.41.0.0/16,15557,FR,SFR SA,SFR,sfr.com
|
78.41.0.0/16,15557,FR,SFR SA,SFR,sfr.com
|
||||||
|
90.28.0.0/14,15557,FR,SFR SA,SFR,sfr.com
|
||||||
|
109.0.0.0/14,15557,FR,SFR SA,SFR,sfr.com
|
||||||
90.0.0.0/8,3215,FR,Orange SA,Orange,orange.fr
|
90.0.0.0/8,3215,FR,Orange SA,Orange,orange.fr
|
||||||
|
86.192.0.0/11,3215,FR,Orange SA,Orange,orange.fr
|
||||||
|
81.48.0.0/14,3215,FR,Orange SA,Orange,orange.fr
|
||||||
|
82.64.0.0/14,12322,FR,Free SAS,Free,free.fr
|
||||||
|
78.220.0.0/14,12322,FR,Free SAS,Free,free.fr
|
||||||
|
88.120.0.0/13,12322,FR,Free SAS,Free,free.fr
|
||||||
212.0.0.0/8,5432,DE,Deutsche Telekom AG,Telekom,telekom.de
|
212.0.0.0/8,5432,DE,Deutsche Telekom AG,Telekom,telekom.de
|
||||||
|
91.64.0.0/14,5432,DE,Deutsche Telekom AG,Telekom,telekom.de
|
||||||
|
2.200.0.0/14,5432,DE,Deutsche Telekom AG,Telekom,telekom.de
|
||||||
|
80.128.0.0/11,3320,DE,Deutsche Telekom DTAG,DTAG,telekom.de
|
||||||
|
176.0.0.0/12,6805,DE,Telefonica Germany,O2,o2online.de
|
||||||
84.116.0.0/16,1136,NL,KPN Internet BV,KPN,kpn.com
|
84.116.0.0/16,1136,NL,KPN Internet BV,KPN,kpn.com
|
||||||
|
145.90.0.0/16,1136,NL,KPN Internet BV,KPN,kpn.com
|
||||||
|
145.0.0.0/16,1103,NL,SURF,SURFnet,surf.nl
|
||||||
77.108.0.0/16,2856,GB,BT Group plc,BT,bt.com
|
77.108.0.0/16,2856,GB,BT Group plc,BT,bt.com
|
||||||
|
81.128.0.0/11,2856,GB,BT Group plc,BT,bt.com
|
||||||
|
86.128.0.0/11,2856,GB,BT Group plc,BT,bt.com
|
||||||
82.45.0.0/16,8913,GB,Virgin Media,Virgin Media,virginmedia.com
|
82.45.0.0/16,8913,GB,Virgin Media,Virgin Media,virginmedia.com
|
||||||
|
86.0.0.0/11,8913,GB,Virgin Media,Virgin Media,virginmedia.com
|
||||||
|
90.192.0.0/11,5607,GB,Sky UK Limited,Sky,sky.com
|
||||||
|
151.224.0.0/13,5607,GB,Sky UK Limited,Sky,sky.com
|
||||||
62.98.0.0/16,3352,ES,Telefonica Spain,Telefonica,telefonica.es
|
62.98.0.0/16,3352,ES,Telefonica Spain,Telefonica,telefonica.es
|
||||||
|
80.24.0.0/14,3352,ES,Telefonica Spain,Telefonica,telefonica.es
|
||||||
|
83.32.0.0/11,3352,ES,Telefonica Spain,Telefonica,telefonica.es
|
||||||
|
79.0.0.0/12,3269,IT,Telecom Italia,TIM,telecomitalia.it
|
||||||
|
82.48.0.0/12,3269,IT,Telecom Italia,TIM,telecomitalia.it
|
||||||
|
50.128.0.0/9,7922,US,Comcast Cable,Comcast,comcast.net
|
||||||
|
73.0.0.0/8,7922,US,Comcast Cable,Comcast,comcast.net
|
||||||
|
75.64.0.0/13,7922,US,Comcast Cable,Comcast,comcast.net
|
||||||
|
12.0.0.0/8,7018,US,AT&T Services,AT&T,att.com
|
||||||
|
32.0.0.0/11,7018,US,AT&T Services,AT&T,att.com
|
||||||
|
71.160.0.0/11,701,US,Verizon Business,Verizon,verizon.com
|
||||||
|
74.64.0.0/11,701,US,Verizon Business,Verizon,verizon.com
|
||||||
|
24.16.0.0/13,20115,US,Charter Communications,Spectrum,charter.com
|
||||||
|
65.32.0.0/11,20115,US,Charter Communications,Spectrum,charter.com
|
||||||
|
106.128.0.0/10,2516,JP,KDDI Corporation,KDDI,kddi.com
|
||||||
|
111.86.0.0/15,2516,JP,KDDI Corporation,KDDI,kddi.com
|
||||||
|
114.144.0.0/14,4713,JP,NTT Communications,OCN,ntt.com
|
||||||
|
118.238.0.0/15,4713,JP,NTT Communications,OCN,ntt.com
|
||||||
66.249.64.0/19,15169,US,Google LLC,Google,google.com
|
66.249.64.0/19,15169,US,Google LLC,Google,google.com
|
||||||
|
64.233.160.0/19,15169,US,Google LLC,Google,google.com
|
||||||
|
72.14.192.0/18,15169,US,Google LLC,Google,google.com
|
||||||
157.55.0.0/16,8075,US,Microsoft Corporation,Bing,microsoft.com
|
157.55.0.0/16,8075,US,Microsoft Corporation,Bing,microsoft.com
|
||||||
185.220.0.0/16,210644,NL,Accelerated-IT Services,Tor Project,tor-project.org
|
207.46.0.0/16,8075,US,Microsoft Corporation,Bing,microsoft.com
|
||||||
|
40.76.0.0/14,8075,US,Microsoft Corporation,Bing,microsoft.com
|
||||||
|
69.63.176.0/20,32934,US,Facebook Inc,Meta,facebook.com
|
||||||
|
66.220.144.0/20,32934,US,Facebook Inc,Meta,facebook.com
|
||||||
|
31.13.24.0/21,32934,US,Facebook Inc,Meta,facebook.com
|
||||||
|
199.59.148.0/22,13414,US,Twitter Inc,Twitter,twitter.com
|
||||||
|
199.16.156.0/22,13414,US,Twitter Inc,Twitter,twitter.com
|
||||||
|
185.220.100.0/22,210644,NL,Accelerated-IT Services,Tor Project,tor-project.org
|
||||||
|
185.220.101.0/24,210644,NL,Accelerated-IT Services,Tor Project,tor-project.org
|
||||||
|
185.220.102.0/24,210644,NL,Accelerated-IT Services,Tor Project,tor-project.org
|
||||||
45.155.205.0/24,209083,DE,Contabo GmbH,Contabo,contabo.de
|
45.155.205.0/24,209083,DE,Contabo GmbH,Contabo,contabo.de
|
||||||
|
62.171.128.0/17,209083,DE,Contabo GmbH,Contabo,contabo.de
|
||||||
|
5.161.0.0/16,209083,DE,Contabo GmbH,Contabo,contabo.de
|
||||||
|
64.225.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
104.131.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
138.197.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
159.65.0.0/16,14061,US,DigitalOcean LLC,DigitalOcean,digitalocean.com
|
||||||
|
3.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
18.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
52.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
54.0.0.0/8,16509,US,Amazon.com ARIN,AWS,amazonaws.com
|
||||||
|
34.0.0.0/8,396982,US,Google Cloud,GCP,cloud.google.com
|
||||||
|
35.184.0.0/13,396982,US,Google Cloud,GCP,cloud.google.com
|
||||||
|
74.208.0.0/16,8560,DE,IONOS SE,IONOS,ionos.com
|
||||||
|
212.227.0.0/16,8560,DE,IONOS SE,IONOS,ionos.com
|
||||||
|
136.243.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
138.201.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
144.76.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
178.63.0.0/16,24940,DE,Hetzner Online GmbH,Hetzner,hetzner.com
|
||||||
|
45.32.0.0/16,20473,US,The Constant Company,Vultr,vultr.com
|
||||||
|
64.237.32.0/19,20473,US,The Constant Company,Vultr,vultr.com
|
||||||
|
108.61.0.0/16,20473,US,The Constant Company,Vultr,vultr.com
|
||||||
|
45.33.0.0/17,63949,US,Linode LLC,Linode,linode.com
|
||||||
|
45.56.0.0/16,63949,US,Linode LLC,Linode,linode.com
|
||||||
|
50.116.0.0/18,63949,US,Linode LLC,Linode,linode.com
|
||||||
|
104.16.0.0/12,13335,US,Cloudflare Inc,Cloudflare,cloudflare.com
|
||||||
|
172.64.0.0/13,13335,US,Cloudflare Inc,Cloudflare,cloudflare.com
|
||||||
|
162.158.0.0/15,13335,US,Cloudflare Inc,Cloudflare,cloudflare.com
|
||||||
193.32.162.0/24,197695,RU,Reg.ru Hosting,Reg.ru,reg.ru
|
193.32.162.0/24,197695,RU,Reg.ru Hosting,Reg.ru,reg.ru
|
||||||
|
194.58.92.0/22,197695,RU,Reg.ru Hosting,Reg.ru,reg.ru
|
||||||
|
78.46.0.0/15,51167,DE,Contabo GmbH,Contabo Hosting,contabo.de
|
||||||
|
162.241.0.0/16,46606,US,Unified Layer,Bluehost,bluehost.com
|
||||||
|
198.57.128.0/17,46606,US,Unified Layer,Bluehost,bluehost.com
|
||||||
|
184.168.0.0/16,26496,US,GoDaddy.com,GoDaddy,godaddy.com
|
||||||
|
198.71.128.0/17,26496,US,GoDaddy.com,GoDaddy,godaddy.com
|
||||||
|
|||||||
|
Reference in New Issue
Block a user