forked from freifunk/icvpn-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkdns
executable file
·117 lines (99 loc) · 3.92 KB
/
mkdns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env python
from textwrap import dedent
from optparse import OptionParser
from socket import AF_INET, AF_INET6, inet_pton
from formatter import Formatter
from filereader import get_communities_data
class DnsmasqFormatter(Formatter):
"Formatter for dnsmasq"
def add_data(self, domains, servers):
for domain in domains:
for server in servers:
self.config.append("server=/%s/%s" % (domain, server))
class BindFormatter(Formatter):
"Formatter for bind9 (>=9.8) using type static-stub"
def add_data(self, domains, servers):
for domain in domains:
self.config.append(dedent("""
zone "%s" {
type static-stub;
server-addresses { %s; };
};
""" % (domain, "; ".join(servers))).lstrip())
class BindForwardFormatter(Formatter):
"Formatter for bind9 using type forward"
def add_data(self, domains, servers):
for domain in domains:
self.config.append(dedent("""
zone "%s" {
type forward;
forwarders { %s; };
forward only;
};
""" % (domain, "; ".join(servers))).lstrip())
def create_config(srcdir, fmtclass, exclude=set(), filters=[]):
"""
Generates a configuration using all files in srcdir
(non-recursively) excluding communities from 'exclude'.
The files are read in lexicographic order to produce deterministic
results.
"""
formatter = fmtclass()
for community, data in get_communities_data(srcdir, exclude):
try:
domains = data['domains']
nameservers = data['nameservers']
except (TypeError, KeyError):
continue
formatter.add_comment("\n%s\n" % community)
servers = filter(lambda d: all(f(d) for f in filters), nameservers)
servers = list(servers)
if len(domains) == 0:
formatter.add_comment("No valid domains found")
elif len(servers) == 0:
formatter.add_comment("No valid servers found")
else:
formatter.add_data(domains, servers)
print(formatter.finalize())
if __name__ == "__main__":
def try_inet_pton(af, ip):
try:
inet_pton(af, ip)
return True
except:
return False
formatters = {
"dnsmasq": DnsmasqFormatter,
"bind": BindFormatter,
"bind-forward": BindForwardFormatter,
}
filters = {
"v4": lambda value: try_inet_pton(AF_INET, value),
"v6": lambda value: try_inet_pton(AF_INET6, value),
}
parser = OptionParser()
parser.add_option("-f", "--format", dest="fmt",
help="""Create config in format FMT.
Possible values: %s. Default: dnsmasq""" %
", ".join(formatters.keys()),
metavar="FMT",
choices=list(formatters.keys()),
default="dnsmasq")
parser.add_option("-s", "--sourcedir", dest="src",
help="Use files in DIR as input files. Default: data/",
metavar="DIR",
default="data")
parser.add_option("-x", "--exclude", dest="exclude", action="append",
help="Exclude COMMUNITY (may be repeated)",
metavar="COMMUNITY",
default=[])
parser.add_option("--filter", dest="filter",
help="""Only include certain servers.
Possible choices: %s""" %
", ".join(filters.keys()),
choices=list(filters.keys()))
(options, args) = parser.parse_args()
create_config(options.src,
formatters[options.fmt],
set(options.exclude),
[filters[options.filter]] if options.filter else [])