overview_tab.lua 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. -- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
  2. -- This is free software, licensed under the Apache License, Version 2.0
  3. local fs = require("nixio.fs")
  4. local uci = require("luci.model.uci").cursor()
  5. local util = require("luci.util")
  6. local res_input = "/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv"
  7. local res_dir = fs.dirname(res_input)
  8. local dump = util.ubus("network.interface", "dump", {})
  9. local plug_cnt = tonumber(luci.sys.exec("env -i /usr/sbin/dnscrypt-proxy --version | grep 'Support for plugins: present' | wc -l"))
  10. local res_list = {}
  11. local url = "https://raw.githubusercontent.com/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv"
  12. local _, date = pcall(require, "luci.http.date")
  13. if not date then
  14. _, date = pcall(require, "luci.http.protocol.date")
  15. end
  16. if not fs.access(res_input) then
  17. if not fs.access("/lib/libustream-ssl.so") then
  18. m = SimpleForm("error", nil, translate("No default resolver list and no SSL support available.<br />")
  19. .. translate("Please install a resolver list to '/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv' to use this package."))
  20. m.submit = false
  21. m.reset = false
  22. return m
  23. else
  24. luci.sys.call("env -i /bin/uclient-fetch --no-check-certificate -O " .. res_input .. " " .. url .. " >/dev/null 2>&1")
  25. end
  26. end
  27. if not uci:get_first("dnscrypt-proxy", "global") then
  28. uci:add("dnscrypt-proxy", "global")
  29. uci:save("dnscrypt-proxy")
  30. uci:commit("dnscrypt-proxy")
  31. end
  32. if fs.access(res_input) then
  33. for line in io.lines(res_input) or {} do
  34. local name,
  35. location,
  36. dnssec,
  37. nolog = line:match("^([^,]+),.-,\".-\",\"*(.-)\"*,.-,[0-9],\"*([yesno]+)\"*,\"*([yesno]+)\"*,.*")
  38. if name ~= "" and name ~= "Name" then
  39. if location == "" then
  40. location = "-"
  41. end
  42. if dnssec == "" then
  43. dnssec = "-"
  44. end
  45. if nolog == "" then
  46. nolog = "-"
  47. end
  48. res_list[#res_list + 1] = { name = name, location = location, dnssec = dnssec, nolog = nolog }
  49. end
  50. end
  51. end
  52. m = Map("dnscrypt-proxy", translate("DNSCrypt-Proxy"),
  53. translate("Configuration of the DNSCrypt-Proxy package. ")
  54. .. translatef("For further information "
  55. .. "<a href=\"%s\" target=\"_blank\">"
  56. .. "see the wiki online</a>", "https://openwrt.org/docs/guide-user/services/dns/dnscrypt"))
  57. m:chain("dhcp")
  58. function m.on_after_commit(self)
  59. function d1.validate(self, value, s1)
  60. if value == "1" then
  61. uci:commit("dnscrypt-proxy")
  62. uci:set("dhcp", s1, "noresolv", 1)
  63. if not fs.access("/etc/resolv-crypt.conf") or fs.stat("/etc/resolv-crypt.conf").size == 0 then
  64. uci:set("dhcp", s1, "resolvfile", "/tmp/resolv.conf.auto")
  65. else
  66. uci:set("dhcp", s1, "resolvfile", "/etc/resolv-crypt.conf")
  67. end
  68. local server_list = {}
  69. local cnt = 1
  70. uci:foreach("dnscrypt-proxy", "dnscrypt-proxy", function(s)
  71. server_list[cnt] = s['address'] .. "#" .. s['port']
  72. cnt = cnt + 1
  73. end)
  74. server_list[cnt] = "/pool.ntp.org/8.8.8.8"
  75. uci:set_list("dhcp", s1, "server", server_list)
  76. if cnt > 2 then
  77. uci:set("dhcp", s1, "allservers", 1)
  78. else
  79. uci:set("dhcp", s1, "allservers", 0)
  80. end
  81. uci:save("dhcp")
  82. uci:commit("dhcp")
  83. end
  84. return value
  85. end
  86. luci.sys.call("env -i /etc/init.d/dnscrypt-proxy restart >/dev/null 2>&1")
  87. luci.sys.call("env -i /etc/init.d/dnsmasq restart >/dev/null 2>&1")
  88. end
  89. s = m:section(TypedSection, "global", translate("General Options"))
  90. s.anonymous = true
  91. -- Main dnscrypt-proxy resource list
  92. o1 = s:option(DummyValue, "", translate("Default Resolver List"))
  93. o1.template = "dnscrypt-proxy/res_options"
  94. o1.value = res_input
  95. o2 = s:option(DummyValue, "", translate("File Date"))
  96. o2.template = "dnscrypt-proxy/res_options"
  97. if fs.access(res_input) then
  98. o2.value = date.to_http(fs.stat(res_input).mtime)
  99. else
  100. o2.value = "-"
  101. end
  102. o3 = s:option(DummyValue, "", translate("File Checksum"))
  103. o3.template = "dnscrypt-proxy/res_options"
  104. if fs.access(res_input) then
  105. o3.value = luci.sys.exec("sha256sum " .. res_input .. " | awk '{print $1}'")
  106. else
  107. o3.value = "-"
  108. end
  109. if fs.access("/lib/libustream-ssl.so") then
  110. btn1 = s:option(Button, "", translate("Refresh Resolver List"),
  111. translate("Download the current resolver list from 'github.com/dyne/dnscrypt-proxy'."))
  112. btn1.inputtitle = translate("Refresh List")
  113. btn1.inputstyle = "apply"
  114. btn1.disabled = false
  115. function btn1.write()
  116. if not fs.access(res_dir) then
  117. fs.mkdir(res_dir)
  118. end
  119. luci.sys.call("env -i /bin/uclient-fetch --no-check-certificate -O " .. res_input .. " " .. url .. " >/dev/null 2>&1")
  120. luci.http.redirect(luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy"))
  121. end
  122. else
  123. btn1 = s:option(Button, "", translate("Refresh Resolver List"),
  124. translate("No SSL support available.<br />")
  125. .. translate("Please install a 'libustream-ssl' library to download the current resolver list from 'github.com/dyne/dnscrypt-proxy'."))
  126. btn1.inputtitle = translate("-------")
  127. btn1.inputstyle = "button"
  128. btn1.disabled = true
  129. end
  130. if not fs.access("/etc/resolv-crypt.conf") or fs.stat("/etc/resolv-crypt.conf").size == 0 then
  131. btn2 = s:option(Button, "", translate("Create Custom Config File"),
  132. translate("Create '/etc/resolv-crypt.conf' with 'options timeout:1' to reduce DNS upstream timeouts with multiple DNSCrypt instances.<br />")
  133. .. translatef("For further information "
  134. .. "<a href=\"%s\" target=\"_blank\">"
  135. .. "see the wiki online</a>", "https://openwrt.org/docs/guide-user/services/dns/dnscrypt"))
  136. btn2.inputtitle = translate("Create Config File")
  137. btn2.inputstyle = "apply"
  138. btn2.disabled = false
  139. function btn2.write()
  140. luci.sys.call("env -i echo 'options timeout:1' > '/etc/resolv-crypt.conf'")
  141. luci.http.redirect(luci.dispatcher.build_url("admin", "services", "dnscrypt-proxy"))
  142. end
  143. else
  144. btn2 = s:option(Button, "", translate("Create Custom Config File"),
  145. translate("The config file '/etc/resolv-crypt.conf' already exist.<br />")
  146. .. translate("Please edit the file manually in the 'Advanced' section."))
  147. btn2.inputtitle = translate("-------")
  148. btn2.inputstyle = "button"
  149. btn2.disabled = true
  150. end
  151. -- Trigger settings
  152. t = s:option(ListValue, "procd_trigger", translate("Startup Trigger"),
  153. translate("By default the DNSCrypt-Proxy startup will be triggered by ifup events of 'All' available network interfaces.<br />")
  154. .. translate("To restrict the trigger, select only the relevant network interface. Usually the 'wan' interface should work for most users."))
  155. t:value("", "All")
  156. if dump then
  157. local i, v
  158. for i, v in ipairs(dump.interface) do
  159. if v.interface ~= "loopback" then
  160. t:value(v.interface)
  161. end
  162. end
  163. end
  164. t.default = procd_trigger or "All"
  165. t.rmempty = true
  166. -- Mandatory options per instance
  167. s = m:section(TypedSection, "dnscrypt-proxy", translate("Instance Options"))
  168. s.anonymous = true
  169. s.addremove = true
  170. i1 = s:option(Value, "address", translate("IP Address"),
  171. translate("The local IPv4 or IPv6 address. The latter one should be specified within brackets, e.g. '[::1]'."))
  172. i1.default = address or "127.0.0.1"
  173. i1.rmempty = false
  174. i2 = s:option(Value, "port", translate("Port"),
  175. translate("The listening port for DNS queries."))
  176. i2.datatype = "port"
  177. i2.default = port
  178. i2.rmempty = false
  179. i3 = s:option(ListValue, "resolver", translate("Resolver (LOC/SEC/NOLOG)"),
  180. translate("Name of the remote DNS service for resolving queries incl. Location, DNSSEC- and NOLOG-Flag."))
  181. i3.datatype = "hostname"
  182. i3.widget = "select"
  183. local i, v
  184. for i, v in ipairs(res_list) do
  185. if v.name then
  186. i3:value(v.name, v.name .. " (" .. v.location .. "/" .. v.dnssec .. "/" .. v.nolog .. ")")
  187. end
  188. end
  189. i3.default = resolver
  190. i3.rmempty = false
  191. -- Extra options per instance
  192. e1 = s:option(Value, "resolvers_list", translate("Alternate Resolver List"),
  193. translate("Specify a non-default Resolver List."))
  194. e1.datatype = "file"
  195. e1.optional = true
  196. e2 = s:option(Value, "ephemeral_keys", translate("Ephemeral Keys"),
  197. translate("Improve privacy by using an ephemeral public key for each query. ")
  198. .. translate("This option requires extra CPU cycles and is useless with most DNSCrypt server."))
  199. e2.datatype = "bool"
  200. e2.value = 1
  201. e2.optional = true
  202. if plug_cnt > 0 then
  203. e3 = s:option(DynamicList, "blacklist", translate("Blacklist"),
  204. translate("Local blacklists allow you to block abuse sites by domains or ip addresses. ")
  205. .. 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'."))
  206. e3.optional = true
  207. e4 = s:option(Value, "block_ipv6", translate("Block IPv6"),
  208. translate("Disable IPv6 to speed up DNSCrypt-Proxy."))
  209. e4.datatype = "bool"
  210. e4.value = 1
  211. e4.optional = true
  212. e5 = s:option(Value, "local_cache", translate("Local Cache"),
  213. translate("Enable Caching to speed up DNSCcrypt-Proxy."))
  214. e5.datatype = "bool"
  215. e5.value = 1
  216. e5.optional = true
  217. e6 = s:option(Value, "query_log_file", translate("DNS Query Logfile"),
  218. translate("Log the received DNS queries to a file, so you can watch in real-time what is happening on the network."))
  219. e6.optional = true
  220. end
  221. -- Dnsmasq options
  222. m1 = Map("dhcp")
  223. s1 = m1:section(TypedSection, "dnsmasq", translate("Dnsmasq Options"))
  224. s1.anonymous = true
  225. d1 = s1:option(Flag, "", translate("Transfer Options To Dnsmasq"),
  226. translate("Apply DNSCrypt-Proxy specific settings to the Dnsmasq configuration.<br />")
  227. .. translate("Please note: This may change the values for 'noresolv', 'resolvfile', 'allservers' and the list 'server' settings."))
  228. d1.default = d1.enabled
  229. d1.rmempty = false
  230. return m, m1