Page MenuHomePhabricator
Paste P8683

RPKI check for invalids
ActivePublic

Authored by faidon on Jun 28 2019, 2:06 PM.
#!/usr/bin/env python3
import re
import pytricia
import urllib.request
import random
import timeit
anafile = "ana-invalids.txt"
anaurl = "https://as286.net/data/ana-invalids.txt"
def parse(iterable):
pattern = "^(?P<prefix>[^;]+);srcAS=(?P<asn>[^;]+);altpfx=(?P<altpfx>[^;]+);.*"
prefixes = pytricia.PyTricia(128)
for line in iterable:
match = re.search(pattern, line)
if not match:
continue
prefix = match.group("prefix")
if match.group("altpfx") == "NONE":
altpfx = False
else:
altpfx = True
prefixes[prefix] = altpfx
return prefixes
def read_and_parse_file(filename):
with open(filename, "r") as f:
return parse(f)
def read_and_parse_url(url):
response = urllib.request.urlopen(url)
content = response.read().decode("utf-8")
return parse(content.splitlines())
prefixes = read_and_parse_file(anafile)
# prefixes = read_and_parse_url(anaurl)
def lookup(ip):
try:
altpfx = prefixes[ip]
if altpfx:
result = "invalid-but-reachable"
else:
result = "unreachable"
except KeyError:
result = "valid-or-unverified"
return result
# test some lookups that we
def test_lookup():
for ip in (
"2.59.118.1", # unreachable
"2.176.52.1", # invalid-but-reachable
"1.1.1.1", # valid-or-unverified
"2a0d:5643::1", # unreachable
"2a0d:5084::1", # invalid-but-reachable
"2606:4700:4700::1111", # valid-or-unverified
):
try:
print(ip, lookup(ip))
except KeyError:
# invalid prefix?
pass
def random_ip(n):
for i in range(n):
random.randint(0, 255)
random_ip4 = ".".join([str(random.randint(0, 255)) for j in range(0, 4)])
yield random_ip4
def test_random():
for ip in random_ip(1000):
lookup(ip)
if __name__ == "__main__":
test_lookup()
n = 10
v = timeit.timeit(
"test_random()", setup="from __main__ import test_random", number=n
)
print("Execution time per run: ", v / n)

Event Timeline

faidon created this paste.Jun 28 2019, 2:06 PM
faidon edited the content of this paste. (Show Details)Jun 28 2019, 2:54 PM

The equivalent linear search (diff below) is ~800-850 times slower on my laptop:

--- parse_ana_patricia.py
+++ parse_ana_linear.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 import re
-import pytricia
+import ipaddress
 import urllib.request
 
 import random
@@ -13,7 +13,7 @@
 
 def parse(iterable):
     pattern = "^(?P<prefix>[^;]+);srcAS=(?P<asn>[^;]+);altpfx=(?P<altpfx>[^;]+);.*"
-    prefixes = pytricia.PyTricia(128)
+    prefixes = {}
 
     for line in iterable:
         match = re.search(pattern, line)
@@ -26,6 +26,7 @@
         else:
             altpfx = True
 
+        prefix = ipaddress.ip_network(prefix)
         prefixes[prefix] = altpfx
 
     return prefixes
@@ -47,14 +48,16 @@
 
 
 def lookup(ip):
-    try:
-        altpfx = prefixes[ip]
-        if altpfx:
-            result = "invalid-but-reachable"
-        else:
-            result = "unreachable"
-    except KeyError:
-        result = "valid-or-unverified"
+    result = "valid-or-unverified"
+
+    ip = ipaddress.ip_address(ip)
+    for prefix, altpfx in prefixes.items():
+        if ip in prefix:
+            if altpfx:
+                result = "invalid-but-reachable"
+            else:
+                result = "unreachable"
+            break
 
     return result