49 lines
1.7 KiB
Python
49 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
from ipaddress import ip_network, IPv4Network, IPv6Network
|
|
from dns.resolver import Resolver
|
|
from typing import List, Union
|
|
from generator import get_version, write_to_file
|
|
|
|
|
|
class Spf:
|
|
def _parse_spf(self, spf: str) -> dict:
|
|
output = {"include": [], "ranges": []}
|
|
for part in spf.split(" "):
|
|
if part.startswith("include:"):
|
|
output["include"].append(part.split(":", 1)[1])
|
|
elif part.startswith("ip4:") or part.startswith("ip6:"):
|
|
output["ranges"].append(ip_network(part.split(":", 1)[1]))
|
|
return output
|
|
|
|
def _query_spf(self, resolver: Resolver, domain: str) -> List[Union[IPv4Network, IPv6Network]]:
|
|
ranges = []
|
|
for rdata in resolver.query(domain, "TXT"):
|
|
parsed = self._parse_spf(rdata.to_text())
|
|
ranges += parsed["ranges"]
|
|
|
|
for include in parsed["include"]:
|
|
ranges += self._query_spf(resolver, include)
|
|
|
|
return ranges
|
|
|
|
def get_list(self, domain: str) -> List[Union[IPv4Network, IPv6Network]]:
|
|
resolver = Resolver()
|
|
return self._query_spf(resolver, domain)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
spf = Spf()
|
|
print()
|
|
|
|
warninglist = {
|
|
'name': "List of known Gmail sending IP ranges",
|
|
'version': get_version(),
|
|
'description': "List of known Gmail sending IP ranges (https://support.google.com/a/answer/27642?hl=en)",
|
|
'matching_attributes': ["ip-src", "ip-dst", "domain|ip"],
|
|
'type': 'cidr',
|
|
'list': [str(range) for range in spf.get_list("_spf.google.com")],
|
|
}
|
|
|
|
write_to_file(warninglist, "google-gmail-sending-ips")
|