From 14dca2f3eef863c03b87bf21dc5787a524d84b62 Mon Sep 17 00:00:00 2001 From: Dirk Brenken Date: Wed, 16 Aug 2017 21:49:20 +0200 Subject: [PATCH] luci-app-dnscrypt-proxy: new package to ease the dnscrypt-proxy configuration I've build this package, main features: * full resolver list handling, incl. list refresh and simple resolver selection per instance * trigger support * support the following (conditional) options: * resolvers_list * ephemeral_keys * blacklist * block_ipv6 * local_cache * query_log_file Signed-off-by: Dirk Brenken --- applications/luci-app-dnscrypt-proxy/Makefile | 13 ++ .../luasrc/controller/dnscrypt-proxy.lua | 32 ++++ .../cbi/dnscrypt-proxy/cfg_dnsmasq_tab.lua | 37 +++++ .../cbi/dnscrypt-proxy/configuration_tab.lua | 39 +++++ .../model/cbi/dnscrypt-proxy/overview_tab.lua | 147 ++++++++++++++++++ .../luasrc/view/dnscrypt-proxy/config_css.htm | 13 ++ .../luasrc/view/dnscrypt-proxy/logread.htm | 15 ++ .../view/dnscrypt-proxy/res_options.htm | 10 ++ .../view/dnscrypt-proxy/view_reslist.htm | 15 ++ .../etc/uci-defaults/60_luci-dnscrypt-proxy | 11 ++ 10 files changed, 332 insertions(+) create mode 100644 applications/luci-app-dnscrypt-proxy/Makefile create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/cfg_dnsmasq_tab.lua create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/configuration_tab.lua create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/config_css.htm create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/logread.htm create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/res_options.htm create mode 100644 applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/view_reslist.htm create mode 100755 applications/luci-app-dnscrypt-proxy/root/etc/uci-defaults/60_luci-dnscrypt-proxy diff --git a/applications/luci-app-dnscrypt-proxy/Makefile b/applications/luci-app-dnscrypt-proxy/Makefile new file mode 100644 index 0000000000..ec4a1d9769 --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/Makefile @@ -0,0 +1,13 @@ +# Copyright 2017 Dirk Brenken (dev@brenken.org) +# This is free software, licensed under the Apache License, Version 2.0 +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI support for DNSCrypt-Proxy +LUCI_DEPENDS:=+libustream-mbedtls +dnscrypt-proxy +LUCI_PKGARCH:=all + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua b/applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua new file mode 100644 index 0000000000..6d6790a839 --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua @@ -0,0 +1,32 @@ +-- Copyright 2017 Dirk Brenken (dev@brenken.org) +-- This is free software, licensed under the Apache License, Version 2.0 + +module("luci.controller.dnscrypt-proxy", package.seeall) + +local util = require("luci.util") +local i18n = require("luci.i18n") +local templ = require("luci.template") + +function index() + if not nixio.fs.access("/etc/config/dnscrypt-proxy") then + nixio.fs.writefile("/etc/config/dnscrypt-proxy", "") + end + entry({"admin", "services", "dnscrypt-proxy"}, firstchild(), _("DNSCrypt-Proxy"), 60).dependent = false + entry({"admin", "services", "dnscrypt-proxy", "tab_from_cbi"}, cbi("dnscrypt-proxy/overview_tab", {hideresetbtn=true, hidesavebtn=true}), _("Overview"), 10).leaf = true + entry({"admin", "services", "dnscrypt-proxy", "logfile"}, call("logread"), _("View Logfile"), 20).leaf = true + entry({"admin", "services", "dnscrypt-proxy", "advanced"}, firstchild(), _("Advanced"), 100) + entry({"admin", "services", "dnscrypt-proxy", "advanced", "configuration"}, cbi("dnscrypt-proxy/configuration_tab"), _("Edit DNSCrypt-Proxy Configuration"), 110).leaf = true + entry({"admin", "services", "dnscrypt-proxy", "advanced", "cfg_dnsmasq"}, cbi("dnscrypt-proxy/cfg_dnsmasq_tab"), _("Edit Dnsmasq Configuration"), 120).leaf = true + entry({"admin", "services", "dnscrypt-proxy", "advanced", "view_reslist"}, call("view_reslist"), _("View Resolver List"), 130).leaf = true + +end + +function view_reslist() + local reslist = util.trim(util.exec("cat /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv")) + templ.render("dnscrypt-proxy/view_reslist", {title = i18n.translate("DNSCrypt-Proxy Resolver List"), content = reslist}) +end + +function logread() + local logfile = util.trim(util.exec("logread -e 'dnscrypt-proxy'")) + templ.render("dnscrypt-proxy/logread", {title = i18n.translate("DNSCrypt-Proxy Logfile"), content = logfile}) +end diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/cfg_dnsmasq_tab.lua b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/cfg_dnsmasq_tab.lua new file mode 100644 index 0000000000..d22abbfd39 --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/cfg_dnsmasq_tab.lua @@ -0,0 +1,37 @@ +-- Copyright 2017 Dirk Brenken (dev@brenken.org) +-- This is free software, licensed under the Apache License, Version 2.0 + +local nxfs = require("nixio.fs") +local util = require("luci.util") +local uci_input = "/etc/config/dhcp" + +if not nxfs.access(uci_input) then + m = SimpleForm("error", nil, translate("Input file not found, please check your configuration.")) + return m +end + +m = SimpleForm("input", nil) +m:append(Template("dnscrypt-proxy/config_css")) +m.submit = translate("Save") +m.reset = false + +s = m:section(SimpleSection, nil, + translate("This form allows you to modify the content of the main Dnsmasq configuration file (/etc/config/dhcp).")) + +f = s:option(TextValue, "data") +f.rows = 20 +f.rmempty = true + +function f.cfgvalue() + return nxfs.readfile(uci_input) or "" +end + +function f.write(self, section, data) + return nxfs.writefile(uci_input, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n") +end + +function s.handle(self, state, data) + return true +end + +return m diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/configuration_tab.lua b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/configuration_tab.lua new file mode 100644 index 0000000000..f1842731d5 --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/configuration_tab.lua @@ -0,0 +1,39 @@ +-- Copyright 2017 Dirk Brenken (dev@brenken.org) +-- This is free software, licensed under the Apache License, Version 2.0 + +local nxfs = require("nixio.fs") +local util = require("luci.util") +local uci_input = "/etc/config/dnscrypt-proxy" + +if not nxfs.access(uci_input) then + m = SimpleForm("error", nil, translate("Input file not found, please check your configuration.")) + m.reset = false + m.submit = false + return m +end + +m = SimpleForm("input", nil) +m:append(Template("dnscrypt-proxy/config_css")) +m.submit = translate("Save") +m.reset = false + +s = m:section(SimpleSection, nil, + translate("This form allows you to modify the content of the main DNSCrypt-Proxy configuration file (/etc/config/dnscrypt-proxy).")) + +f = s:option(TextValue, "data") +f.rows = 20 +f.rmempty = true + +function f.cfgvalue() + return nxfs.readfile(uci_input) or "" +end + +function f.write(self, section, data) + return nxfs.writefile(uci_input, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n") +end + +function s.handle(self, state, data) + return true +end + +return m diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua new file mode 100644 index 0000000000..ea61366b13 --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua @@ -0,0 +1,147 @@ +-- Copyright 2017 Dirk Brenken (dev@brenken.org) +-- This is free software, licensed under the Apache License, Version 2.0 + +local fs = require("nixio.fs") +local uci = require("luci.model.uci").cursor() +local util = require("luci.util") +local date = require("luci.http.protocol.date") +local res_input = "/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv" +local dump = util.ubus("network.interface", "dump", {}) +local plug_cnt = tonumber(luci.sys.exec("env -i /usr/sbin/dnscrypt-proxy --version | grep 'Support for plugins: present' | wc -l")) +local res_list = {} +local url = "https://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-resolvers.csv" + +if not fs.access(res_input) then + luci.sys.call("env -i /bin/uclient-fetch --no-check-certificate -O " .. res_input .. " " .. url .. " >/dev/null 2>&1") +end + +for line in io.lines(res_input) do + local name = line:match("^[%w_.-]*") + res_list[#res_list + 1] = { name = name } +end + +m = Map("dnscrypt-proxy", translate("DNSCrypt-Proxy"), + translate("Configuration of the DNSCrypt-Proxy package. ") + .. translate("Keep in mind to configure Dnsmasq as well. ") + .. translatef("For further information " + .. "" + .. "see the wiki online", "https://wiki.openwrt.org/inbox/dnscrypt")) + +function m.on_after_commit(self) + luci.sys.call("env -i /etc/init.d/dnsmasq restart >/dev/null 2>&1") + luci.sys.call("env -i /etc/init.d/dnscrypt-proxy restart >/dev/null 2>&1") +end + +-- Trigger selection + +s = m:section(TypedSection, "global", "General options") +s.anonymous = true + +-- Main dnscrypt-proxy resource list + +o1 = s:option(DummyValue, "", translate("Default Resolver List")) +o1.template = "dnscrypt-proxy/res_options" +o1.value = res_input + +o2 = s:option(DummyValue, "", translate("File Date")) +o2.template = "dnscrypt-proxy/res_options" +o2.value = date.to_http(nixio.fs.stat(res_input).mtime) + +o3 = s:option(DummyValue, "", translate("File Checksum")) +o3.template = "dnscrypt-proxy/res_options" +o3.value = luci.sys.exec("sha256sum " .. res_input .. " | awk '{print $1}'") + +btn = s:option(Button, "", translate("Refresh Resolver List")) +btn.inputtitle = translate("Refresh List") +btn.inputstyle = "apply" +btn.disabled = false +function btn.write(self, section, value) + luci.sys.call("env -i /bin/uclient-fetch --no-check-certificate -O " .. res_input .. " " .. url .. " >/dev/null 2>&1") + luci.http.redirect(luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy")) +end + +-- Trigger settings + +t = s:option(DynamicList, "procd_trigger", "Startup Trigger", + translate("By default the DNSCrypt-Proxy startup will be triggered by ifup events of multiple network interfaces. ") + .. translate("To restrict the trigger, add only the relevant network interface(s). ") + .. translate("Usually the 'wan' interface should work for most users.")) +if dump then + local i, v + for i, v in ipairs(dump.interface) do + if v.interface ~= "loopback" then + t:value(v.interface) + end + end +end +t.rmempty = true + +-- Mandatory options per instance + +s = m:section(TypedSection, "dnscrypt-proxy", "Instance options") +s.anonymous = true +s.addremove = true + +o1 = s:option(Value, "address", translate("IP Address"), + translate("The local IP address.")) +o1.datatype = "ip4addr" +o1.default = address or "127.0.0.1" +o1.rmempty = false + +o2 = s:option(Value, "port", translate("Port"), + translate("The listening port for DNS queries.")) +o2.datatype = "port" +o2.default = port +o2.rmempty = false + +o3 = s:option(ListValue, "resolver", translate("Resolver"), + translate("Name of the remote DNS service for resolving queries.")) +o3.datatype = "hostname" +o3.widget = "select" +local i, v +for i, v in ipairs(res_list) do + if v.name ~= "Name" then + o3:value(v.name) + end +end +o3.default = resolver +o3.rmempty = false + +-- Extra options per instance + +e1 = s:option(Value, "resolvers_list", translate("Alternate Resolver List"), + translate("Specify a non-default Resolver List.")) +e1.datatype = "file" +e1.optional = true + +e2 = s:option(Value, "ephemeral_keys", translate("Ephemeral Keys"), + translate("Improve privacy by using an ephemeral public key for each query. ") + .. translate("This option requires extra CPU cycles and is useless with most DNSCrypt server.")) +e2.datatype = "bool" +e2.value = 1 +e2.optional = true + +if plug_cnt > 0 then + e3 = s:option(DynamicList, "blacklist", translate("Blacklist"), + translate("Local blacklists allow you to block abuse sites by domains or ip addresses. ") + .. 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'.")) + e3.optional = true + + e4 = s:option(Value, "block_ipv6", translate("Block IPv6"), + translate("Disable IPv6 to speed up DNSCrypt-Proxy.")) + e4.datatype = "bool" + e4.value = 1 + e4.optional = true + + e5 = s:option(Value, "local_cache", translate("Local Cache"), + translate("Enable Caching to speed up DNSCcrypt-Proxy.")) + e5.datatype = "bool" + e5.value = 1 + e5.optional = true + + e6 = s:option(Value, "query_log_file", translate("DNS Query Logfile"), + translate("Log the received DNS queries to a file, so you can watch in real-time what is happening on the network.")) + e6.optional = true +end + +return m diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/config_css.htm b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/config_css.htm new file mode 100644 index 0000000000..2233a15e31 --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/config_css.htm @@ -0,0 +1,13 @@ + diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/logread.htm b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/logread.htm new file mode 100644 index 0000000000..5c5ac6f81f --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/logread.htm @@ -0,0 +1,15 @@ +<%# +Copyright 2017 Dirk Brenken (dev@brenken.org) +This is free software, licensed under the Apache License, Version 2.0 +-%> + +<%+header%> + +
+
+
<%:This form shows the syslog output, pre-filtered for DNSCrypt-Proxy related messages only.%>
+ +
+
+ +<%+footer%> diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/res_options.htm b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/res_options.htm new file mode 100644 index 0000000000..04dc37bc9d --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/res_options.htm @@ -0,0 +1,10 @@ +<%# +Copyright 2017 Dirk Brenken (dev@brenken.org) +This is free software, licensed under the Apache License, Version 2.0 +-%> + +<%+cbi/valueheader%> + + + +<%+cbi/valuefooter%> diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/view_reslist.htm b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/view_reslist.htm new file mode 100644 index 0000000000..76a2300932 --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/luasrc/view/dnscrypt-proxy/view_reslist.htm @@ -0,0 +1,15 @@ +<%# +Copyright 2017 Dirk Brenken (dev@brenken.org) +This is free software, licensed under the Apache License, Version 2.0 +-%> + +<%+header%> + +
+
+
<%:This form shows the content of the current DNSCrypt Resolver List.%>
+ +
+
+ +<%+footer%> diff --git a/applications/luci-app-dnscrypt-proxy/root/etc/uci-defaults/60_luci-dnscrypt-proxy b/applications/luci-app-dnscrypt-proxy/root/etc/uci-defaults/60_luci-dnscrypt-proxy new file mode 100755 index 0000000000..ec4da17c9a --- /dev/null +++ b/applications/luci-app-dnscrypt-proxy/root/etc/uci-defaults/60_luci-dnscrypt-proxy @@ -0,0 +1,11 @@ +#!/bin/sh + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@dnscrypt-proxy[-1] + add ucitrack dnscrypt-proxy + set ucitrack.@dnscrypt-proxy[-1].init=dnscrypt-proxy + commit ucitrack +EOF + +rm -f /tmp/luci-indexcache +exit 0 -- 2.30.2