smartdns.lua 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. --
  2. -- Copyright (C) 2018-2023 Ruilin Peng (Nick) <[email protected]>.
  3. --
  4. -- smartdns is free software: you can redistribute it and/or modify
  5. -- it under the terms of the GNU General Public License as published by
  6. -- the Free Software Foundation, either version 3 of the License, or
  7. -- (at your option) any later version.
  8. --
  9. -- smartdns is distributed in the hope that it will be useful,
  10. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. -- GNU General Public License for more details.
  13. --
  14. -- You should have received a copy of the GNU General Public License
  15. -- along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. require ("nixio.fs")
  17. require ("luci.http")
  18. require ("luci.dispatcher")
  19. require ("nixio.fs")
  20. local uci = require "luci.model.uci".cursor()
  21. m = Map("smartdns")
  22. m.title = translate("SmartDNS Server")
  23. m.description = translate("SmartDNS is a local high-performance DNS server, supports finding fastest IP, supports ad filtering, and supports avoiding DNS poisoning.")
  24. m:section(SimpleSection).template = "smartdns/smartdns_status"
  25. -- Basic
  26. s = m:section(TypedSection, "smartdns", translate("Settings"), translate("General Settings"))
  27. s.anonymous = true
  28. s:tab("settings", translate("General Settings"))
  29. s:tab("advanced", translate('Advanced Settings'))
  30. s:tab("seconddns", translate("Second Server Settings"))
  31. s:tab("dns64", translate("DNS64 Server Settings"))
  32. s:tab("proxy", translate("Proxy Server Settings"))
  33. s:tab("custom", translate("Custom Settings"))
  34. ---- Eanble
  35. o = s:taboption("settings", Flag, "enabled", translate("Enable"), translate("Enable or disable smartdns server"))
  36. o.default = o.disabled
  37. o.rempty = false
  38. ---- server name
  39. o = s:taboption("settings", Value, "server_name", translate("Server Name"), translate("Smartdns server name"))
  40. o.default = "smartdns"
  41. o.datatype = "hostname"
  42. o.rempty = false
  43. ---- Port
  44. o = s:taboption("settings", Value, "port", translate("Local Port"),
  45. translate("Smartdns local server port, smartdns will be automatically set as main dns when the port is 53."))
  46. o.placeholder = 53
  47. o.default = 53
  48. o.datatype = "port"
  49. o.rempty = false
  50. -- Automatically Set Dnsmasq
  51. o = s:taboption("settings", Flag, "auto_set_dnsmasq", translate("Automatically Set Dnsmasq"), translate("Automatically set as upstream of dnsmasq when port changes."))
  52. o.rmempty = false
  53. o.default = o.enabled
  54. o.cfgvalue = function(...)
  55. return Flag.cfgvalue(...) or "0"
  56. end
  57. ---- Speed check mode;
  58. o = s:taboption("advanced", Value, "speed_check_mode", translate("Speed Check Mode"), translate("Smartdns speed check mode."));
  59. o.rmempty = true;
  60. o.placeholder = "default";
  61. o.default = o.enabled;
  62. o:value("", translate("default"))
  63. o:value("ping,tcp:80,tcp:443");
  64. o:value("ping,tcp:443,tcp:80");
  65. o:value("tcp:80,tcp:443,ping");
  66. o:value("tcp:443,tcp:80,ping");
  67. o:value("none", translate("None"));
  68. function o.validate (section_id, value)
  69. if value == "" then
  70. return value
  71. end
  72. if value == nil then
  73. return nil, translate("Speed check mode is invalid.")
  74. end
  75. if value == "none" then
  76. return value
  77. end
  78. local mode = value:split(",");
  79. for _, v in ipairs(mode) do repeat
  80. if v == "ping" then
  81. break
  82. end
  83. if v == nil then
  84. return nil, translate("Speed check mode is invalid.")
  85. end
  86. local port = v:split(":");
  87. if "tcp" == port[1] then
  88. if tonumber(port[2]) then
  89. break
  90. end
  91. end
  92. return nil, translate("Speed check mode is invalid.")
  93. until true end
  94. return value
  95. end
  96. ---- response mode;
  97. o = s:taboption("advanced", ListValue, "response_mode", translate("Response Mode"),
  98. translate("Smartdns response mode, First Ping: return the first ping IP, Fastest IP: return the fastest IP, Fastest Response: return the fastest DNS response."))
  99. o.rmempty = true
  100. o.placeholder = "default"
  101. o:value("", translate("default"))
  102. o:value("first-ping", translate("First Ping"))
  103. o:value("fastest-ip", translate("Fastest IP"))
  104. o:value("fastest-response", translate("Fastest Response"))
  105. ---- Enable TCP server
  106. o = s:taboption("advanced", Flag, "tcp_server", translate("TCP Server"), translate("Enable TCP DNS Server"))
  107. o.rmempty = false
  108. o.default = o.enabled
  109. o.cfgvalue = function(...)
  110. return Flag.cfgvalue(...) or "1"
  111. end
  112. ---- Enable DOT server;
  113. o = s:taboption("advanced", Flag, "tls_server", translate("DOT Server"), translate("Enable DOT DNS Server"))
  114. o.rmempty = false
  115. o.default = o.disabled
  116. o.cfgvalue = function(...)
  117. return Flag.cfgvalue(...) or "0"
  118. end
  119. o = s:taboption("advanced", Value, "tls_server_port", translate("DOT Server Port"), translate("Smartdns DOT server port."))
  120. o.placeholder = 853
  121. o.default = 853
  122. o.datatype = "port"
  123. o.rempty = false
  124. o:depends('tls_server', '1')
  125. ---- Enable DOH server;
  126. o = s:taboption("advanced", Flag, "doh_server", translate("DOH Server"), translate("Enable DOH DNS Server"))
  127. o.rmempty = false
  128. o.default = o.disabled
  129. o.cfgvalue = function(...)
  130. return Flag.cfgvalue(...) or "0"
  131. end
  132. o = s:taboption("advanced", Value, "doh_server_port", translate("DOH Server Port"), translate("Smartdns DOH server port."))
  133. o.placeholder = 843
  134. o.default = 843
  135. o.datatype = "port"
  136. o.rempty = false
  137. o:depends('doh_server', '1')
  138. o = s:taboption("advanced", Value, "bind_cert", translate("Server Cert"), translate("Server certificate file path."))
  139. o.datatype = "string"
  140. o.placeholder = "/var/etc/smartdns/smartdns/smartdns-cert.pem"
  141. o.rempty = true
  142. o:depends('tls_server', '1')
  143. o:depends('doh_server', '1')
  144. o = s:taboption("advanced", Value, "bind_cert_key", translate("Server Cert Key"), translate("Server certificate key file path."))
  145. o.datatype = "string"
  146. o.placeholder = "/var/etc/smartdns/smartdns/smartdns-key.pem"
  147. o.rempty = false
  148. o:depends('tls_server', '1')
  149. o:depends('doh_server', '1')
  150. o = s:taboption("advanced", Value, "bind_cert_key_pass", translate("Server Cert Key Pass"), translate("Server certificate key file password."))
  151. o.datatype = "string"
  152. o.rempty = false
  153. o:depends('tls_server', '1')
  154. o:depends('doh_server', '1')
  155. ---- Support IPV6
  156. o = s:taboption("advanced", Flag, "ipv6_server", translate("IPV6 Server"), translate("Enable IPV6 DNS Server"))
  157. o.rmempty = false
  158. o.default = o.enabled
  159. o.cfgvalue = function(...)
  160. return Flag.cfgvalue(...) or "1"
  161. end
  162. ---- bind to device;
  163. o = s:taboption("advanced", Flag, "bind_device", translate("Bind Device"), translate("Listen only on the specified interfaces."))
  164. o.rmempty = false
  165. o.default = o.enabled
  166. o.cfgvalue = function(...)
  167. return Flag.cfgvalue(...) or "1"
  168. end
  169. ---- bind device name;
  170. o = s:taboption("advanced", Value, "bind_device_name", translate("Bind Device Name"), translate("Name of device name listen on."))
  171. o.placeholder = "default"
  172. o.rempty = true
  173. o.datatype = "string"
  174. ---- Support DualStack ip selection
  175. o = s:taboption("advanced", Flag, "dualstack_ip_selection", translate("Dual-stack IP Selection"), translate("Enable IP selection between IPV4 and IPV6"))
  176. o.rmempty = false
  177. o.default = o.enabled
  178. o.cfgvalue = function(...)
  179. return Flag.cfgvalue(...) or "0"
  180. end
  181. ---- Domain prefetch load
  182. o = s:taboption("advanced", Flag, "prefetch_domain", translate("Domain prefetch"), translate("Enable domain prefetch, accelerate domain response speed."))
  183. o.rmempty = true
  184. o.default = o.disabled
  185. o.cfgvalue = function(...)
  186. return Flag.cfgvalue(...) or "0"
  187. end
  188. ---- Domain Serve expired
  189. o = s:taboption("advanced", Flag, "serve_expired", translate("Serve expired"),
  190. translate("Attempts to serve old responses from cache with a TTL of 0 in the response without waiting for the actual resolution to finish."))
  191. o.rmempty = false
  192. o.default = o.enabled
  193. o.cfgvalue = function(...)
  194. return Flag.cfgvalue(...) or "0"
  195. end
  196. ---- cache-size
  197. o = s:taboption("advanced", Value, "cache_size", translate("Cache Size"), translate("DNS domain result cache size"))
  198. o.rempty = true
  199. ---- cache-persist;
  200. o = s:taboption("advanced", Flag, "cache_persist", translate("Cache Persist"), translate("Write cache to disk on exit and load on startup."))
  201. o.rmempty = false
  202. o.default = o.enabled
  203. o.cfgvalue = function(...)
  204. return Flag.cfgvalue(...) or "1"
  205. end
  206. -- cache-size
  207. o = s:taboption("advanced", Flag, "resolve_local_hostnames", translate("Resolve Local Hostnames"), translate("Resolve local hostnames by reading Dnsmasq lease file."))
  208. o.rmempty = false
  209. o.default = o.enabled
  210. o.cfgvalue = function(...)
  211. return Flag.cfgvalue(...) or "1"
  212. end
  213. -- Force AAAA SOA
  214. o = s:taboption("advanced", Flag, "force_aaaa_soa", translate("Force AAAA SOA"), translate("Force AAAA SOA."))
  215. o.rmempty = true
  216. o.default = o.disabled
  217. o.cfgvalue = function(...)
  218. return Flag.cfgvalue(...) or "0"
  219. end
  220. -- Force HTTPS SOA
  221. o = s:taboption("advanced", Flag, "force_https_soa", translate("Force HTTPS SOA"), translate("Force HTTPS SOA."))
  222. o.rmempty = false
  223. o.default = o.enabled
  224. o.cfgvalue = function(...)
  225. return Flag.cfgvalue(...) or "1"
  226. end
  227. ---- Ipset no speed.
  228. o = s:taboption("advanced", Value, "ipset_no_speed", translate("No Speed IPset Name"),
  229. translate("Ipset name, Add domain result to ipset when speed check fails."));
  230. o.rmempty = true;
  231. o.datatype = "hostname";
  232. o.rempty = true;
  233. ---- NFTset no speed.
  234. o = s:taboption("advanced", Value, "nftset_no_speed", translate("No Speed NFTset Name"),
  235. translate("Nftset name, Add domain result to nftset when speed check fails, format: [#[4|6]:[family#table#set]]"));
  236. o.rmempty = true;
  237. o.datatype = "string";
  238. o.rempty = true;
  239. function o.validate(self, value)
  240. if (value == "") then
  241. return value
  242. end
  243. if (value:match("#[4|6]:[a-zA-Z0-9%-_]+#[a-zA-Z0-9%-_]+#[a-zA-Z0-9%-_]+$")) then
  244. return value
  245. end
  246. return nil, translate("NFTset name format error, format: [#[4|6]:[family#table#set]]")
  247. end
  248. ---- rr-ttl
  249. o = s:taboption("advanced", Value, "rr_ttl", translate("Domain TTL"), translate("TTL for all domain result."))
  250. o.rempty = true
  251. ---- rr-ttl-min
  252. o = s:taboption("advanced", Value, "rr_ttl_min", translate("Domain TTL Min"), translate("Minimum TTL for all domain result."))
  253. o.rempty = true
  254. o.placeholder = "600"
  255. o.default = 600
  256. o.optional = true
  257. ---- rr-ttl-max
  258. o = s:taboption("advanced", Value, "rr_ttl_max", translate("Domain TTL Max"), translate("Maximum TTL for all domain result."))
  259. o.rempty = true
  260. ---- rr-ttl-reply-max
  261. o = s:taboption("advanced", Value, "rr_ttl_reply_max", translate("Reply Domain TTL Max"), translate("Reply maximum TTL for all domain result."))
  262. o.rempty = true
  263. o = s:taboption("advanced", DynamicList, "conf_files", translate("Include Config Files<br>/etc/smartdns/conf.d"),
  264. translate("Include other config files from /etc/smartdns/conf.d or custom path, can be downloaded from the download page."));
  265. uci:foreach("smartdns", "download-file", function(section)
  266. local filetype = section.type
  267. if (filetype ~= 'config') then
  268. return
  269. end
  270. o:value(section.name);
  271. end)
  272. ---- other args
  273. o = s:taboption("advanced", Value, "server_flags", translate("Additional Server Args"), translate("Additional server args, refer to the help description of the bind option."))
  274. o.default = ""
  275. o.rempty = true
  276. o.optional = true
  277. ---- second dns server
  278. ---- Eanble
  279. o = s:taboption("seconddns", Flag, "seconddns_enabled", translate("Enable"), translate("Enable or disable second DNS server."))
  280. o.default = o.disabled
  281. o.rempty = false
  282. ---- Port
  283. o = s:taboption("seconddns", Value, "seconddns_port", translate("Local Port"), translate("Smartdns local server port"))
  284. o.placeholder = 6553
  285. o.default = 6553
  286. o.datatype = "port"
  287. o.rempty = false
  288. ---- Enable TCP server
  289. o = s:taboption("seconddns", Flag, "seconddns_tcp_server", translate("TCP Server"), translate("Enable TCP DNS Server"))
  290. o.rmempty = false
  291. o.default = o.enabled
  292. o.cfgvalue = function(...)
  293. return Flag.cfgvalue(...) or "1"
  294. end
  295. ---- dns server group
  296. o = s:taboption("seconddns", Value, "seconddns_server_group", translate("Server Group"), translate("Query DNS through specific dns server group, such as office, home."))
  297. o.rmempty = true
  298. o.placeholder = "default"
  299. o.datatype = "hostname"
  300. o.rempty = true
  301. o = s:taboption("seconddns", Flag, "seconddns_no_speed_check", translate("Skip Speed Check"), translate("Do not check speed."))
  302. o.rmempty = true
  303. o.default = o.disabled
  304. o.cfgvalue = function(...)
  305. return Flag.cfgvalue(...) or "0"
  306. end
  307. ---- skip address rules
  308. o = s:taboption("seconddns", Flag, "seconddns_no_rule_addr", translate("Skip Address Rules"), translate("Skip address rules."))
  309. o.rmempty = true
  310. o.default = o.disabled
  311. o.cfgvalue = function(...)
  312. return Flag.cfgvalue(...) or "0"
  313. end
  314. ---- skip name server rules
  315. o = s:taboption("seconddns", Flag, "seconddns_no_rule_nameserver", translate("Skip Nameserver Rule"), translate("Skip nameserver rules."))
  316. o.rmempty = true
  317. o.default = o.disabled
  318. o.cfgvalue = function(...)
  319. return Flag.cfgvalue(...) or "0"
  320. end
  321. ---- skip ipset rules
  322. o = s:taboption("seconddns", Flag, "seconddns_no_rule_ipset", translate("Skip Ipset Rule"), translate("Skip ipset rules."))
  323. o.rmempty = true
  324. o.default = o.disabled
  325. o.cfgvalue = function(...)
  326. return Flag.cfgvalue(...) or "0"
  327. end
  328. ---- skip soa address rule
  329. o = s:taboption("seconddns", Flag, "seconddns_no_rule_soa", translate("Skip SOA Address Rule"), translate("Skip SOA address rules."))
  330. o.rmempty = true
  331. o.default = o.disabled
  332. o.cfgvalue = function(...)
  333. return Flag.cfgvalue(...) or "0"
  334. end
  335. o = s:taboption("seconddns", Flag, "seconddns_no_dualstack_selection", translate("Skip Dualstack Selection"), translate("Skip Dualstack Selection."))
  336. o.rmempty = true
  337. o.default = o.disabled
  338. o.cfgvalue = function(...)
  339. return Flag.cfgvalue(...) or "0"
  340. end
  341. ---- skip cache
  342. o = s:taboption("seconddns", Flag, "seconddns_no_cache", translate("Skip Cache"), translate("Skip Cache."))
  343. o.rmempty = true
  344. o.default = o.disabled
  345. o.cfgvalue = function(...)
  346. return Flag.cfgvalue(...) or "0"
  347. end
  348. ---- Force AAAA SOA
  349. o = s:taboption("seconddns", Flag, "seconddns_force_aaaa_soa", translate("Force AAAA SOA"), translate("Force AAAA SOA."))
  350. o.rmempty = true
  351. o.default = o.disabled
  352. o.cfgvalue = function(...)
  353. return Flag.cfgvalue(...) or "0"
  354. end
  355. o = s:taboption("seconddns", Value, "seconddns_ipset_name", translate("IPset Name"), translate("IPset name."))
  356. o.rmempty = true
  357. o.datatype = "hostname"
  358. o.rempty = true
  359. o = s:taboption("seconddns", Value, "seconddns_nftset_name", translate("NFTset Name"), translate("NFTset name, format: [#[4|6]:[family#table#set]]"))
  360. o.rmempty = true
  361. o.datatype = "string"
  362. o.rempty = true
  363. function o.validate(self, value)
  364. if (value == "") then
  365. return value
  366. end
  367. if (value:match("#[4|6]:[a-zA-Z0-9%-_]+#[a-zA-Z0-9%-_]+#[a-zA-Z0-9%-_]+$")) then
  368. return value
  369. end
  370. return nil, translate("NFTset name format error, format: [#[4|6]:[family#table#set]]")
  371. end
  372. ---- other args
  373. o = s:taboption("seconddns", Value, "seconddns_server_flags", translate("Additional Server Args"), translate("Additional server args, refer to the help description of the bind option."))
  374. o.default = ""
  375. o.rempty = true
  376. o.optional = true
  377. ----- Proxy server settings
  378. o = s:taboption("proxy", Value, "proxy_server", translate("Proxy Server"), translate("Proxy Server URL, format: [socks5|http]://user:pass@ip:port."));
  379. o.datatype = 'string';
  380. function o.validate(self, value)
  381. if (value == "") then
  382. return true
  383. end
  384. if (not value:match("^http://") and not value:match("^socks5://")) then
  385. return nil, translate("Proxy server URL format error, format: [socks5|http]://user:pass@ip:port.")
  386. end
  387. return value
  388. end
  389. ----- dns64 server settings
  390. o = s:taboption("dns64", Value, "dns64", translate("DNS64"));
  391. o.placeholder = "64:ff9b::/96"
  392. o.datatype = 'ip6addr'
  393. o.rmempty = true
  394. ----- custom settings
  395. custom = s:taboption("custom", Value, "Custom Settings",
  396. translate(""),
  397. translate("smartdns custom settings"))
  398. custom.template = "cbi/tvalue"
  399. custom.rows = 20
  400. function custom.cfgvalue(self, section)
  401. return nixio.fs.readfile("/etc/smartdns/custom.conf")
  402. end
  403. function custom.write(self, section, value)
  404. value = value:gsub("\r\n?", "\n")
  405. nixio.fs.writefile("/etc/smartdns/custom.conf", value)
  406. end
  407. o = s:taboption("custom", Flag, "coredump", translate("Generate Coredump"), translate("Generate Coredump file when smartdns crash, coredump file is located at /tmp/smartdns.xxx.core."))
  408. o.rmempty = true
  409. o.default = o.disabled
  410. o.cfgvalue = function(...)
  411. return Flag.cfgvalue(...) or "0"
  412. end
  413. o = s:taboption("custom", Value, "log_size", translate("Log Size"))
  414. o.rmempty = true
  415. o.placeholder = "default"
  416. o = s:taboption("custom", ListValue, "log_level", translate("Log Level"))
  417. o.rmempty = true
  418. o.placeholder = "default"
  419. o:value("", translate("default"))
  420. o:value("debug")
  421. o:value("info")
  422. o:value("notice")
  423. o:value("warn")
  424. o:value("error")
  425. o:value("fatal")
  426. o:value("off")
  427. o = s:taboption("custom", Value, "log_num", translate("Log Number"))
  428. o.rmempty = true
  429. o.placeholder = "default"
  430. o = s:taboption("custom", Value, "log_file", translate("Log File"))
  431. o.rmempty = true
  432. o.placeholder = "/var/log/smartdns/smartdns.log"
  433. -- Upstream servers
  434. s = m:section(TypedSection, "server", translate("Upstream Servers"), translate("Upstream Servers, support UDP, TCP protocol. " ..
  435. "Please configure multiple DNS servers, including multiple foreign DNS servers."))
  436. s.anonymous = true
  437. s.addremove = true
  438. s.template = "cbi/tblsection"
  439. s.extedit = luci.dispatcher.build_url("admin/services/smartdns/upstream/%s")
  440. ---- enable flag
  441. o = s:option(Flag, "enabled", translate("Enable"), translate("Enable"))
  442. o.rmempty = false
  443. o.default = o.enabled
  444. o.cfgvalue = function(...)
  445. return Flag.cfgvalue(...) or "1"
  446. end
  447. ---- name
  448. s:option(Value, "name", translate("DNS Server Name"), translate("DNS Server Name"))
  449. ---- IP address
  450. o = s:option(Value, "ip", translate("ip"), translate("DNS Server ip"))
  451. o.datatype = "or(ipaddr, string)"
  452. o.rmempty = false
  453. ---- port
  454. o = s:option(Value, "port", translate("port"), translate("DNS Server port"))
  455. o.placeholder = "default"
  456. o.datatype = "port"
  457. o.rempty = true
  458. o:depends("type", "udp")
  459. o:depends("type", "tcp")
  460. o:depends("type", "tls")
  461. ---- type
  462. o = s:option(ListValue, "type", translate("type"), translate("DNS Server type"))
  463. o.placeholder = "udp"
  464. o:value("udp", translate("udp"))
  465. o:value("tcp", translate("tcp"))
  466. o:value("tls", translate("tls"))
  467. o:value("https", translate("https"))
  468. o.default = "udp"
  469. o.rempty = false
  470. ---- domain rules;
  471. s = m:section(TypedSection, "domain-rule", translate("Domain Rules"), translate("Domain Rules Settings"))
  472. s.anonymous = true
  473. s.nodescriptions = true
  474. s:tab("forwarding", translate('DNS Forwarding Setting'))
  475. s:tab("block", translate("DNS Block Setting"))
  476. s:tab("domain-address", translate("Domain Address"), translate("Set Specific domain ip address."))
  477. s:tab("blackip-list", translate("IP Blacklist"), translate("Set Specific ip blacklist."))
  478. ---- domain forwarding;
  479. o = s:taboption("forwarding", Value, "server_group", translate("Server Group"), translate("DNS Server group belongs to, such as office, home."))
  480. o.rmempty = true
  481. o.placeholder = "default"
  482. o.datatype = "hostname"
  483. o.rempty = true
  484. uci:foreach("smartdns", "server", function(section)
  485. local server_group = section.server_group
  486. if server_group == nil then
  487. return
  488. end
  489. o:value(server_group);
  490. end)
  491. function o.validate (section_id, value)
  492. if value == "" then
  493. return value
  494. end
  495. if value == nil then
  496. return nil, translate('Server Group not exists')
  497. end
  498. local exists = false
  499. uci:foreach("smartdns", "server", function(section)
  500. local server_group = section.server_group
  501. if (exists == true) then
  502. return
  503. end
  504. if (value == server_group) then
  505. exists = true
  506. end
  507. end)
  508. if exists == false then
  509. return nil, translate('Server Group not exists')
  510. end
  511. return value;
  512. end
  513. o = s:taboption("forwarding", Flag, "no_speed_check", translate("Skip Speed Check"),
  514. translate("Do not check speed."))
  515. o.rmempty = true
  516. o.default = o.disabled
  517. o = s:taboption("forwarding", Flag, "force_aaaa_soa", translate("Force AAAA SOA"), translate("Force AAAA SOA."))
  518. o.rmempty = true
  519. o.default = o.disabled
  520. o = s:taboption("forwarding", Value, "ipset_name", translate("IPset Name"), translate("IPset name."))
  521. o.rmempty = true
  522. o.datatype = "hostname"
  523. o.rempty = true
  524. o = s:taboption("forwarding", Value, "nftset_name", translate("NFTset Name"), translate("NFTset name, format: [#[4|6]:[family#table#set]]"))
  525. o.rmempty = true
  526. o.datatype = "string"
  527. o.rempty = true
  528. function o.validate(self, value)
  529. if (value == "") then
  530. return value
  531. end
  532. if (value:match("#[4|6]:[a-zA-Z0-9%-_]+#[a-zA-Z0-9%-_]+#[a-zA-Z0-9%-_]+$")) then
  533. return value
  534. end
  535. return nil, translate("NFTset name format error, format: [#[4|6]:[family#table#set]]")
  536. end
  537. ---- other args
  538. o = s:taboption("forwarding", Value, "addition_flag", translate("Additional Rule Flag"), translate("Additional Flags for rules, read help on domain-rule for more information."))
  539. o.default = ""
  540. o.rempty = true
  541. o.modalonly = true;
  542. o = s:taboption("forwarding", FileUpload, "forwarding_domain_set_file", translate("Domain List File"),
  543. translate("Upload domain list file, or configure auto download from Download File Setting page."))
  544. o.rmempty = true
  545. o.datatype = "file"
  546. o.rempty = true
  547. o.editable = true
  548. o.root_directory = "/etc/smartdns/domain-set"
  549. o = s:taboption("forwarding", TextValue, "domain_forwarding_list",
  550. translate("Domain List"), translate("Configure forwarding domain name list."))
  551. o.rows = 10
  552. o.cols = 64
  553. o.monospace = true
  554. function o.cfgvalue(self, section)
  555. return nixio.fs.readfile("/etc/smartdns/domain-forwarding.list")
  556. end
  557. function o.write(self, section, value)
  558. value = value:gsub("\r\n?", "\n")
  559. nixio.fs.writefile("/etc/smartdns/domain-forwarding.list", value)
  560. end
  561. ---- domain block;
  562. o = s:taboption("block", FileUpload, "block_domain_set_file", translate("Domain List File"), translate("Upload domain list file."))
  563. o.rmempty = true
  564. o.datatype = "file"
  565. o.rempty = true
  566. o.editable = true
  567. o.root_directory = "/etc/smartdns/domain-set"
  568. o = s:taboption("block", TextValue, "domain_block_list",
  569. translate("Domain List"), translate("Configure block domain list."))
  570. o.rows = 10
  571. o.cols = 64
  572. function o.cfgvalue(self, section)
  573. return nixio.fs.readfile("/etc/smartdns/domain-block.list")
  574. end
  575. function o.write(self, section, value)
  576. value = value:gsub("\r\n?", "\n")
  577. nixio.fs.writefile("/etc/smartdns/domain-block.list", value)
  578. end
  579. -- Doman addresss
  580. addr = s:taboption("domain-address", Value, "address",
  581. translate(""),
  582. translate("Specify an IP address to return for any host in the given domains, Queries in the domains are never forwarded and always replied to with the specified IP address which may be IPv4 or IPv6."))
  583. addr.template = "cbi/tvalue"
  584. addr.rows = 20
  585. function addr.cfgvalue(self, section)
  586. return nixio.fs.readfile("/etc/smartdns/address.conf")
  587. end
  588. function addr.write(self, section, value)
  589. value = value:gsub("\r\n?", "\n")
  590. nixio.fs.writefile("/etc/smartdns/address.conf", value)
  591. end
  592. -- IP Blacklist
  593. addr = s:taboption("blackip-list", Value, "blacklist_ip",
  594. translate(""),
  595. translate("Configure IP blacklists that will be filtered from the results of specific DNS server."))
  596. addr.template = "cbi/tvalue"
  597. addr.rows = 20
  598. function addr.cfgvalue(self, section)
  599. return nixio.fs.readfile("/etc/smartdns/blacklist-ip.conf")
  600. end
  601. function addr.write(self, section, value)
  602. value = value:gsub("\r\n?", "\n")
  603. nixio.fs.writefile("/etc/smartdns/blacklist-ip.conf", value)
  604. end
  605. s = m:section(TypedSection, "smartdns", translate("Download Files Setting"), translate("Download domain list files for domain-rule and include config files, please refresh the page after download to take effect."))
  606. s.anonymous = true
  607. ---- download Files Settings
  608. o = s:option(Flag, "enable_auto_update", translate("Enable Auto Update"), translate("Enable daily(week) auto update."))
  609. o.rmempty = true
  610. o.default = o.disabled
  611. o.rempty = true
  612. o = s:option(ListValue, "auto_update_week_time", translate("Update Time (Every Week)"))
  613. o:value("*", translate("Every Day"))
  614. o:value("1", translate("Every Monday"))
  615. o:value("2", translate("Every Tuesday"))
  616. o:value("3", translate("Every Wednesday"))
  617. o:value("4", translate("Every Thursday"))
  618. o:value("5", translate("Every Friday"))
  619. o:value("6", translate("Every Saturday"))
  620. o:value("0", translate("Every Sunday"))
  621. o.default = "*"
  622. o = s:option(ListValue, "auto_update_day_time", translate("Update Time (Every Day)"))
  623. for i = 0, 23 do o:value(i, i .. ":00") end
  624. o.default = 5
  625. o = s:option(FileUpload, "upload_conf_file", translate("Upload Config File"),
  626. translate("Upload smartdns config file to /etc/smartdns/conf.d"))
  627. o.rmempty = true
  628. o.datatype = "file"
  629. o.rempty = true
  630. o.editable = true
  631. o.root_directory = "/etc/smartdns/conf.d"
  632. o = s:option(FileUpload, "upload_list_file", translate("Upload Domain List File"),
  633. translate("Upload domain list file to /etc/smartdns/domain-set"))
  634. o.rmempty = true
  635. o.datatype = "file"
  636. o.rempty = true
  637. o.editable = true
  638. o.root_directory = "/etc/smartdns/domain-set"
  639. o = s:option(Button, "_updateate")
  640. o.title = translate("Update Files")
  641. o.inputtitle = translate("Update Files")
  642. o.inputstyle = "apply"
  643. o.write = function()
  644. luci.sys.call("/etc/init.d/smartdns updatefiles >/dev/null 2>&1")
  645. end
  646. s = m:section(TypedSection, "download-file", translate("Download Files"), translate("List of files to download."))
  647. s.anonymous = true
  648. s.addremove = true
  649. s.template = "cbi/tblsection"
  650. o = s:option(Value, 'name', translate('File Name'), translate('File Name'))
  651. o.rmempty = true
  652. o.datatype = 'string'
  653. o = s:option(Value, 'url', translate('URL'), translate('URL'))
  654. o.rmempty = true
  655. o.datatype = 'string'
  656. function o.validate(self, value, section)
  657. if value == "" then
  658. return nil, translate("URL format error, format: http:// or https://")
  659. end
  660. if value == nil then
  661. return nil, translate("URL format error, format: http:// or https://")
  662. end
  663. if value.find(value, "http://") then
  664. return value
  665. end
  666. if value.find(value, "https://") then
  667. return value
  668. end
  669. return nil, translate("URL format error, format: http:// or https://")
  670. end
  671. o = s:option(ListValue, "type", translate("type"), translate("File Type"))
  672. o:value("list", translate("domain list (/etc/smartdns/domain-set)"))
  673. o:value("config", translate("smartdns config (/etc/smartdns/conf.d)"))
  674. o.default = "list"
  675. o.rempty = false
  676. o = s:option(Value, 'desc', translate('Description'), translate('Description'))
  677. o.rmempty = true
  678. o.datatype = 'string'
  679. -- Technical Support
  680. s = m:section(TypedSection, "smartdns", translate("Technical Support"),
  681. translate("If you like this software, please buy me a cup of coffee."))
  682. s.anonymous = true
  683. o = s:option(Button, "web")
  684. o.title = translate("SmartDNS official website")
  685. o.inputtitle = translate("open website")
  686. o.inputstyle = "apply"
  687. o.write = function()
  688. luci.http.redirect("https://pymumu.github.io/smartdns")
  689. end
  690. o = s:option(Button, "report")
  691. o.title = translate("Report bugs")
  692. o.inputtitle = translate("Report bugs")
  693. o.inputstyle = "apply"
  694. o.write = function()
  695. luci.http.redirect("https://github.com/pymumu/smartdns/issues")
  696. end
  697. o = s:option(Button, "Donate")
  698. o.title = translate("Donate to smartdns")
  699. o.inputtitle = translate("Donate")
  700. o.inputstyle = "apply"
  701. o.write = function()
  702. luci.http.redirect("https://pymumu.github.io/smartdns/#donate")
  703. end
  704. o = s:option(Button, "Restart")
  705. o.title = translate("Restart Service")
  706. o.inputtitle = translate("Restart")
  707. o.inputstyle = "apply"
  708. o.write = function()
  709. luci.sys.call("/etc/init.d/smartdns restart >/dev/null 2>&1")
  710. end
  711. return m