14 SUSPICIOUS_HOSTS = set([
15 "130.211.129.106",
"178.63.107.226",
16 "83.81.130.26",
"88.198.17.7",
"148.251.238.178",
"176.9.46.6",
17 "54.173.72.127",
"54.174.10.182",
"54.183.64.54",
"54.194.231.211",
18 "54.66.214.167",
"54.66.220.137",
"54.67.33.14",
"54.77.251.214",
19 "54.94.195.96",
"54.94.200.247" 27 PATTERN_IPV4 = re.compile(
r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):(\d+)$")
28 PATTERN_IPV6 = re.compile(
r"^\[([0-9a-z:]+)\]:(\d+)$")
29 PATTERN_ONION = re.compile(
r"^([abcdefghijklmnopqrstuvwxyz234567]{16}\.onion):(\d+)$")
30 PATTERN_AGENT = re.compile(
r"^(\/Satoshi:0\.8\.6\/|\/Satoshi:0\.9\.(2|3|4|5)\/|\/Core:0.1(0|1|2).\d{1,2}.\d{1,2}\/)$")
36 m = PATTERN_IPV4.match(sline[0])
40 m = PATTERN_IPV6.match(sline[0])
42 m = PATTERN_ONION.match(sline[0])
47 ipstr = sortkey = m.group(1)
48 port = int(m.group(2))
51 if m.group(1)
in [
'::']:
55 port = int(m.group(2))
60 if int(m.group(i+2)) < 0
or int(m.group(i+2)) > 255:
62 ip = ip + (int(m.group(i+2)) << (8*(3-i)))
68 port = int(m.group(6))
73 uptime30 = float(sline[7][:-1])
75 lastsuccess = int(sline[2])
77 version = int(sline[10])
79 agent = sline[11][1:-1]
81 service = int(sline[9], 16)
83 blocks = int(sline[8])
91 'lastsuccess': lastsuccess,
100 '''Filter out hosts with more nodes per IP''' 101 hist = collections.defaultdict(list)
103 hist[ip[
'sortkey']].append(ip)
104 return [value[0]
for (key,value)
in hist.items()
if len(value)==1]
109 ips_ipv4 = [ip
for ip
in ips
if ip[
'net'] ==
'ipv4']
110 ips_ipv6 = [ip
for ip
in ips
if ip[
'net'] ==
'ipv6']
111 ips_onion = [ip
for ip
in ips
if ip[
'net'] ==
'onion']
117 if len(result) == max_total:
120 asn = int([x.to_text()
for x
in dns.resolver.query(
'.'.join(reversed(ip[
'ip'].split(
'.'))) +
'.origin.asn.cymru.com',
'TXT').response.answer][0].split(
'\"')[1].split(
' ')[0])
121 if asn
not in asn_count:
123 if asn_count[asn] == max_per_asn:
128 sys.stderr.write(
'ERR: Could not resolve ASN for "' + ip[
'ip'] +
'"\n')
133 result.extend(ips_ipv6)
134 result.extend(ips_onion)
138 lines = sys.stdin.readlines()
139 ips = [
parseline(line)
for line
in lines]
142 ips = [ip
for ip
in ips
if ip
is not None]
144 ips = [ip
for ip
in ips
if ip[
'ip']
not in SUSPICIOUS_HOSTS]
146 ips = [ip
for ip
in ips
if ip[
'blocks'] >= MIN_BLOCKS]
148 ips = [ip
for ip
in ips
if (ip[
'service'] & 1) == 1]
150 ips = [ip
for ip
in ips
if ip[
'uptime'] > 50]
152 ips = [ip
for ip
in ips
if PATTERN_AGENT.match(ip[
'agent'])]
154 ips.sort(key=
lambda x: (x[
'uptime'], x[
'lastsuccess'], x[
'ip']), reverse=
True)
160 ips.sort(key=
lambda x: (x[
'net'], x[
'sortkey']))
163 if ip[
'net'] ==
'ipv6':
164 print '[%s]:%i' % (ip[
'ip'], ip[
'port'])
166 print '%s:%i' % (ip[
'ip'], ip[
'port'])
168 if __name__ ==
'__main__':
def filterbyasn(ips, max_per_asn, max_total)