Skip to content

Instantly share code, notes, and snippets.

@wafflecomposite
Created May 8, 2023 20:48
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 wafflecomposite/81de26f9fa1fd16f33a7496c55fd637b to your computer and use it in GitHub Desktop.
Save wafflecomposite/81de26f9fa1fd16f33a7496c55fd637b to your computer and use it in GitHub Desktop.
πŸ‡¬πŸ‡ͺ Silknet DNS Incident: potential censorship against Activitypub
import json
import csv
from urllib.parse import urlparse
# pip install requests
import requests
# pip install dnspython
from dns import resolver
from dns.exception import DNSException
# Quad9 dns as "ground truth"
# aka https://dns.quad9.net/dns-query
r1 = resolver.Resolver()
r1.nameservers = ["9.9.9.9"]
# GE, GEOCELL(Silknet) DNS as the subject of research
# aka https://maradona.silknet.com
r2 = resolver.Resolver()
r2.nameservers = ["91.151.130.117"]
# Get OONI global server list
ooni_csv = requests.get('https://raw.githubusercontent.com/citizenlab/test-lists/master/lists/global.csv')
ooni_servers = [urlparse(row[0] if row else "").netloc for row in csv.reader(ooni_csv.text.split("\n")[1:], delimiter=',')]
# Get Activitypub instances, sorted by reported activity
headers = {'Accept': 'application/json'}
r_body = {"query": "{\n nodes(status: \"1\") {\n active_users_monthly\n domain\n }\n}"}
ap_nodes = requests.post('https://api.fediverse.observer', headers=headers, json=r_body).json()["data"]["nodes"] # get node list
ap_active_nodes = [item for item in ap_nodes if item["active_users_monthly"] is not None and item["active_users_monthly"] > 3] # filter low activity nodes
ap_sorted_nodes = [item["domain"] for item in list(sorted(ap_active_nodes, key=lambda item: item["active_users_monthly"], reverse=True))] # sort by activity
print(f"AP servers len:{len(ap_sorted_nodes)}")
print(f"OONI servers len:{len(ooni_servers)}")
results = {
"AP": {
0: 0, # not available on Quad9, not checked on Silknet
1: 0, # available on both
2: 0 # available on Quad9 but not on Silknet <- This is the point of interest.
},
"OONI": {
0: 0, # not available on Quad9, not checked on Silknet
1: 0, # available on both
2: 0 # available on Quad9 but not on Silknet
},
}
def check_server(server):
resp1 = None
resp2 = None
try:
q = r1.resolve(server)
resp1 = [x.address for x in q]
except DNSException:
return 0 # not available on Quad9, no point to check further
try:
q = r2.resolve(server)
resp2 = [x.address for x in q]
except DNSException:
resp2 = []
if resp1 and resp2:
return 1 # available on both
else:
return 2 # available on Quad9 but not on Silknet
for i in range(1000):
ap_res = check_server(ap_sorted_nodes[i])
oomi_res = check_server(ooni_servers[i])
results["AP"][ap_res] += 1
results["OONI"][oomi_res] += 1
print(results)
# 00:32 UTC+4 09.05.2023
# {'AP': {0: 46, 1: 498, 2: 456}, 'OONI': {0: 19, 1: 951, 2: 30}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment