summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-smartdns/htdocs/luci-static/resources
diff options
context:
space:
mode:
Diffstat (limited to 'applications/luci-app-smartdns/htdocs/luci-static/resources')
-rw-r--r--applications/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js784
1 files changed, 728 insertions, 56 deletions
diff --git a/applications/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js b/applications/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js
index e26aeed33f..91d7d0964e 100644
--- a/applications/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js
+++ b/applications/luci-app-smartdns/htdocs/luci-static/resources/view/smartdns/smartdns.js
@@ -1,6 +1,6 @@
/*************************************************************************
*
- * Copyright (C) 2018-2020 Ruilin Peng (Nick) <pymumu@gmail.com>.
+ * Copyright (C) 2018-2023 Ruilin Peng (Nick) <pymumu@gmail.com>.
*
* smartdns is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -38,11 +38,11 @@ var pollAdded = false;
function getServiceStatus() {
return L.resolveDefault(callServiceList(conf), {})
.then(function (res) {
- var isrunning = false;
+ var is_running = false;
try {
- isrunning = res[conf]['instances']['smartdns']['running'];
+ is_running = res[conf]['instances']['smartdns']['running'];
} catch (e) { }
- return isrunning;
+ return is_running;
});
}
@@ -73,7 +73,7 @@ function smartdnsRenderStatus(res) {
uci.unload('dhcp');
uci.load('dhcp');
if (dnsmasqServer == undefined || dnsmasqServer.indexOf(matchLine) < 0) {
- renderHTML += "<br /><span style=\"color:red;font-weight:bold\">" + _("Dnsmasq Forwared To Smartdns Failure") + "</span>";
+ renderHTML += "<br /><span style=\"color:red;font-weight:bold\">" + _("Dnsmasq Forwarded To Smartdns Failure") + "</span>";
}
}
@@ -89,6 +89,8 @@ return view.extend({
},
render: function (stats) {
var m, s, o;
+ var ss, so;
+ var servers, download_files;
m = new form.Map('smartdns', _('SmartDNS'));
m.title = _("SmartDNS Server");
@@ -120,14 +122,23 @@ return view.extend({
]);
}
+ ////////////////
// Basic;
+ ////////////////
s = m.section(form.TypedSection, "smartdns", _("Settings"), _("General Settings"));
s.anonymous = true;
s.tab("settings", _("General Settings"));
+ s.tab("advanced", _('Advanced Settings'));
s.tab("seconddns", _("Second Server Settings"));
+ s.tab("dns64", _("DNS64 Server Settings"));
+ s.tab("files", _("Download Files Setting"), _("Download domain list files for domain-rule and include config files, please refresh the page after download to take effect."));
+ s.tab("proxy", _("Proxy Server Settings"));
s.tab("custom", _("Custom Settings"));
+ ///////////////////////////////////////
+ // Basic Settings
+ ///////////////////////////////////////
o = s.taboption("settings", form.Flag, "enabled", _("Enable"), _("Enable or disable smartdns server"));
o.rmempty = false;
o.default = o.disabled;
@@ -145,65 +156,176 @@ return view.extend({
o.default = 53;
o.datatype = "port";
o.rempty = false;
+
+ // auto-conf-dnsmasq;
+ o = s.taboption("settings", form.Flag, "auto_set_dnsmasq", _("Automatically Set Dnsmasq"), _("Automatically set as upstream of dnsmasq when port changes."));
+ o.rmempty = false;
+ o.default = o.enabled;
+
+ ///////////////////////////////////////
+ // advanced settings;
+ ///////////////////////////////////////
+ // Speed check mode;
+ o = s.taboption("advanced", form.Value, "speed_check_mode", _("Speed Check Mode"), _("Smartdns speed check mode."));
+ o.rmempty = true;
+ o.placeholder = "default";
+ o.value("", _("default"));
+ o.value("ping,tcp:80,tcp:443");
+ o.value("ping,tcp:443,tcp:80");
+ o.value("tcp:80,tcp:443,ping");
+ o.value("tcp:443,tcp:80,ping");
+ o.value("none", _("None"));
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ if (value == "none") {
+ return true;
+ }
+
+ var check_mode = value.split(",")
+ for (var i = 0; i < check_mode.length; i++) {
+ if (check_mode[i] == "ping") {
+ continue;
+ }
+
+ if (check_mode[i].indexOf("tcp:") == 0) {
+ var port = check_mode[i].split(":")[1];
+ if (port == "") {
+ return _("TCP port is empty");
+ }
+
+ continue;
+ }
+
+ return _("Speed check mode is invalid.");
+ }
+
+ return true;
+ }
+
+ // response mode;
+ o = s.taboption("advanced", form.ListValue, "response_mode", _("Response Mode"),
+ _("Smartdns response mode, First Ping: return the first ping IP, Fastest IP: return the fastest IP, Fastest Response: return the fastest DNS response."));
+ o.rmempty = true;
+ o.placeholder = "default";
+ o.value("", _("default"));
+ o.value("first-ping", _("First Ping"));
+ o.value("fastest-ip", _("Fastest IP"));
+ o.value("fastest-response", _("Fastest Response"));
// Enable TCP server;
- o = s.taboption("settings", form.Flag, "tcp_server", _("TCP Server"), _("Enable TCP DNS Server"));
+ o = s.taboption("advanced", form.Flag, "tcp_server", _("TCP Server"), _("Enable TCP DNS Server"));
o.rmempty = false;
o.default = o.enabled;
// Support IPV6;
- o = s.taboption("settings", form.Flag, "ipv6_server", _("IPV6 Server"), _("Enable IPV6 DNS Server"));
+ o = s.taboption("advanced", form.Flag, "ipv6_server", _("IPV6 Server"), _("Enable IPV6 DNS Server"));
+ o.rmempty = false;
+ o.default = o.enabled;
+
+ // bind to device;
+ o = s.taboption("advanced", form.Flag, "bind_device", _("Bind Device"), _("Listen only on the specified interfaces."));
o.rmempty = false;
o.default = o.enabled;
+ // bind device name;
+ o = s.taboption("advanced", form.Value, "bind_device_name", _("Bind Device Name"), _("Name of device name listen on."));
+ o.placeholder = "default";
+ o.rempty = true;
+ o.datatype = "string";
+
// Support DualStack ip selection;
- o = s.taboption("settings", form.Flag, "dualstack_ip_selection", _("Dual-stack IP Selection"),
+ o = s.taboption("advanced", form.Flag, "dualstack_ip_selection", _("Dual-stack IP Selection"),
_("Enable IP selection between IPV4 and IPV6"));
o.rmempty = false;
o.default = o.enabled;
// Domain prefetch load ;
- o = s.taboption("settings", form.Flag, "prefetch_domain", _("Domain prefetch"),
+ o = s.taboption("advanced", form.Flag, "prefetch_domain", _("Domain prefetch"),
_("Enable domain prefetch, accelerate domain response speed."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
// Domain Serve expired
- o = s.taboption("settings", form.Flag, "serve_expired", _("Serve expired"),
+ o = s.taboption("advanced", form.Flag, "serve_expired", _("Serve expired"),
_("Attempts to serve old responses from cache with a TTL of 0 in the response without waiting for the actual resolution to finish."));
o.rmempty = false;
o.default = o.enabled;
// cache-size;
- o = s.taboption("settings", form.Value, "cache_size", _("Cache Size"), _("DNS domain result cache size"));
+ o = s.taboption("advanced", form.Value, "cache_size", _("Cache Size"), _("DNS domain result cache size"));
o.rempty = true;
- // cache-size;
- o = s.taboption("settings", form.Flag, "resolve_local_hostnames", _("Resolve Local Hostnames"), _("Resolve local hostnames by reading Dnsmasq lease file."));
+ // cache-persist;
+ o = s.taboption("advanced", form.Flag, "cache_persist", _("Cache Persist"), _("Write cache to disk on exit and load on startup."));
o.rmempty = false;
o.default = o.enabled;
- // auto-conf-dnsmasq;
- o = s.taboption("settings", form.Flag, "auto_set_dnsmasq", _("Automatically Set Dnsmasq"), _("Automatically set as upstream of dnsmasq when port changes."));
+ // cache-size;
+ o = s.taboption("advanced", form.Flag, "resolve_local_hostnames", _("Resolve Local Hostnames"), _("Resolve local hostnames by reading Dnsmasq lease file."));
o.rmempty = false;
o.default = o.enabled;
// Force AAAA SOA
- o = s.taboption("settings", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
- o.rmempty = false;
+ o = s.taboption("advanced", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
+ o.rmempty = true;
o.default = o.disabled;
// Force HTTPS SOA
- o = s.taboption("settings", form.Flag, "force_https_soa", _("Force HTTPS SOA"), _("Force HTTPS SOA."));
+ o = s.taboption("advanced", form.Flag, "force_https_soa", _("Force HTTPS SOA"), _("Force HTTPS SOA."));
o.rmempty = false;
- o.default = o.disabled;
+ o.default = o.enabled;
+
+ // Ipset no speed.
+ o = s.taboption("advanced", form.Value, "ipset_no_speed", _("No Speed IPset Name"),
+ _("Ipset name, Add domain result to ipset when speed check fails."));
+ o.rmempty = true;
+ o.datatype = "string";
+ o.rempty = true;
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var ipset = value.split(",")
+ for (var i = 0; i < ipset.length; i++) {
+ if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
+ return _("ipset name format error, format: [#[4|6]:]ipsetname");
+ }
+ }
+
+ return true;
+ }
+
+ // NFTset no speed.
+ o = s.taboption("advanced", form.Value, "nftset_no_speed", _("No Speed NFTset Name"),
+ _("Nftset name, Add domain result to nftset when speed check fails, format: [#[4|6]:[family#table#set]]"));
+ o.rmempty = true;
+ o.datatype = "string";
+ o.rempty = true;
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var nftset = value.split(",")
+ for (var i = 0; i < nftset.length; i++) {
+ if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
+ }
+ }
+
+ return true;
+ }
// rr-ttl;
- o = s.taboption("settings", form.Value, "rr_ttl", _("Domain TTL"), _("TTL for all domain result."));
+ o = s.taboption("advanced", form.Value, "rr_ttl", _("Domain TTL"), _("TTL for all domain result."));
o.rempty = true;
// rr-ttl-min;
- o = s.taboption("settings", form.Value, "rr_ttl_min", _("Domain TTL Min"),
+ o = s.taboption("advanced", form.Value, "rr_ttl_min", _("Domain TTL Min"),
_("Minimum TTL for all domain result."));
o.rempty = true;
o.placeholder = "600";
@@ -211,21 +333,45 @@ return view.extend({
o.optional = true;
// rr-ttl-max;
- o = s.taboption("settings", form.Value, "rr_ttl_max", _("Domain TTL Max"),
+ o = s.taboption("advanced", form.Value, "rr_ttl_max", _("Domain TTL Max"),
_("Maximum TTL for all domain result."));
o.rempty = true;
// rr-ttl-reply-max;
- o = s.taboption("settings", form.Value, "rr_ttl_reply_max", _("Reply Domain TTL Max"),
+ o = s.taboption("advanced", form.Value, "rr_ttl_reply_max", _("Reply Domain TTL Max"),
_("Reply maximum TTL for all domain result."));
o.rempty = true;
+ // other args
+ o = s.taboption("advanced", form.Value, "server_flags", _("Additional Server Args"),
+ _("Additional server args, refer to the help description of the bind option."))
+ o.default = ""
+ o.rempty = true
+
+ // include config
+ download_files = uci.sections('smartdns', 'download-file');
+ o = s.taboption("advanced", form.DynamicList, "conf_files", _("Include Config Files<br>/etc/smartdns/conf.d"),
+ _("Include other config files from /etc/smartdns/conf.d or custom path, can be downloaded from the download page."));
+ for (var i = 0; i < download_files.length; i++) {
+ if (download_files[i].type == undefined) {
+ continue;
+ }
+
+ if (download_files[i].type != 'config') {
+ continue
+ }
+
+ o.value(download_files[i].name);
+ }
+
+ ///////////////////////////////////////
// second dns server;
- // Eanble;
+ ///////////////////////////////////////
+ // Enable;
o = s.taboption("seconddns", form.Flag, "seconddns_enabled", _("Enable"),
_("Enable or disable second DNS server."));
o.default = o.disabled;
- o.rempty = false;
+ o.rempty = true;
// Port;
o = s.taboption("seconddns", form.Value, "seconddns_port", _("Local Port"), _("Smartdns local server port"));
@@ -249,52 +395,194 @@ return view.extend({
o = s.taboption("seconddns", form.Flag, "seconddns_no_speed_check", _("Skip Speed Check"),
_("Do not check speed."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
// skip address rules;
o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_addr", _("Skip Address Rules"),
_("Skip address rules."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
// skip name server rules;
o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_nameserver", _("Skip Nameserver Rule"),
_("Skip nameserver rules."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
// skip ipset rules;
o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_ipset", _("Skip Ipset Rule"),
_("Skip ipset rules."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
// skip soa address rule;
o = s.taboption("seconddns", form.Flag, "seconddns_no_rule_soa", _("Skip SOA Address Rule"),
_("Skip SOA address rules."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
o = s.taboption("seconddns", form.Flag, "seconddns_no_dualstack_selection", _("Skip Dualstack Selection"),
_("Skip Dualstack Selection."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
// skip cache;
o = s.taboption("seconddns", form.Flag, "seconddns_no_cache", _("Skip Cache"), _("Skip Cache."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
// Force AAAA SOA
o = s.taboption("seconddns", form.Flag, "seconddns_force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
- o.rmempty = false;
+ o.rmempty = true;
+ o.default = o.disabled;
+
+ o = s.taboption("seconddns", form.Value, "seconddns_ipset_name", _("IPset Name"), _("IPset name."));
+ o.rmempty = true;
+ o.datatype = "string";
+ o.rempty = true;
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var ipset = value.split(",")
+ for (var i = 0; i < ipset.length; i++) {
+ if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
+ return _("ipset name format error, format: [#[4|6]:]ipsetname");
+ }
+ }
+
+ return true;
+ }
+
+ o = s.taboption("seconddns", form.Value, "seconddns_nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
+ o.rmempty = true;
+ o.datatype = "string";
+ o.rempty = true;
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var nftset = value.split(",")
+ for (var i = 0; i < nftset.length; i++) {
+ if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
+ }
+ }
+
+ return true;
+ }
+
+ // other args
+ o = s.taboption("seconddns", form.Value, "seconddns_server_flags", _("Additional Server Args"),
+ _("Additional server args, refer to the help description of the bind option."))
+ o.default = ""
+ o.rempty = true
+
+ ///////////////////////////////////////
+ // DNS64 Settings
+ ///////////////////////////////////////
+ o = s.taboption("dns64", form.Value, "dns64", _("DNS64"));
+ o.placeholder = "64:ff9b::/96";
+ o.datatype = "ip6addr";
+ o.rempty = true;
+
+ ///////////////////////////////////////
+ // download Files Settings
+ ///////////////////////////////////////
+ o = s.taboption("files", form.Flag, "enable_auto_update", _("Enable Auto Update"), _("Enable daily auto update."));
+ o.rmempty = true;
o.default = o.disabled;
+ o.rempty = true;
+
+ o = s.taboption("files", form.FileUpload, "upload_conf_file", _("Upload Config File"),
+ _("Upload smartdns config file to /etc/smartdns/conf.d"));
+ o.rmempty = true
+ o.datatype = "file"
+ o.rempty = true
+ o.root_directory = "/etc/smartdns/conf.d"
+
+ o = s.taboption("files", form.FileUpload, "upload_list_file", _("Upload Domain List File"),
+ _("Upload domain list file to /etc/smartdns/domain-set"));
+ o.rmempty = true
+ o.datatype = "file"
+ o.rempty = true
+ o.root_directory = "/etc/smartdns/domain-set"
+
+ o = s.taboption('files', form.DummyValue, "_update", _("Update Files"));
+ o.renderWidget = function () {
+ return E('button', {
+ 'class': 'btn cbi-button cbi-button-apply',
+ 'id': 'btn_update',
+ 'click': ui.createHandlerFn(this, function () {
+ return fs.exec('/etc/init.d/smartdns', ['updatefiles'])
+ .catch(function (e) { ui.addNotification(null, E('p', e.message), 'error') });
+ })
+ }, [_("Update")]);
+ }
+
+ o = s.taboption('files', form.SectionValue, '__files__', form.GridSection, 'download-file', _('Download Files'),
+ _('List of files to download.'));
+
+ ss = o.subsection;
+
+ ss.addremove = true;
+ ss.anonymous = true;
+ ss.sortable = true;
+
+ so = ss.option(form.Value, 'name', _('File Name'), _('File Name'));
+ so.rmempty = true;
+ so.datatype = 'file';
+
+ so = ss.option(form.Value, 'url', _('URL'), _('URL'));
+ so.rmempty = true;
+ so.datatype = 'string';
+ so.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ if (!value.match(/^(http|https|ftp|sftp):\/\//)) {
+ return _("URL format error, format: http:// or https://");
+ }
+
+ return true;
+ }
+
+ so = ss.option(form.ListValue, "type", _("type"), _("File Type"));
+ so.value("list", _("domain list (/etc/smartdns/domain-set)"));
+ so.value("config", _("smartdns config (/etc/smartdns/conf.d)"));
+ so.default = "list";
+ so.rempty = false;
+
+ so = ss.option(form.Value, 'desc', _('Description'), _('Description'));
+ so.rmempty = true;
+ so.datatype = 'string';
+
+ ///////////////////////////////////////
+ // Proxy server settings;
+ ///////////////////////////////////////
+ o = s.taboption("proxy", form.Value, "proxy_server", _("Proxy Server"), _("Proxy Server URL, format: [socks5|http]://user:pass@ip:port."));
+ o.datatype = 'string';
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ if (!value.match(/^(socks5|http):\/\//)) {
+ return _("Proxy server URL format error, format: [socks5|http]://user:pass@ip:port.");
+ }
+ return true;
+ }
+
+ ///////////////////////////////////////
// custom settings;
+ ///////////////////////////////////////
o = s.taboption("custom", form.TextValue, "custom_conf",
"", _("smartdns custom settings"));
-
o.rows = 20;
o.cfgvalue = function (section_id) {
return fs.trimmed('/etc/smartdns/custom.conf');
@@ -310,14 +598,42 @@ return view.extend({
o = s.taboption("custom", form.Flag, "coredump", _("Generate Coredump"),
_("Generate Coredump file when smartdns crash, coredump file is located at /tmp/smartdns.xxx.core."));
- o.rmempty = false;
+ o.rmempty = true;
o.default = o.disabled;
+
+ o = s.taboption("custom", form.Value, "log_size", _("Log Size"));
+ o.rmempty = true;
+ o.placeholder = "default";
+
+ o = s.taboption("custom", form.ListValue, "log_level", _("Log Level"));
+ o.rmempty = true;
+ o.placeholder = "default";
+ o.value("", _("default"));
+ o.value("debug");
+ o.value("info");
+ o.value("notice");
+ o.value("warn");
+ o.value("error");
+ o.value("fatal");
+ o.value("off");
+
+ o = s.taboption("custom", form.Value, "log_num", _("Log Number"));
+ o.rmempty = true;
+ o.placeholder = "default";
+
+ o = s.taboption("custom", form.Value, "log_file", _("Log File"))
+ o.rmempty = true
+ o.placeholder = "/var/log/smartdns/smartdns.log"
+
+ ////////////////
// Upstream servers;
+ ////////////////
s = m.section(form.GridSection, "server", _("Upstream Servers"),
_("Upstream Servers, support UDP, TCP protocol. Please configure multiple DNS servers, "
+ "including multiple foreign DNS servers."));
s.anonymous = true;
s.addremove = true;
+ s.sortable = true;
s.tab('general', _('General Settings'));
s.tab('advanced', _('Advanced Settings'));
@@ -355,20 +671,36 @@ return view.extend({
o.default = "udp";
o.rempty = false;
- // Advanced Options
// server group
- o = s.taboption("advanced", form.Value, "server_group", _("Server Group"), _("DNS Server group belongs to, "
- + "used with nameserver, such as office, home."))
- o.rmempty = true
- o.placeholder = "default"
- o.datatype = "hostname"
- o.rempty = true
+ o = s.taboption("general", form.Value, "server_group", _("Server Group"), _("DNS Server group"))
+ o.rmempty = true;
+ o.placeholder = "default";
+ o.datatype = "hostname";
+ o.rempty = true;
+ servers = uci.sections('smartdns', 'server');
+ var groupnames = new Set();
+ for (var i = 0; i < servers.length; i++) {
+ if (servers[i].server_group == undefined) {
+ continue;
+ }
+ groupnames.add(servers[i].server_group);
+ }
+
+ for (const groupname of groupnames) {
+ o.value(groupname);
+ }
+
+ // Advanced Options
+ o = s.taboption("advanced", form.Flag, "exclude_default_group", _("Exclude Default Group"), _("Exclude DNS Server from default group."))
+ o.rmempty = true;
+ o.default = o.disabled;
+ o.editable = true;
o.modalonly = true;
// blacklist_ip
o = s.taboption("advanced", form.Flag, "blacklist_ip", _("IP Blacklist Filtering"),
_("Filtering IP with blacklist"))
- o.rmempty = false
+ o.rmempty = true
o.default = o.disabled
o.modalonly = true;
@@ -385,7 +717,7 @@ return view.extend({
// certificate verify
o = s.taboption("advanced", form.Flag, "no_check_certificate", _("No check certificate"),
_("Do not check certificate."))
- o.rmempty = false
+ o.rmempty = true
o.default = o.disabled
o.modalonly = true;
o.depends("type", "tls")
@@ -393,7 +725,7 @@ return view.extend({
// SNI host name
o = s.taboption("advanced", form.Value, "host_name", _("TLS SNI name"),
- _("Sets the server name indication for query."))
+ _("Sets the server name indication for query. '-' for disable SNI name."))
o.default = ""
o.datatype = "hostname"
o.rempty = true
@@ -421,6 +753,40 @@ return view.extend({
o.depends("type", "tls")
o.depends("type", "https")
+ // mark
+ o = s.taboption("advanced", form.Value, "set_mark", _("Marking Packets"),
+ _("Set mark on packets."))
+ o.default = ""
+ o.rempty = true
+ o.datatype = "uinteger"
+ o.modalonly = true;
+
+ // use proxy
+ o = s.taboption("advanced", form.Flag, "use_proxy", _("Use Proxy"),
+ _("Use proxy to connect to upstream DNS server."))
+ o.default = o.disabled
+ o.modalonly = true;
+ o.optional = true;
+ o.rempty = true;
+ o.validate = function (section_id, value) {
+ var flag = this.formvalue(section_id);
+ if (flag == "0") {
+ return true;
+ }
+
+ var proxy_server = uci.sections("smartdns", "smartdns")[0].proxy_server;
+ var server_type = this.section.formvalue(section_id, "type");
+ if (proxy_server == "" || proxy_server == undefined) {
+ return _("Please set proxy server first.");
+ }
+
+ if (server_type == "udp" && !proxy_server.match(/^(socks5):\/\//)) {
+ return _("Only socks5 proxy support udp server.");
+ }
+
+ return true;
+ }
+
// other args
o = s.taboption("advanced", form.Value, "addition_arg", _("Additional Server Args"),
_("Additional Args for upstream dns servers"))
@@ -428,31 +794,307 @@ return view.extend({
o.rempty = true
o.modalonly = true;
- // Doman addresss;
- s = m.section(form.TypedSection, "smartdns", _("Advanced Settings"), _("Advanced Settings"));
+ ////////////////
+ // domain rules;
+ ////////////////
+ s = m.section(form.TypedSection, "domain-rule", _("Domain Rules"), _("Domain Rules Settings"));
s.anonymous = true;
+ s.nodescriptions = true;
+ s.tab("forwarding", _('DNS Forwarding Setting'));
+ s.tab("block", _("DNS Block Setting"));
+ s.tab("domain-rule-list", _("Domain Rule List"), _("Set Specific domain rule list."));
s.tab("domain-address", _("Domain Address"), _("Set Specific domain ip address."));
s.tab("blackip-list", _("IP Blacklist"), _("Set Specific ip blacklist."));
- o = s.taboption("domain-address", form.TextValue, "address_conf",
- "",
- _("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."));
- o.rows = 20;
+ ///////////////////////////////////////
+ // domain forwarding;
+ ///////////////////////////////////////
+ o = s.taboption("forwarding", form.Value, "server_group", _("Server Group"), _("DNS Server group belongs to, such as office, home."))
+ o.rmempty = true
+ o.placeholder = "default"
+ o.datatype = "hostname"
+ o.rempty = true
+ for (const groupname of groupnames) {
+ o.value(groupname);
+ }
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var val = uci.sections('smartdns', 'server');
+ for (var i = 0; i < val.length; i++) {
+ if (value == val[i].server_group) {
+ return true;
+ }
+ }
+
+ return _('Server Group %s not exists').format(value);
+
+ }
+
+ o = s.taboption("forwarding", form.Flag, "no_speed_check", _("Skip Speed Check"),
+ _("Do not check speed."));
+ o.rmempty = true;
+ o.default = o.disabled;
+
+ o = s.taboption("forwarding", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
+ o.rmempty = true;
+ o.default = o.disabled;
+
+ o = s.taboption("forwarding", form.Value, "ipset_name", _("IPset Name"), _("IPset name."));
+ o.rmempty = true;
+ o.datatype = "string";
+ o.rempty = true;
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var ipset = value.split(",")
+ for (var i = 0; i < ipset.length; i++) {
+ if (!ipset[i].match(/^(#[4|6]:)?[a-zA-Z0-9\-_]+$/)) {
+ return _("ipset name format error, format: [#[4|6]:]ipsetname");
+ }
+ }
+
+ return true;
+ }
+
+ o = s.taboption("forwarding", form.Value, "nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
+ o.rmempty = true;
+ o.datatype = "string";
+ o.rempty = true;
+ o.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var nftset = value.split(",")
+ for (var i = 0; i < nftset.length; i++) {
+ if (!nftset[i].match(/^#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
+ }
+ }
+
+ return true;
+ }
+
+ // other args
+ o = s.taboption("forwarding", form.Value, "addition_flag", _("Additional Rule Flag"),
+ _("Additional Flags for rules, read help on domain-rule for more information."))
+ o.default = ""
+ o.rempty = true
+ o.modalonly = true;
+
+ o = s.taboption("forwarding", form.FileUpload, "forwarding_domain_set_file", _("Domain List File"),
+ _("Upload domain list file, or configure auto download from Download File Setting page."));
+ o.rmempty = true
+ o.datatype = "file"
+ o.rempty = true
+ o.editable = true
+ o.root_directory = "/etc/smartdns/domain-set"
+
+ o = s.taboption("forwarding", form.TextValue, "domain_forwarding_list",
+ _("Domain List"), _("Configure forwarding domain name list."));
+ o.rows = 10;
+ o.cols = 64;
+ o.monospace = true;
o.cfgvalue = function (section_id) {
- return fs.trimmed('/etc/smartdns/address.conf');
+ return fs.trimmed('/etc/smartdns/domain-forwarding.list').catch(function (e) {
+ return "";
+ });
};
o.write = function (section_id, formvalue) {
return this.cfgvalue(section_id).then(function (value) {
if (value == formvalue) {
return
}
- return fs.write('/etc/smartdns/address.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
+ return fs.write('/etc/smartdns/domain-forwarding.list', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
+ });
+ };
+
+ ///////////////////////////////////////
+ // domain block;
+ ///////////////////////////////////////
+ o = s.taboption("block", form.FileUpload, "block_domain_set_file", _("Domain List File"), _("Upload domain list file."));
+ o.rmempty = true
+ o.datatype = "file"
+ o.rempty = true
+ o.editable = true
+ o.root_directory = "/etc/smartdns/domain-set"
+
+ o = s.taboption("block", form.TextValue, "domain_block_list",
+ _("Domain List"), _("Configure block domain list."));
+ o.rows = 10;
+ o.cols = 64;
+ o.cfgvalue = function (section_id) {
+ return fs.trimmed('/etc/smartdns/domain-block.list').catch(function (e) {
+ return "";
+ });
+ };
+ o.write = function (section_id, formvalue) {
+ return this.cfgvalue(section_id).then(function (value) {
+ if (value == formvalue) {
+ return
+ }
+ return fs.write('/etc/smartdns/domain-block.list', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
});
};
+ ///////////////////////////////////////
+ // domain rule list;
+ ///////////////////////////////////////
+ o = s.taboption('domain-rule-list', form.SectionValue, '__domain-rule-list__', form.GridSection, 'domain-rule-list', _('Domain Rule List'),
+ _('Configure domain rule list.'));
+
+ ss = o.subsection;
+
+ ss.addremove = true;
+ ss.anonymous = true;
+ ss.sortable = true;
+
+ // enable flag;
+ so = ss.option(form.Flag, "enabled", _("Enable"), _("Enable"));
+ so.rmempty = false;
+ so.default = so.enabled;
+ so.editable = true;
+
+ // name;
+ so = ss.option(form.Value, "name", _("Domain Rule Name"), _("Domain Rule Name"));
+
+ so = ss.option(form.Value, "server_group", _("Server Group"), _("DNS Server group belongs to, such as office, home."))
+ so.rmempty = true
+ so.placeholder = "default"
+ so.datatype = "hostname"
+ so.rempty = true
+ for (const groupname of groupnames) {
+ so.value(groupname);
+ }
+ so.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var val = uci.sections('smartdns', 'server');
+ for (var i = 0; i < val.length; i++) {
+ if (value == val[i].server_group) {
+ return true;
+ }
+ }
+
+ return _('Server Group %s not exists').format(value);
+
+ }
+
+ so = ss.option(form.FileUpload, "domain_list_file", _("Domain List File"),
+ _("Upload domain list file, or configure auto download from Download File Setting page."));
+ so.rmempty = true
+ so.datatype = "file"
+ so.rempty = true
+ so.root_directory = "/etc/smartdns/domain-set"
+
+ so = ss.option(form.ListValue, "block_domain_type", _("Block domain"), _("Block domain."));
+ so.rmempty = true;
+ so.value("none", _("None"));
+ so.value("all", "IPv4/IPv6");
+ so.value("ipv4", "IPv4");
+ so.value("ipv6", "IPv6");
+ so.modalonly = true;
+
+ // Support DualStack ip selection;
+ so = ss.option(form.ListValue, "dualstack_ip_selection", _("Dual-stack IP Selection"),
+ _("Enable IP selection between IPV4 and IPV6"));
+ so.rmempty = true;
+ so.default = "default";
+ so.modalonly = true;
+ so.value("", _("default"));
+ so.value("yes", _("Yes"));
+ so.value("no", _("No"));
+
+ so = ss.option(form.Value, "speed_check_mode", _("Speed Check Mode"), _("Smartdns speed check mode."));
+ so.rmempty = true;
+ so.placeholder = "default";
+ so.modalonly = true;
+ so.value("", _("default"));
+ so.value("ping,tcp:80,tcp:443");
+ so.value("ping,tcp:443,tcp:80");
+ so.value("tcp:80,tcp:443,ping");
+ so.value("tcp:443,tcp:80,ping");
+ so.value("none", _("None"));
+ so.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ if (value == "none") {
+ return true;
+ }
+
+ var check_mode = value.split(",")
+ for (var i = 0; i < check_mode.length; i++) {
+ if (check_mode[i] == "ping") {
+ continue;
+ }
+
+ if (check_mode[i].indexOf("tcp:") == 0) {
+ var port = check_mode[i].split(":")[1];
+ if (port == "") {
+ return _("TCP port is empty");
+ }
+
+ continue;
+ }
+
+ return _("Speed check mode is invalid.");
+ }
+
+ return true;
+ }
+
+ so = ss.option(form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
+ so.rmempty = true;
+ so.default = so.disabled;
+ so.modalonly = true;
+
+
+ so = ss.option(form.Value, "ipset_name", _("IPset Name"), _("IPset name."));
+ so.rmempty = true;
+ so.datatype = "hostname";
+ so.rempty = true;
+ so.modalonly = true;
+
+ so = ss.option(form.Value, "nftset_name", _("NFTset Name"), _("NFTset name, format: [#[4|6]:[family#table#set]]"));
+ so.rmempty = true;
+ so.datatype = "string";
+ so.rempty = true;
+ so.modalonly = true;
+ so.validate = function (section_id, value) {
+ if (value == "") {
+ return true;
+ }
+
+ var nftset = value.split(",")
+ for (var i = 0; i < nftset.length; i++) {
+ if (!nftset[i].match(/#[4|6]:[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+#[a-zA-Z0-9\-_]+$/)) {
+ return _("NFTset name format error, format: [#[4|6]:[family#table#set]]");
+ }
+ }
+
+ return true;
+ }
+
+ // other args
+ so = ss.option(form.Value, "addition_flag", _("Additional Rule Flag"),
+ _("Additional Flags for rules, read help on domain-rule for more information."))
+ so.default = ""
+ so.rempty = true
+ so.modalonly = true;
+
+ ///////////////////////////////////////
// IP Blacklist;
+ ///////////////////////////////////////
// blacklist;
o = s.taboption("blackip-list", form.TextValue, "blackip_ip_conf",
"", _("Configure IP blacklists that will be filtered from the results of specific DNS server."));
@@ -469,7 +1111,29 @@ return view.extend({
});
};
- // Doman addresss;
+ ///////////////////////////////////////
+ // domain address
+ ///////////////////////////////////////
+ o = s.taboption("domain-address", form.TextValue, "address_conf",
+ "",
+ _("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."));
+ o.rows = 20;
+ o.cfgvalue = function (section_id) {
+ return fs.trimmed('/etc/smartdns/address.conf');
+ };
+ o.write = function (section_id, formvalue) {
+ return this.cfgvalue(section_id).then(function (value) {
+ if (value == formvalue) {
+ return
+ }
+ return fs.write('/etc/smartdns/address.conf', formvalue.trim().replace(/\r\n/g, '\n') + '\n');
+ });
+ };
+
+ ////////////////
+ // Support
+ ////////////////
s = m.section(form.TypedSection, "smartdns", _("Technical Support"),
_("If you like this software, please buy me a cup of coffee."));
s.anonymous = true;
@@ -482,6 +1146,14 @@ return view.extend({
window.open("https://pymumu.github.io/smartdns", '_blank');
};
+ o = s.option(form.Button, "report");
+ o.title = _("Report bugs");
+ o.inputtitle = _("Report bugs");
+ o.inputstyle = "apply";
+ o.onclick = function () {
+ window.open("https://github.com/pymumu/smartdns/issues", '_blank');
+ };
+
o = s.option(form.Button, "Donate");
o.title = _("Donate to smartdns");
o.inputtitle = _("Donate");