Skip to content

Instantly share code, notes, and snippets.

@beppe9000
Forked from 0x9900/whitelist.py
Last active January 22, 2022 15:42
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 beppe9000/546a648335f5f04186264942ac66258e to your computer and use it in GitHub Desktop.
Save beppe9000/546a648335f5f04186264942ac66258e to your computer and use it in GitHub Desktop.
Extract the IP addresses from SPF records.
#!/usr/bin/env python
# Purpose: Print the list of ip addresses from SPF records
# Author: beppe9000
import dns
from dns import resolver
from collections import defaultdict
import re
import sys
RE_PARSE = re.compile(r'(ip4|ip6|include|redirect)[:=](.*)', re.IGNORECASE)
MAX_RECURSION = 5
def dns_txt(domain):
response = []
try:
answers = dns.resolver.resolve(domain, 'TXT')
except dns.exception.DNSException as err:
print(err, file=sys.stderr)
return None
#print (' query qname:', answers.qname, ' num ans.', len(answers))
for rdata in answers:
for txt_string in rdata.strings:
#print (' TXT: ', txt_string)
if (txt_string.decode().startswith('v=spf1')):
#print (' SPF: ', str(txt_string))
response.append(txt_string.decode())
#print(dir(answers))
#return "FUCKU"
return response
def dns_parse(txt_field):
# print("Parsing...")
resp = defaultdict(set)
for rec in txt_field:
fields = rec.split()
for field in fields:
match = RE_PARSE.match(field)
if match:
resp[match.group(1)].add(match.group(2) if not match.group(1).startswith("ipv6") else '"'+match.group(2)+'"')
#print("MATCH [",match.group(1),"] => ",match.group(2))
return resp
def process(domain):
domains = [domain]
ip_addresses = set()
for cnt in range(MAX_RECURSION):
includes = set()
for dom in domains:
txt = dns_txt(dom)
if not txt:
continue
spf = dns_parse(txt)
ip_addresses |= spf.get('ip4', set())
ip_addresses |= spf.get('ip6', set())
includes |= spf.get('include', set())
includes |= spf.get('redirect', set())
if not includes:
break
domains = includes
return ip_addresses
def test():
#for v in dns_txt("_spf.google.com"):
# print('VAL: ', v.to_text())
r1 = dns_txt("_spf.google.com")
for txt_string in r1:
print (' SPF: ', txt_string)
spf = dns_parse(r1)
#for item in spf.items():
# print(item)
includes = set()
ip_addresses = set()
ip_addresses |= spf.get('ip4', set())
includes |= spf.get('include', set())
print("INCLUDES: ",str(includes))
print("IP ADDRS: ",str(ip_addresses))
#print (' PARSED: ', str(txt_string))
process("_spf.google.com")
if __name__ == '__main__':
whitelist=set()
if(len(sys.argv)>1):
with open(sys.argv[1]) as fd:
for line in fd:
line = line.strip()
for ip in process(line):
whitelist.add(ip)
else:
for ip in process("_spf.google.com"):
whitelist.add(ip)
for ip in sorted(whitelist):
print(ip)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment