Skip to content

Instantly share code, notes, and snippets.

@ximon18
Last active March 8, 2019 13:48
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 ximon18/82d20d3ae190b7be54be236a6f6244f5 to your computer and use it in GitHub Desktop.
Save ximon18/82d20d3ae190b7be54be236a6f6244f5 to your computer and use it in GitHub Desktop.
An incomplete Python3 module for Unbound 1.9.0 showing a proof-of-concept partial implementation of http://xip.io/ like functionality in Unbound, and an extension of the idea to support dynamic delegation (which I'm not sure is even a sensible thing to do).
import base64
# Based on: https://jpmens.net/2011/08/09/extending-unbound-with-python-module/
def init_standard(id, env):
return True
def deinit(id):
return True
def inform_super(id, qstate, superqstate, qdata):
return True
def operate(id, event, qstate, qdata):
if event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS:
qdn = qstate.qinfo.qname_str.lower()
if qdn.endswith(".asa.inet_aton.ximoneighteen.com."):
# The xip.io-like case: respond with an A record.
# Expects as input a dotted quad format IPv4 address sub-domain name.
ipv4 = '.'.join(qstate.qinfo.qname_list[0:4])
msg = DNSMessage(qdn, qstate.qinfo.qtype, qstate.qinfo.qclass, PKT_QR | PKT_AA)
msg.answer.append("{} 300 IN A {}".format(qdn, ipv4))
set_return_msg_and_finish(id, msg, qstate)
elif qdn.endswith(".nsdel.inet_aton.ximoneighteen.com."):
# A proposed 'xipdelegate.io' case: respond with NS and A glue records.
# Expects as input a base 32 encoded dotted quad format IPv4 address which "points" to a
# nameserver.
b32 = ''.join(qstate.qinfo.qname_list[-6:-5])
decoded = base64.b32decode(b32).decode('utf-8')
msg = DNSMessage(qdn, qstate.qinfo.qtype, qstate.qinfo.qclass, PKT_QR)
msg.authority.append("{}.isdel.inet_aton.ximoneighteen.com. 60 IN NS {}.asa.inet_aton.ximoneighteen.com".format(b32, decoded))
msg.additional.append("{}.asa.inet_aton.ximoneighteen.com. 60 IN A {}".format(b32, decoded))
set_return_msg_and_finish(id, msg, qstate)
else:
# Pass the query to validator
qstate.ext_state[id] = MODULE_WAIT_MODULE
elif event == MODULE_EVENT_MODDONE:
qstate.ext_state[id] = MODULE_FINISHED
else:
qstate.ext_state[id] = MODULE_ERROR
return True
def set_return_msg_and_finish(id, msg, qstate):
qstate.return_rcode = RCODE_NOERROR
# Set qstate.return_msg
if not msg.set_return_msg(qstate):
qstate.ext_state[id] = MODULE_ERROR
else:
# Indicate valid result
qstate.return_msg.rep.security = 2
qstate.ext_state[id] = MODULE_FINISHED
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment