smartdns.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*************************************************************************
  2. *
  3. * Copyright (C) 2018-2020 Ruilin Peng (Nick) <[email protected]>.
  4. *
  5. * smartdns is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * smartdns is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. 'use strict';
  19. 'require fs';
  20. 'require uci';
  21. 'require form';
  22. 'require view';
  23. 'require poll';
  24. 'require rpc';
  25. var conf = 'smartdns';
  26. var callServiceList = rpc.declare({
  27. object: 'service',
  28. method: 'list',
  29. params: ['name'],
  30. expect: { '': {} }
  31. });
  32. function getServiceStatus() {
  33. return L.resolveDefault(callServiceList(conf), {})
  34. .then(function (res) {
  35. var isrunning = false;
  36. try {
  37. isrunning = res[conf]['instances']['smartdns']['running'];
  38. } catch (e) { }
  39. return isrunning;
  40. });
  41. }
  42. function smartdnsServiceStatus() {
  43. return Promise.all([
  44. getServiceStatus()
  45. ]);
  46. }
  47. function smartdnsRenderStatus(res) {
  48. var renderHTML = "";
  49. var isRunning = res[0];
  50. var autoSetDnsmasq = uci.get_first('smartdns', 'smartdns', 'auto_set_dnsmasq');
  51. var smartdnsPort = uci.get_first('smartdns', 'smartdns', 'port');
  52. var dnsmasqServer = uci.get_first('dhcp', 'dnsmasq', 'server');
  53. uci.unload('dhcp');
  54. if (isRunning) {
  55. renderHTML += "<span style=\"color:green;font-weight:bold\">SmartDNS - " + _("RUNNING") + "</span>";
  56. } else {
  57. renderHTML += "<span style=\"color:red;font-weight:bold\">SmartDNS - " + _("NOT RUNNING") + "</span>";
  58. return renderHTML;
  59. }
  60. if (autoSetDnsmasq === '1' && smartdnsPort != '53') {
  61. var matchLine = "127.0.0.1#" + smartdnsPort;
  62. var dnsmasqServer = uci.get_first('dhcp', 'dnsmasq', 'server') || "";
  63. if (dnsmasqServer.indexOf(matchLine) < 0) {
  64. renderHTML += "<br /><span style=\"color:red;font-weight:bold\">" + _("Dnsmasq Forwared To Smartdns Failure") + "</span>";
  65. }
  66. }
  67. return renderHTML;
  68. }
  69. return view.extend({
  70. load: function () {
  71. return Promise.all([
  72. uci.load('dhcp'),
  73. uci.load('smartdns'),
  74. ]);
  75. },
  76. render: function (stats) {
  77. var m, s, o;
  78. m = new form.Map('smartdns', _('SmartDNS'));
  79. m.title = _("SmartDNS Server");
  80. m.description = _("SmartDNS is a local high-performance DNS server, supports finding fastest IP, "
  81. + "supports ad filtering, and supports avoiding DNS poisoning.");
  82. s = m.section(form.NamedSection, '_status');
  83. s.anonymous = true;
  84. s.render = function (section_id) {
  85. var renderStatus = function () {
  86. return L.resolveDefault(smartdnsServiceStatus()).then(function (res) {
  87. var view = document.getElementById("service_status");
  88. if (view == null) {
  89. return;
  90. }
  91. view.innerHTML = smartdnsRenderStatus(res);
  92. });
  93. }
  94. poll.add(renderStatus);
  95. setTimeout(renderStatus, 1000);
  96. return E('div', { class: 'cbi-map' },
  97. E('div', { class: 'cbi-section' }, [
  98. E('div', { id: 'service_status' },
  99. _('Collecting data ...'))
  100. ])
  101. );
  102. }
  103. // Basic;
  104. s = m.section(form.TypedSection, "smartdns", _("Settings"), _("General Settings"));
  105. s.anonymous = true;
  106. s.tab("settings", _("General Settings"));
  107. s.tab("seconddns", _("Second Server Settings"));
  108. s.tab("custom", _("Custom Settings"));
  109. o = s.taboption("settings", form.Flag, "enabled", _("Enable"), _("Enable or disable smartdns server"));
  110. o.rmempty = false;
  111. o.default = o.disabled;
  112. // server name;
  113. o = s.taboption("settings", form.Value, "server_name", _("Server Name"), _("Smartdns server name"));
  114. o.default = "smartdns";
  115. o.datatype = "hostname";
  116. o.rempty = false;
  117. // Port;
  118. o = s.taboption("settings", form.Value, "port", _("Local Port"),
  119. _("Smartdns local server port, smartdns will be automatically set as main dns when the port is 53."));
  120. o.placeholder = 53;
  121. o.default = 53;
  122. o.datatype = "port";
  123. o.rempty = false;
  124. // Enable TCP server;
  125. o = s.taboption("settings", form.Flag, "tcp_server", _("TCP Server"), _("Enable TCP DNS Server"));
  126. o.rmempty = false;
  127. o.default = o.enabled;
  128. // Support IPV6;
  129. o = s.taboption("settings", form.Flag, "ipv6_server", _("IPV6 Server"), _("Enable IPV6 DNS Server"));
  130. o.rmempty = false;
  131. o.default = o.enabled;
  132. // Support DualStack ip selection;
  133. o = s.taboption("settings", form.Flag, "dualstack_ip_selection", _("Dual-stack IP Selection"),
  134. _("Enable IP selection between IPV4 and IPV6"));
  135. o.rmempty = false;
  136. o.default = o.enabled;
  137. // Domain prefetch load ;
  138. o = s.taboption("settings", form.Flag, "prefetch_domain", _("Domain prefetch"),
  139. _("Enable domain prefetch, accelerate domain response speed."));
  140. o.rmempty = false;
  141. o.default = o.disabled;
  142. // Domain Serve expired
  143. o = s.taboption("settings", form.Flag, "serve_expired", _("Serve expired"),
  144. _("Attempts to serve old responses from cache with a TTL of 0 in the response without waiting for the actual resolution to finish."));
  145. o.rmempty = false;
  146. o.default = o.enabled;
  147. // cache-size;
  148. o = s.taboption("settings", form.Value, "cache_size", _("Cache Size"), _("DNS domain result cache size"));
  149. o.rempty = true;
  150. // cache-size;
  151. o = s.taboption("settings", form.Flag, "resolve_local_hostnames", _("Resolve Local Hostnames"), _("Resolve local hostnames by reading Dnsmasq lease file."));
  152. o.rmempty = false;
  153. o.default = o.enabled;
  154. // auto-conf-dnsmasq;
  155. o = s.taboption("settings", form.Flag, "auto_set_dnsmasq", _("Automatically Set Dnsmasq"), _("Automatically set as upstream of dnsmasq when port changes."));
  156. o.rmempty = false;
  157. o.default = o.enabled;
  158. // Force AAAA SOA
  159. o = s.taboption("settings", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
  160. o.rmempty = false;
  161. o.default = o.disabled;
  162. // Force HTTPS SOA
  163. o = s.taboption("settings", form.Flag, "force_https_soa", _("Force HTTPS SOA"), _("Force HTTPS SOA."));
  164. o.rmempty = false;
  165. o.default = o.disabled;
  166. // rr-ttl;
  167. o = s.taboption("settings", form.Value, "rr_ttl", _("Domain TTL"), _("TTL for all domain result."));
  168. o.rempty = true;
  169. // rr-ttl-min;
  170. o = s.taboption("settings", form.Value, "rr_ttl_min", _("Domain TTL Min"),
  171. _("Minimum TTL for all domain result."));
  172. o.rempty = true;
  173. o.placeholder = "600";
  174. o.default = 600;
  175. o.optional = true;
  176. // rr-ttl-max;
  177. o = s.taboption("settings", form.Value, "rr_ttl_max", _("Domain TTL Max"),
  178. _("Maximum TTL for all domain result."));
  179. o.rempty = true;
  180. // rr-ttl-reply-max;
  181. o = s.taboption("settings", form.Value, "rr_ttl_reply_max", _("Reply Domain TTL Max"),
  182. _("Reply maximum TTL for all domain result."));
  183. o.rempty = true;
  184. // second dns server;
  185. // Eanble;
  186. o = s.taboption("seconddns", form.Flag, "seconddns_enabled", _("Enable"),
  187. _("Enable or disable second DNS server."));
  188. o.default = o.disabled;
  189. o.rempty = false;
  190. // Port;
  191. o = s.taboption("seconddns", form.Value, "seconddns_port", _("Local Port"), _("Smartdns local server port"));
  192. o.placeholder = 6553;
  193. o.default = 6553;
  194. o.datatype = "port";
  195. o.rempty = false;
  196. // Enable TCP server;
  197. o = s.taboption("seconddns", form.Flag, "seconddns_tcp_server", _("TCP Server"), _("Enable TCP DNS Server"));
  198. o.rmempty = false;
  199. o.default = o.enabled;
  200. // dns server group;
  201. o = s.taboption("seconddns", form.Value, "seconddns_server_group", _("Server Group"),
  202. _("Query DNS through specific dns server group, such as office, home."));
  203. o.rmempty = true;
  204. o.placeholder = "default";
  205. o.datatype = "hostname";
  206. o.rempty = true;
  207. o = s.taboption("seconddns", form.Flag, "seconddns_no_speed_check", _("Skip Speed Check"),
  208. _("Do not check speed."));
  209. o.rmempty = false;
  210. o.default = o.disabled;
  211. // skip address rules;
  212. o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_addr", _("Skip Address Rules"),
  213. _("Skip address rules."));
  214. o.rmempty = false;
  215. o.default = o.disabled;
  216. // skip name server rules;
  217. o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_nameserver", _("Skip Nameserver Rule"),
  218. _("Skip nameserver rules."));
  219. o.rmempty = false;
  220. o.default = o.disabled;
  221. // skip ipset rules;
  222. o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_ipset", _("Skip Ipset Rule"),
  223. _("Skip ipset rules."));
  224. o.rmempty = false;
  225. o.default = o.disabled;
  226. // skip soa address rule;
  227. o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_soa", _("Skip SOA Address Rule"),
  228. _("Skip SOA address rules."));
  229. o.rmempty = false;
  230. o.default = o.disabled;
  231. o = s.taboption("seconddns", form.Flag, "seconddns_no_dualstack_selection", _("Skip Dualstack Selection"),
  232. _("Skip Dualstack Selection."));
  233. o.rmempty = false;
  234. o.default = o.disabled;
  235. // skip cache;
  236. o = s.taboption("seconddns", form.Flag, "seconddns_no_cache", _("Skip Cache"), _("Skip Cache."));
  237. o.rmempty = false;
  238. o.default = o.disabled;
  239. // Force AAAA SOA
  240. o = s.taboption("seconddns", form.Flag, "seconddns_force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
  241. o.rmempty = false;
  242. o.default = o.disabled;
  243. // custom settings;
  244. o = s.taboption("custom", form.TextValue, "custom_conf",
  245. "", _("smartdns custom settings"));
  246. o.rows = 20;
  247. o.cfgvalue = function (section_id) {
  248. return fs.trimmed('/etc/smartdns/custom.conf');
  249. };
  250. o.write = function (section_id, formvalue) {
  251. return fs.write('/etc/smartdns/custom.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
  252. };
  253. o = s.taboption("custom", form.Flag, "coredump", _("Generate Coredump"),
  254. _("Generate Coredump file when smartdns crash, coredump file is located at /tmp/smartdns.xxx.core."));
  255. o.rmempty = false;
  256. o.default = o.disabled;
  257. // Upstream servers;
  258. s = m.section(form.GridSection, "server", _("Upstream Servers"),
  259. _("Upstream Servers, support UDP, TCP protocol. Please configure multiple DNS servers, "
  260. + "including multiple foreign DNS servers."));
  261. s.anonymous = true;
  262. s.addremove = true;
  263. s.tab('general', _('General Settings'));
  264. s.tab('advanced', _('Advanced Settings'));
  265. // enable flag;
  266. o = s.taboption("general", form.Flag, "enabled", _("Enable"), _("Enable"));
  267. o.rmempty = false;
  268. o.default = o.enabled;
  269. o.editable = true;
  270. // name;
  271. o = s.taboption("general", form.Value, "name", _("DNS Server Name"), _("DNS Server Name"));
  272. // IP address;
  273. o = s.taboption("general", form.Value, "ip", _("ip"), _("DNS Server ip"));
  274. o.datatype = "or(ipaddr, string)";
  275. o.rmempty = false;
  276. // port;
  277. o = s.taboption("general", form.Value, "port", _("port"), _("DNS Server port"));
  278. o.placeholder = "default";
  279. o.datatype = "port";
  280. o.rempty = true;
  281. o.depends("type", "udp");
  282. o.depends("type", "tcp");
  283. o.depends("type", "tls");
  284. // type;
  285. o = s.taboption("general", form.ListValue, "type", _("type"), _("DNS Server type"));
  286. o.placeholder = "udp";
  287. o.value("udp", _("udp"));
  288. o.value("tcp", _("tcp"));
  289. o.value("tls", _("tls"));
  290. o.value("https", _("https"));
  291. o.default = "udp";
  292. o.rempty = false;
  293. // Advanced Options
  294. // server group
  295. o = s.taboption("advanced", form.Value, "server_group", _("Server Group"), _("DNS Server group belongs to, "
  296. + "used with nameserver, such as office, home."))
  297. o.rmempty = true
  298. o.placeholder = "default"
  299. o.datatype = "hostname"
  300. o.rempty = true
  301. o.modalonly = true;
  302. // blacklist_ip
  303. o = s.taboption("advanced", form.Flag, "blacklist_ip", _("IP Blacklist Filtering"),
  304. _("Filtering IP with blacklist"))
  305. o.rmempty = false
  306. o.default = o.disabled
  307. o.modalonly = true;
  308. // TLS host verify
  309. o = s.taboption("advanced", form.Value, "tls_host_verify", _("TLS Hostname Verify"),
  310. _("Set TLS hostname to verify."))
  311. o.default = ""
  312. o.datatype = "string"
  313. o.rempty = true
  314. o.modalonly = true;
  315. o.depends("type", "tls")
  316. o.depends("type", "https")
  317. // certificate verify
  318. o = s.taboption("advanced", form.Flag, "no_check_certificate", _("No check certificate"),
  319. _("Do not check certificate."))
  320. o.rmempty = false
  321. o.default = o.disabled
  322. o.modalonly = true;
  323. o.depends("type", "tls")
  324. o.depends("type", "https")
  325. // SNI host name
  326. o = s.taboption("advanced", form.Value, "host_name", _("TLS SNI name"),
  327. _("Sets the server name indication for query."))
  328. o.default = ""
  329. o.datatype = "hostname"
  330. o.rempty = true
  331. o.modalonly = true;
  332. o.depends("type", "tls")
  333. o.depends("type", "https")
  334. // http host
  335. o = s.taboption("advanced", form.Value, "http_host", _("HTTP Host"),
  336. _("Set the HTTP host used for the query. Use this parameter when the host of the URL address is an IP address."))
  337. o.default = ""
  338. o.datatype = "hostname"
  339. o.rempty = true
  340. o.modalonly = true;
  341. o.depends("type", "https")
  342. // SPKI pin
  343. o = s.taboption("advanced", form.Value, "spki_pin", _("TLS SPKI Pinning"),
  344. _("Used to verify the validity of the TLS server, The value is Base64 encoded SPKI fingerprint, "
  345. + "leaving blank to indicate that the validity of TLS is not verified."))
  346. o.default = ""
  347. o.datatype = "string"
  348. o.rempty = true
  349. o.modalonly = true;
  350. o.depends("type", "tls")
  351. o.depends("type", "https")
  352. // other args
  353. o = s.taboption("advanced", form.Value, "addition_arg", _("Additional Server Args"),
  354. _("Additional Args for upstream dns servers"))
  355. o.default = ""
  356. o.rempty = true
  357. o.modalonly = true;
  358. // Doman addresss;
  359. s = m.section(form.TypedSection, "smartdns", _("Advanced Settings"), _("Advanced Settings"));
  360. s.anonymous = true;
  361. s.tab("domain-address", _("Domain Address"), _("Set Specific domain ip address."));
  362. s.tab("blackip-list", _("IP Blacklist"), _("Set Specific ip blacklist."));
  363. o = s.taboption("domain-address", form.TextValue, "address_conf",
  364. "",
  365. _("Specify an IP address to return for any host in the given domains, Queries in the domains are never "
  366. + "forwarded and always replied to with the specified IP address which may be IPv4 or IPv6."));
  367. o.rows = 20;
  368. o.cfgvalue = function (section_id) {
  369. return fs.trimmed('/etc/smartdns/address.conf');
  370. };
  371. o.write = function (section_id, formvalue) {
  372. return fs.write('/etc/smartdns/address.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
  373. };
  374. // IP Blacklist;
  375. // blacklist;
  376. o = s.taboption("blackip-list", form.TextValue, "blackip_ip_conf",
  377. "", _("Configure IP blacklists that will be filtered from the results of specific DNS server."));
  378. o.rows = 20;
  379. o.cfgvalue = function (section_id) {
  380. return fs.trimmed('/etc/smartdns/blacklist-ip.conf');
  381. };
  382. o.write = function (section_id, formvalue) {
  383. return fs.write('/etc/smartdns/blacklist-ip.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
  384. };
  385. // Doman addresss;
  386. s = m.section(form.TypedSection, "smartdns", _("Technical Support"),
  387. _("If you like this software, please buy me a cup of coffee."));
  388. s.anonymous = true;
  389. o = s.option(form.Button, "web");
  390. o.title = _("SmartDNS official website");
  391. o.inputtitle = _("open website");
  392. o.inputstyle = "apply";
  393. o.onclick = function () {
  394. window.open("https://pymumu.github.io/smartdns", '_blank');
  395. };
  396. o = s.option(form.Button, "Donate");
  397. o.title = _("Donate to smartdns");
  398. o.inputtitle = _("Donate");
  399. o.inputstyle = "apply";
  400. o.onclick = function () {
  401. window.open("https://pymumu.github.io/smartdns/#donate", '_blank');
  402. };
  403. return m.render();
  404. }
  405. });