1212from oxl_utils .ps import wait_for_threads
1313from dns .resolver import Resolver , NoAnswer , NXDOMAIN , LifetimeTimeout , NoNameservers
1414from dns .exception import SyntaxError as DNSSyntaxError
15+ from netaddr .ip import IPNetwork , cidr_merge
16+ from netaddr .core import AddrFormatError , AddrConversionError
1517
1618from riskdb .builder .util import log
1719from riskdb .config import KIND_FILES
1820from riskdb .builder .load_reports import FileLoader
1921from riskdb .builder .config import CACHE_FILE_PTR , ASN_JSON_FILE , TOR_EXIT_NODE_LIST , PTR_LOOKUP_THREADS , \
20- PTR_CACHE_DAYS , PTR_STATUS_COUNT , PTR_NAMESERVERS , PTR_MAX_QUERY_RETRIES
22+ PTR_CACHE_DAYS , PTR_STATUS_COUNT , PTR_NAMESERVERS , PTR_MAX_QUERY_RETRIES , VPN_URLS , DOWNLOAD_TIMEOUT
2123
2224now = int (time ())
2325ptr_cache_lock = Lock ()
@@ -35,6 +37,35 @@ def load_lookup_list_asn() -> dict:
3537 return json_loads (f .read ())
3638
3739
40+ def load_vpn_ips () -> list [IPNetwork ]:
41+ vpn_file = '/tmp/vpns.txt'
42+ os_shell (
43+ f"wget -q --connect-timeout={ DOWNLOAD_TIMEOUT } -O { vpn_file } .tmp { VPN_URLS ['apple' ]} &&"
44+ f"tail -n +2 { vpn_file } .tmp | cut -d ',' -f1 | sort | uniq > { vpn_file } "
45+ )
46+ os_shell (
47+ f"wget -q --connect-timeout={ DOWNLOAD_TIMEOUT } -O { vpn_file } .tmp { VPN_URLS ['mullvad' ]} &&"
48+ f"jq -r '.[][] | try .[] | try .ipv4_addr_in' < { vpn_file } .tmp | sort | uniq >> { vpn_file } &&"
49+ f"jq -r '.[][] | try .[] | try .ipv6_addr_in' < { vpn_file } .tmp | sort | uniq >> { vpn_file } "
50+ )
51+ os_shell (
52+ f"wget -q --connect-timeout={ DOWNLOAD_TIMEOUT } -O { vpn_file } .tmp { VPN_URLS ['pia' ]} &&"
53+ f"tail -n +2 { vpn_file } .tmp | cut -d ',' -f1 | sort | uniq >> { vpn_file } "
54+ )
55+
56+ # NOTE: using netaddr to allow for subnet-merging where possible
57+ nets = []
58+ with open (vpn_file , 'r' , encoding = 'utf-8' ) as f :
59+ for net in f .readlines ():
60+ try :
61+ nets .append (IPNetwork (net .strip ()))
62+
63+ except (AddrFormatError , AddrConversionError , ValueError ):
64+ continue
65+
66+ return cidr_merge (nets )
67+
68+
3869def load_lookup_lists () -> dict :
3970 lookup_lists = {}
4071 tor_exit_node_file = '/tmp/tor_exit_nodes.txt'
@@ -51,6 +82,7 @@ def load_lookup_lists() -> dict:
5182 except AddressValueError :
5283 continue
5384
85+ lookup_lists ['vpns' ] = load_vpn_ips ()
5486 lookup_lists ['asn' ] = load_lookup_list_asn ()
5587
5688 # creation of these files has yet to be automated
0 commit comments