diff --git a/README.md b/README.md index 9d79108..a656c47 100644 --- a/README.md +++ b/README.md @@ -91,12 +91,18 @@ an output CSV path: python scripts/parked_domain_csv.py domains.txt parked_domains.csv ``` +Pass `--dmarc-cname` to override the default DMARC CNAME target: + +```bash +python scripts/parked_domain_csv.py domains.txt parked_domains.csv --dmarc-cname reject.dmarc.contoso.com. +``` + Each domain receives the following DNS entries: - SPF record with `-all` - Null MX record - DKIM wildcard with an empty key -- DMARC CNAME pointing to a reject policy +- DMARC CNAME pointing to a reject policy (customizable via `--dmarc-cname`) ## License diff --git a/scripts/parked_domain_csv.py b/scripts/parked_domain_csv.py index 7ee6fc5..0ae2b93 100644 --- a/scripts/parked_domain_csv.py +++ b/scripts/parked_domain_csv.py @@ -1,5 +1,5 @@ import csv -import sys +import argparse HEADER = [ "Action", @@ -11,37 +11,50 @@ "Comments", ] +DEFAULT_DMARC_CNAME = "reject.dmarc.fabrikam.com." + RECORD_TEMPLATE = [ ["REMOVE", "{domain}", "@", "MX", "", "10 custmx.cscdns.net.", "Remove existing MX record"], ["ADD", "{domain}", "@", "TXT", "3600", "v=spf1 -all", "SPF hard fail"], ["ADD", "{domain}", "@", "MX", "3600", "0 .", "Null MX (RFC 7505)"], ["ADD", "{domain}", "*._domainkey", "TXT", "3600", "v=DKIM1; p=", "DKIM wildcard with empty key"], - ["ADD", "{domain}", "_dmarc", "CNAME", "3600", "reject.dmarc.fabrikam.com.", "DMARC reject policy via CNAME"], + ["ADD", "{domain}", "_dmarc", "CNAME", "3600", "{dmarc_target}", "DMARC reject policy via CNAME"], ] -def generate_records(domain: str): +def generate_records(domain: str, dmarc_target: str): records = [[f"--- {domain} ---", "", "", "", "", "", "Domain configuration"]] for template in RECORD_TEMPLATE: + value = template[5].format(dmarc_target=dmarc_target) records.append([ template[0], domain, template[2], template[3], template[4], - template[5], + value, template[6], ]) return records def main(): - if len(sys.argv) != 3: - print("Usage: python parked_domain_csv.py domains.txt output.csv") - sys.exit(1) + parser = argparse.ArgumentParser( + description="Generate CSV records to lock down parked or non-mailing domains" + ) + parser.add_argument("domain_file", help="Text file containing domain names") + parser.add_argument("output_csv", help="Path to write the output CSV") + parser.add_argument( + "--dmarc-cname", + default=DEFAULT_DMARC_CNAME, + help="DMARC CNAME target (default: %(default)s)", + ) + + args = parser.parse_args() - domain_file = sys.argv[1] - output_csv = sys.argv[2] + domain_file = args.domain_file + output_csv = args.output_csv + dmarc_cname = args.dmarc_cname with open(domain_file, "r", encoding="utf-8") as f: domains = [line.strip() for line in f if line.strip()] @@ -50,7 +63,7 @@ def main(): writer = csv.writer(csvfile) writer.writerow(HEADER) for domain in domains: - for row in generate_records(domain): + for row in generate_records(domain, dmarc_cname): writer.writerow(row)