Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pierky/59f995bf98f3c8a87e41 to your computer and use it in GitHub Desktop.
Save pierky/59f995bf98f3c8a87e41 to your computer and use it in GitHub Desktop.
Python script used to analyze data for my blog post "DNSSEC: ECDSA-aware resolvers seen by RIPE Atlas"
import urllib2
import json
import os.path
import sys
from ripe.atlas.sagan import DnsResult
from pprint import pprint
RIPE_ATLAS_KEY = ""
def GetRIPEAtlasLatestMsmResults( MsmID, RIPEAtlasKey = "", CacheFile = None ):
if os.path.isfile( CacheFile or "%d.json" % MsmID ):
MsmFile = open( CacheFile or "%d.json" % MsmID, "r" )
JSONResponseData = MsmFile.read()
MsmFile.close()
else:
HTTPRequest = urllib2.Request( "https://atlas.ripe.net/api/v1/measurement-latest/%d/?key=%s" % ( MsmID, RIPEAtlasKey ) )
HTTPRequest.add_header( "Content-Type", "application/json" )
HTTPRequest.add_header( "Accept", "application/json" )
JSONResponseData = urllib2.urlopen( HTTPRequest ).read()
LatestResults = json.loads( JSONResponseData )
if not os.path.isfile( CacheFile or "%d.json" % MsmID ):
MsmFile = open( CacheFile or "%d.json" % MsmID, "w" )
MsmFile.write( JSONResponseData )
MsmFile.close
Results = []
for ProbeID in LatestResults:
Results.append( LatestResults[ProbeID][0] )
return Results
Measurements = {
"West": { "MsmID_RIPE": 1849609, "MsmID_CF": 1849622 },
"North-Central": { "MsmID_RIPE": 1849610, "MsmID_CF": 1849623 },
"South-Central": { "MsmID_RIPE": 1849611, "MsmID_CF": 1849624 },
"North-East": { "MsmID_RIPE": 1849612, "MsmID_CF": 1849625 },
"South-East": { "MsmID_RIPE": 1849613, "MsmID_CF": 1849626 }
}
"""
Probes = {
"<probe_id>": {
"Area": "<area>",
"<target>": {
"Status": "<OK|malformed|error (<err_descr>)>",
"AtLeastOneAD": <bool>,
...
}
"Destinations": {
"<dest_addr>": {
"RIPE": { "AD": <bool>, "Answers": "<answers>" },
"CF": { "AD": <bool>, "Answers": "<answers>" }
}
}
},
"<probe_id>": { ... }
}
"""
Probes = {}
def DoArea( Area ):
DoTarget( Area, "RIPE" )
DoTarget( Area, "CF" )
def DoTarget( Area, Target ):
MsmID = Measurements[Area]["MsmID_%s" % Target]
MsmResults = GetRIPEAtlasLatestMsmResults( MsmID, RIPE_ATLAS_KEY )
for JSONResult in MsmResults:
Result = DnsResult( JSONResult, on_malformation=DnsResult.ACTION_FAIL, on_error=DnsResult.ACTION_FAIL )
ProbeID = str(Result.probe_id)
if not ProbeID in Probes:
Probes[ProbeID] = {}
Probes[ProbeID]["Area"] = Area
Probes[ProbeID][Target] = {}
if Result.is_malformed:
Probes[ProbeID][Target]["Status"] = "malformed"
elif Result.is_error:
Probes[ProbeID][Target]["Status"] = "error (%s)" % Result.error_message
else:
Probes[ProbeID][Target]["Status"] = "parsing error" # changed later if everything is OK
Probes[ProbeID][Target]["AtLeastOneAD"] = False
Probes[ProbeID][Target]["Responses"] = []
if not "Destinations" in Probes[ProbeID]:
Probes[ProbeID]["Destinations"] = {}
for Response in Result.responses:
try:
if Response.abuf.header:
NewResponse = {}
NewResponse["DstAddr"] = Response.destination_address
if Response.abuf.header.ad:
Probes[ProbeID][Target]["AtLeastOneAD"] = True
NewResponse["Header"] = "%s, AN %s" % ( str( Response.abuf.header ), Response.abuf.header.ancount )
NewResponse["AD"] = Response.abuf.header.ad
NewResponse["Answers"] = ""
Answers = []
for Answer in Response.abuf.answers:
NewAnswer = Answer.type
try:
NewAnswer = NewAnswer + " " + Answer.address
except:
pass
try:
NewAnswer = NewAnswer + " " + Answer.target
except:
pass
Answers.append( NewAnswer )
NewResponse["Answers"] = ",".join( Answers )
if not Response.destination_address in Probes[ProbeID]["Destinations"]:
Probes[ProbeID]["Destinations"][Response.destination_address] = {}
Probes[ProbeID]["Destinations"][Response.destination_address][Target] = {
"Header": NewResponse["Header"],
"AD": NewResponse["AD"],
"Answers": NewResponse["Answers"] }
Probes[ProbeID][Target]["Status"] = "OK"
Probes[ProbeID][Target]["Responses"].append( NewResponse )
except:
pass
for Area in Measurements.keys():
DoArea( Area )
sys.stdout.write("ProbeID;Area;RIPE Status;CF Status;RIPE AD; CF AD")
for DestN in [ 1, 2, 3 ]:
sys.stdout.write(";Dest%s IP" % DestN)
for Target in [ "RIPE", "CF" ]:
sys.stdout.write(";Dest%s %s Header" % ( DestN, Target ) )
sys.stdout.write(";Dest%s %s AD" % ( DestN, Target ) )
sys.stdout.write(";Dest%s %s Answers" % ( DestN, Target ) )
print("")
for ProbeID in Probes.keys():
Probe = Probes[ProbeID]
sys.stdout.write("%s;%s" % ( ProbeID, Probe["Area"] ) )
for Target in [ "RIPE", "CF" ]:
if Target in Probe:
sys.stdout.write(";%s" % Probe[Target]["Status"] )
else:
sys.stdout.write(";no data")
if "RIPE" in Probe and "CF" in Probe and Probe["RIPE"]["Status"] == "OK" and Probe["CF"]["Status"] == "OK":
sys.stdout.write(";%s;%s" % ( Probe["RIPE"]["AtLeastOneAD"], Probe["CF"]["AtLeastOneAD"] ) )
for DestinationID in Probe["Destinations"].keys():
Destination = Probe["Destinations"][DestinationID]
sys.stdout.write(";%s" % DestinationID)
for Target in [ "RIPE", "CF" ]:
if Target in Destination:
try:
sys.stdout.write(";%s;%s;%s" % ( Destination[Target]["Header"], Destination[Target]["AD"], Destination[Target]["Answers"] ) )
except:
print("")
print("ERROR")
pprint(Probe)
raise
else:
sys.stdout.write(";no data;no data;no data")
print("")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment