1 -- Copyright 2017 Dirk Brenken (dev@brenken.org)
2 -- This is free software, licensed under the Apache License, Version 2.0
4 local fs = require("nixio.fs")
5 local uci = require("luci.model.uci").cursor()
6 local util = require("luci.util")
7 local date = require("luci.http.protocol.date")
8 local res_input = "/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv"
9 local dump = util.ubus("network.interface", "dump", {})
10 local plug_cnt = tonumber(luci.sys.exec("env -i /usr/sbin/dnscrypt-proxy --version | grep 'Support for plugins: present' | wc -l"))
12 local url = "https://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-resolvers.csv"
14 if not fs.access("/lib/libustream-ssl.so") then
15 m = SimpleForm("error", nil, translate("SSL support not available, please install an libustream-ssl variant to use this package."))
21 if not fs.access(res_input) then
22 luci.sys.call("env -i /bin/uclient-fetch --no-check-certificate -O " .. res_input .. " " .. url .. " >/dev/null 2>&1")
25 if not uci:get_first("dnscrypt-proxy", "global") then
26 uci:add("dnscrypt-proxy", "global")
27 uci:save("dnscrypt-proxy")
28 uci:commit("dnscrypt-proxy")
31 for line in io.lines(res_input) do
32 local name = line:match("^[%w_.-]*")
33 res_list[#res_list + 1] = { name = name }
36 m = Map("dnscrypt-proxy", translate("DNSCrypt-Proxy"),
37 translate("Configuration of the DNSCrypt-Proxy package. ")
38 .. translate("Keep in mind to configure Dnsmasq as well. ")
39 .. translatef("For further information "
40 .. "<a href=\"%s\" target=\"_blank\">"
41 .. "see the wiki online</a>", "https://wiki.openwrt.org/inbox/dnscrypt"))
43 function m.on_after_commit(self)
44 luci.sys.call("env -i /etc/init.d/dnsmasq restart >/dev/null 2>&1")
45 luci.sys.call("env -i /etc/init.d/dnscrypt-proxy restart >/dev/null 2>&1")
48 s = m:section(TypedSection, "global", translate("General options"))
51 -- Main dnscrypt-proxy resource list
53 o1 = s:option(DummyValue, "", translate("Default Resolver List"))
54 o1.template = "dnscrypt-proxy/res_options"
57 o2 = s:option(DummyValue, "", translate("File Date"))
58 o2.template = "dnscrypt-proxy/res_options"
59 o2.value = date.to_http(nixio.fs.stat(res_input).mtime)
61 o3 = s:option(DummyValue, "", translate("File Checksum"))
62 o3.template = "dnscrypt-proxy/res_options"
63 o3.value = luci.sys.exec("sha256sum " .. res_input .. " | awk '{print $1}'")
65 btn = s:option(Button, "", translate("Refresh Resolver List"))
66 btn.inputtitle = translate("Refresh List")
67 btn.inputstyle = "apply"
69 function btn.write(self, section, value)
70 luci.sys.call("env -i /bin/uclient-fetch --no-check-certificate -O " .. res_input .. " " .. url .. " >/dev/null 2>&1")
71 luci.http.redirect(luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy"))
76 t = s:option(DynamicList, "procd_trigger", translate("Startup Trigger"),
77 translate("By default the DNSCrypt-Proxy startup will be triggered by ifup events of multiple network interfaces. ")
78 .. translate("To restrict the trigger, add only the relevant network interface(s). ")
79 .. translate("Usually the 'wan' interface should work for most users."))
82 for i, v in ipairs(dump.interface) do
83 if v.interface ~= "loopback" then
92 ds = s:option(DummyValue, "_dummy", translate("Extra options"),
93 translate("Options for further tweaking in case the defaults are not suitable for you."))
94 ds.template = "cbi/nullsection"
96 btn = s:option(Button, "", translate("Create custom config file"),
97 translate("Create '/etc/resolv-crypt.conf' with 'options timeout:1' to reduce DNS upstream timeouts with multiple DNSCrypt instances. ")
98 .. translatef("For further information "
99 .. "<a href=\"%s\" target=\"_blank\">"
100 .. "see the wiki online</a>", "https://wiki.openwrt.org/inbox/dnscrypt"))
101 btn.inputtitle = translate("Create Config File")
102 btn.inputstyle = "apply"
104 function btn.write(self, section, value)
105 if not fs.access("/etc/resolv-crypt.conf") then
106 luci.sys.call("env -i echo 'options timeout:1' > '/etc/resolv-crypt.conf'")
110 -- Mandatory options per instance
112 s = m:section(TypedSection, "dnscrypt-proxy", translate("Instance options"))
116 o1 = s:option(Value, "address", translate("IP Address"),
117 translate("The local IPv4 or IPv6 address. The latter one should be specified within brackets, e.g. '[::1]'."))
118 o1.default = address or "127.0.0.1"
121 o2 = s:option(Value, "port", translate("Port"),
122 translate("The listening port for DNS queries."))
127 o3 = s:option(ListValue, "resolver", translate("Resolver"),
128 translate("Name of the remote DNS service for resolving queries."))
129 o3.datatype = "hostname"
132 for i, v in ipairs(res_list) do
133 if v.name ~= "Name" then
137 o3.default = resolver
140 -- Extra options per instance
142 e1 = s:option(Value, "resolvers_list", translate("Alternate Resolver List"),
143 translate("Specify a non-default Resolver List."))
147 e2 = s:option(Value, "ephemeral_keys", translate("Ephemeral Keys"),
148 translate("Improve privacy by using an ephemeral public key for each query. ")
149 .. translate("This option requires extra CPU cycles and is useless with most DNSCrypt server."))
155 e3 = s:option(DynamicList, "blacklist", translate("Blacklist"),
156 translate("Local blacklists allow you to block abuse sites by domains or ip addresses. ")
157 .. translate("The value for this property is the blocklist type and path to the file, e.g.'domains:/path/to/dbl.txt' or 'ips:/path/to/ipbl.txt'."))
160 e4 = s:option(Value, "block_ipv6", translate("Block IPv6"),
161 translate("Disable IPv6 to speed up DNSCrypt-Proxy."))
166 e5 = s:option(Value, "local_cache", translate("Local Cache"),
167 translate("Enable Caching to speed up DNSCcrypt-Proxy."))
172 e6 = s:option(Value, "query_log_file", translate("DNS Query Logfile"),
173 translate("Log the received DNS queries to a file, so you can watch in real-time what is happening on the network."))