asn-dns.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/usr/bin/env python
  2. """This script generates DNS TXT records containing ASN information.
  3. The idea comes from asn.cymru.com. Example:
  4. dig +short AS1.asn.cymru.com TXT
  5. The output looks like this:
  6. "1 | US | arin | 2001-09-20 | LVLT-1 - Level 3 Communications, Inc."
  7. In dn42, we try to respect this format. Fields 2 and 3 are set to "DN42"
  8. and "dn42", respectively. The date field is left empty, as we currently
  9. do not record this information in the registry. For the last field, we use
  10. "[as-name] [descr]" from the registry.
  11. """
  12. import sys
  13. import time
  14. import argparse
  15. from registry import AutNum
  16. def gen_zone(args):
  17. out = args.output
  18. # SOA and stuff
  19. out.write("$ORIGIN {}\n".format(args.zone))
  20. out.write("$TTL {}\n".format(args.ttl))
  21. serial = int(time.time())
  22. out.write("@ IN SOA {0.ns[0]} {0.rname} "
  23. "({1} {0.refresh} {0.retry} {0.expire} {0.negative})\n".format(args,
  24. serial))
  25. # NS
  26. for ns in args.ns:
  27. out.write("@ NS {}\n".format(ns))
  28. # TXT data
  29. autnum = AutNum(args.registry)
  30. for (asn, data) in autnum.data.items():
  31. comment = ""
  32. if "as-name" in data:
  33. comment = data["as-name"][0]
  34. if "descr" in data:
  35. comment += " " + data["descr"][0]
  36. comment.replace('"', '')
  37. out.write('{} TXT "{} | DN42 | dn42 | | {}"\n'.format(asn, asn[2:], comment))
  38. def cleanup(args):
  39. def final_dot(s):
  40. if not s.endswith('.'):
  41. return s + "."
  42. else:
  43. return s
  44. args.zone = final_dot(args.zone)
  45. args.rname.replace("@", ".")
  46. args.rname = final_dot(args.rname)
  47. for (i, ns) in enumerate(args.ns):
  48. args.ns[i] = final_dot(ns)
  49. if __name__ == "__main__":
  50. parser = argparse.ArgumentParser(description=__doc__)
  51. parser.add_argument("-n", "--ns", action="append", required=True,
  52. help="name server, can be passed multiple times (the first one will be listed as master in the SOA)")
  53. parser.add_argument("-r", "--rname", required=True,
  54. help="contact email of the administrator of the zone")
  55. parser.add_argument("-o", "--output", default=sys.stdout, type=argparse.FileType('w'),
  56. help="output file (default: stdout)")
  57. parser.add_argument("registry", help="path to the monotone registry")
  58. opt = parser.add_argument_group("Zone options")
  59. opt.add_argument("-z", "--zone", default="asn.dn42.",
  60. help="zone to generate data for (default: %(default)s)")
  61. opt.add_argument("-t", "--ttl", default="1h",
  62. help="TTL for all records (default: %(default)s)")
  63. opt.add_argument("--refresh", default="1d",
  64. help="refresh timer for slaves (default: %(default)s)")
  65. opt.add_argument("--retry", default="1h",
  66. help="retry timer for slaves (default: %(default)s)")
  67. opt.add_argument("--expire", default="4w",
  68. help="expire time for slaves (default: %(default)s)")
  69. opt.add_argument("--negative", default="5m",
  70. help="negative TTL (default: %(default)s)")
  71. args = parser.parse_args()
  72. # Sanity checks
  73. cleanup(args)
  74. gen_zone(args)