Skip to content

Instantly share code, notes, and snippets.

@v6ak
Created March 14, 2018 21:27
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 v6ak/52aaf19ee71f5528dfa8d0def991d27a to your computer and use it in GitHub Desktop.
Save v6ak/52aaf19ee71f5528dfa8d0def991d27a to your computer and use it in GitHub Desktop.
Simple DNS server intended for responding ACME challenges. Assumes ownership of /etc/authbind/byport/53.
#/usr/bin/env authbind python3
from dnslib.label import DNSLabel
from dnslib.server import DNSServer, DNSLogger, DNSRecord, RR
from dnslib.dns import TXT
import re
import sys
import os
from os import listdir
def find_challenge(s_un):
s = s_un.lower()
PREFIX = "_acme-challenge."
SUFFIX = "."
if re.match("^[A-Za-z0-9_.-]*$", s) and (s.replace(".", "") != '') and s.startswith(PREFIX) and s.endswith(SUFFIX):
name = s[len(PREFIX):-len(SUFFIX)]
dirname = path+os.sep+name
try:
files = listdir(dirname)
except FileNotFoundError:
return []
responses = []
for file in files:
with open(dirname+os.sep+file, 'r') as f:
responses.append(f.read().replace('\n', ''))
return responses
else:
return []
class TestResolver:
def resolve(self,request,handler):
reply = request.reply()
for q in request.questions:
name = str(q.qname)
challenges = find_challenge(name)
if (q.qtype == 16):
for challenge in challenges:
reply.add_answer(RR(rname=DNSLabel(name), rtype=16, rdata=TXT(challenge)))
return reply
path = sys.argv[1]
logger = DNSLogger(prefix=False)
resolver = TestResolver()
server = DNSServer(resolver, port=53, address="0.0.0.0", logger=logger, tcp=False)
server.start()
#!/bin/bash
# safety settings
set -u
set -e
set -o pipefail
cd "$(dirname "$(realpath "$0")")"
pip3 install --user -r requirements.txt
authbind python3 dnsserver.py ~letsencrypt/.challenges-per-domain
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment