luci-app-https-dns-proxy: update to 2025-12-29-1

* update version to match principal package
* split the main config section into service configs and the global
  instance configs
* add support for the new source_addr option; @karl82 I'd appreciate if
  you could look at the WebUI and documentation and suggest improvements
  for description
* add WebUI support for all available configs in both global configs and
  per-instance/provider modal window
* bugfix: store bootstrap_dns options from the provider json file when
  adding a new instance
* if listen_addr or listen_port or source_addr are not set, display nicer
  text in the GridSection view than `none`.

Signed-off-by: Stan Grishin <stangri@melmac.ca>
This commit is contained in:
Stan Grishin
2026-01-08 03:30:01 +00:00
parent 6ebcfe66ec
commit 4979338bbb
3 changed files with 516 additions and 168 deletions

View File

@@ -1,13 +1,13 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright 2017-2025 MOSSDeF, Stan Grishin (stangri@melmac.ca).
# Copyright 2017-2026 MOSSDeF, Stan Grishin (stangri@melmac.ca).
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-https-dns-proxy
PKG_LICENSE:=AGPL-3.0-or-later
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
PKG_VERSION:=2025.10.07
PKG_RELEASE:=2
PKG_VERSION:=2025.12.29
PKG_RELEASE:=1
LUCI_TITLE:=DNS Over HTTPS Proxy Web UI
LUCI_URL:=https://github.com/stangri/luci-app-https-dns-proxy/

View File

@@ -46,16 +46,19 @@ return view.extend({
status = new hdp.status();
m = new form.Map(pkg.Name, _("HTTPS DNS Proxy - Configuration"));
s = m.section(form.NamedSection, "config", pkg.Name);
s.tab("service", _("Service Options"));
s.tab("global", _("Global Instance Options"));
var dhcp_dnsmasq_values = Object.values(L.uci.sections("dhcp", "dnsmasq"));
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
if (!isEmpty(dhcp_dnsmasq_values)) {
o = s.option(
o = s.taboption(
"service",
form.ListValue,
"dnsmasq_config_update_option",
_("Update DNSMASQ Config on Start/Stop"),
@@ -93,7 +96,8 @@ return view.extend({
L.uci.set(pkg.Name, section_id, "dnsmasq_config_update", formvalue);
};
o = s.option(
o = s.taboption(
"service",
form.MultiValue,
"dnsmasq_config_update",
_("Select the DNSMASQ Configs to update")
@@ -115,7 +119,8 @@ return view.extend({
o.retain = true;
}
o = s.option(
o = s.taboption(
"service",
form.ListValue,
"force_dns",
_("Force Router DNS"),
@@ -130,7 +135,8 @@ return view.extend({
o.value("1", _("Force Router DNS server to all local devices"));
o.default = "1";
o = s.option(
o = s.taboption(
"service",
form.ListValue,
"canary_domains_icloud",
_("Canary Domains iCloud"),
@@ -146,7 +152,8 @@ return view.extend({
o.depends("force_dns", "1");
o.default = "1";
o = s.option(
o = s.taboption(
"service",
form.ListValue,
"canary_domains_mozilla",
_("Canary Domains Mozilla"),
@@ -154,9 +161,9 @@ return view.extend({
"Blocks access to Mozilla Encrypted resolvers, forcing local devices to use router for DNS resolution (%smore information%s)."
).format(
'<a href="' +
pkg.URL +
"#canary_domains_mozilla" +
'" target="_blank">',
pkg.URL +
"#canary_domains_mozilla" +
'" target="_blank">',
"</a>"
)
);
@@ -165,6 +172,149 @@ return view.extend({
o.depends("force_dns", "1");
o.default = "1";
o = s.taboption(
"service",
form.Value,
"heartbeat_domain",
_("Heartbeat Domain"),
_(
"The domain used for connectivity checks (%smore information%s)."
).format(
'<a href="' + pkg.URL + "#heartbeat_domain" + '" target="_blank">',
"</a>"
)
);
o.optional = true;
o.placeholder = "heartbeat.melmac.ca";
o = s.taboption(
"service",
form.Value,
"heartbeat_sleep_timeout",
_("Heartbeat Sleep Timeout"),
_("Time to wait before checking connectivity (seconds).")
);
o.datatype = "uinteger";
o.optional = true;
o.placeholder = "10";
o = s.taboption(
"service",
form.Value,
"heartbeat_wait_timeout",
_("Heartbeat Wait Timeout"),
_("Time to wait for connectivity check response (seconds).")
);
o.datatype = "uinteger";
o.optional = true;
o.placeholder = "30";
o = s.taboption(
"global",
form.ListValue,
"force_http1",
_("Use HTTP/1")
);
o.optional = true;
o.rmempty = true;
o.value("", _("Use negotiated HTTP version"));
o.value("1", _("Force use of HTTP/1"));
o.default = "";
o = s.taboption(
"global",
form.ListValue,
"force_http3",
_("Use HTTP/3 (QUIC)")
);
o.optional = true;
o.rmempty = true;
o.value("", _("Use negotiated HTTP version"));
o.value("1", _("Force use of HTTP/3 (QUIC)"));
o.default = "";
o.depends("force_http1", "");
o = s.taboption(
"global",
form.ListValue,
"force_ipv6_resolvers",
_("Use IPv6 resolvers")
);
o.optional = true;
o.rmempty = true;
o.value("", _("Use any family DNS resolvers"));
o.value("1", _("Force use of IPv6 DNS resolvers"));
o.default = "";
o = s.taboption("global", form.ListValue, "verbosity", _("Logging Verbosity Level"));
o.optional = true;
o.value("", _("0: Fatal"));
o.value("1", _("1: Error"));
o.value("2", _("2: Warning"));
o.value("3", _("3: Info"));
o.value("4", _("4: Debug"));
o.default = "";
o = s.taboption("global", form.Value, "listen_addr", _("Listen Address"));
o.datatype = "ipaddr('nomask')";
o.optional = true;
o.placeholder = "127.0.0.1";
o = s.taboption("global", form.Value, "user", _("Run As User"));
o.optional = true;
o.placeholder = "nobody";
o = s.taboption("global", form.Value, "group", _("Run As Group"));
o.optional = true;
o.placeholder = "nogroup";
o = s.taboption("global", form.Value, "source_addr", _("Source Address"));
o.datatype = "ipaddr('nomask')";
o.optional = true;
o.placeholder = "";
o = s.taboption("global", form.Value, "logfile", _("Logging File Path"));
o.datatype = "file";
o.optional = true;
o.placeholder = "";
o = s.taboption("global", form.Value, "polling_interval", _("Polling Interval"));
o.datatype = "range(5,3600)";
o.optional = true;
o.placeholder = "120";
o = s.taboption("global", form.Value, "proxy_server", _("Proxy Server"));
o.optional = true;
o = s.taboption("global", form.Value, "ca_certs_file", _("CA Certs File"));
o.datatype = "file";
o.optional = true;
o = s.taboption("global", form.Value, "conn_loss_time", _("Connection Loss Time"));
o.datatype = "uinteger";
o.optional = true;
o.placeholder = "15";
o = s.taboption("global", form.Value, "log_limit", _("Log Limit"));
o.datatype = "uinteger";
o.optional = true;
o.placeholder = "0";
o = s.taboption("global", form.Value, "max_idle_time", _("Max Idle Time"));
o.datatype = "uinteger";
o.optional = true;
o.placeholder = "118";
o = s.taboption("global", form.Value, "statistic_interval", _("Statistic Interval"));
o.datatype = "uinteger";
o.optional = true;
o.placeholder = "0";
o = s.taboption("global", form.Value, "tcp_client_limit", _("TCP Client Limit"));
o.datatype = "uinteger";
o.optional = true;
o.placeholder = "20";
text = "";
if (!reply.platform.http2_support)
text +=
@@ -250,85 +400,114 @@ return view.extend({
});
return ret || "";
};
_provider.write = function (section_id, formvalue) {
L.uci.set(pkg.Name, section_id, "resolver_url", formvalue);
let providerTemplate = formvalue;
let resolverUrl = providerTemplate;
let bootstrapDns = "";
let section = this.section;
reply.providers.forEach((prov, i) => {
if (prov.template === providerTemplate) {
let paramValue = "";
let paramWidgetOption = "";
if (prov.params && prov.params.option) {
if (prov.params.option.type === "select") {
paramWidgetOption = "_paramList_" + i;
} else if (prov.params.option.type === "text") {
paramWidgetOption = "_paramText_" + i;
}
}
if (paramWidgetOption) {
// Find the widget object to get the value safely
let widget = section.children.find(w => w.option === paramWidgetOption);
if (widget) {
paramValue = widget.formvalue(section_id) || "";
}
}
resolverUrl = pkg.templateToResolver(providerTemplate, {
option: paramValue
});
let bootWidget = section.children.find(w => w.option === "_bootstrap_dns_" + i);
if (bootWidget) {
bootstrapDns = bootWidget.formvalue(section_id);
}
// Fallback to default if empty
if (!bootstrapDns) {
bootstrapDns = prov.bootstrap_dns || "";
}
}
});
if (resolverUrl) {
L.uci.set(pkg.Name, section_id, "resolver_url", resolverUrl);
}
if (bootstrapDns) {
L.uci.set(pkg.Name, section_id, "bootstrap_dns", bootstrapDns);
} else {
L.uci.unset(pkg.Name, section_id, "bootstrap_dns");
}
};
_provider.remove = function (section_id) {
L.uci.unset(pkg.Name, section_id, "resolver_url");
L.uci.unset(pkg.Name, section_id, "bootstrap_dns");
};
reply.providers.forEach((prov, i) => {
if (prov.http2_only && !reply.platform.http2_support) return;
if (prov.http3_only && !reply.platform.http3_support) return;
_provider.value(prov.template, _(prov.title));
function createProviderWidget(s, i, prov) {
if (
prov.params &&
prov.params.option &&
prov.params.option.type &&
prov.params.option.type === "select"
prov.params.option.type
) {
let optName = prov.params.option.description || _("Parameter");
var _paramList = s.option(form.ListValue, "_paramList_" + i, optName);
_paramList.template = prov.template;
_paramList.modalonly = true;
if (prov.params.option.default) {
_paramList.default = prov.params.option.default;
if (prov.params.option.type === "select") {
let optName = prov.params.option.description || _("Parameter");
var _paramList = s.option(form.ListValue, "_paramList_" + i, optName);
_paramList.template = prov.template;
_paramList.modalonly = true;
if (prov.params.option.default) {
_paramList.default = prov.params.option.default;
}
prov.params.option.options.forEach((opt) => {
let val = opt.value || "";
let descr = opt.description || "";
_paramList.value(val, descr);
});
_paramList.depends("_provider", prov.template);
_paramList.write = function (section_id, formvalue) { };
_paramList.remove = function (section_id, formvalue) { };
} else if (prov.params.option.type === "text") {
let optName = prov.params.option.description || _("Parameter");
var _paramText = s.option(form.Value, "_paramText_" + i, optName);
_paramText.template = prov.template;
_paramText.modalonly = true;
_paramText.depends("_provider", prov.template);
_paramText.optional = !(
prov.params.option.default && prov.params.option.default !== ""
);
_paramText.cfgvalue = function (section_id) {
let resolver = this.map.data.get(
this.map.config,
section_id,
"resolver_url"
);
if (resolver === undefined || resolver === null) return null;
let regexp = pkg.templateToRegexp(prov.template);
let match = resolver.match(regexp);
return (match && match[1]) || null;
};
_paramText.write = function (section_id, formvalue) { };
_paramText.remove = function (section_id, formvalue) { };
}
prov.params.option.options.forEach((opt) => {
let val = opt.value || "";
let descr = opt.description || "";
_paramList.value(val, descr);
});
_paramList.depends("_provider", prov.template);
_paramList.write = function (section_id, formvalue) {
let template = this.map.data.get(
this.map.config,
section_id,
"resolver_url"
);
if (!formvalue && _paramList.template !== template) return 0;
let resolver = pkg.templateToResolver(_paramList.template, {
option: formvalue || "",
});
L.uci.set(pkg.Name, section_id, "resolver_url", resolver);
};
_paramList.remove = _paramList.write;
} else if (
prov.params &&
prov.params.option &&
prov.params.option.type &&
prov.params.option.type === "text"
) {
let optName = prov.params.option.description || _("Parameter");
var _paramText = s.option(form.Value, "_paramText_" + i, optName);
_paramText.template = prov.template;
_paramText.modalonly = true;
_paramText.depends("_provider", prov.template);
_paramText.optional = !(
prov.params.option.default && prov.params.option.default !== ""
);
_paramText.cfgvalue = function (section_id) {
let resolver = this.map.data.get(
this.map.config,
section_id,
"resolver_url"
);
if (resolver === undefined || resolver === null) return null;
let regexp = pkg.templateToRegexp(prov.template);
let match = resolver.match(regexp);
return (match && match[1]) || null;
};
_paramText.write = function (section_id, formvalue) {
let template = this.map.data.get(
this.map.config,
section_id,
"resolver_url"
);
if (!formvalue && _paramText.template !== template) return 0;
let resolver = pkg.templateToResolver(_paramText.template, {
option: formvalue || "",
});
L.uci.set(pkg.Name, section_id, "resolver_url", resolver);
};
_paramText.remove = _paramText.write;
}
}
function createBootstrapWidget(s, i, prov) {
const _boot_dns = s.option(
form.Value,
"_bootstrap_dns_" + i,
@@ -345,85 +524,120 @@ return view.extend({
);
return c_value || prov.bootstrap_dns || "";
};
_boot_dns.write = function (section_id, formvalue) {
const resolver = this.map.data.get(
this.map.config,
section_id,
"resolver_url"
);
const regexp = pkg.templateToRegexp(_boot_dns.template);
if (regexp.test(resolver)) {
console.log(
pkg.Name,
section_id,
"bootstrap_dns",
formvalue,
this.cfgvalue(section_id)
);
if (formvalue)
L.uci.set(pkg.Name, section_id, "bootstrap_dns", formvalue);
else
L.uci.set(
pkg.Name,
section_id,
"bootstrap_dns",
this.cfgvalue(section_id)
);
}
_boot_dns.remove = _boot_dns.write;
};
_boot_dns.write = function (section_id, formvalue) { };
_boot_dns.remove = function (section_id, formvalue) { };
}
reply.providers.forEach((prov, i) => {
if (prov.http2_only && !reply.platform.http2_support) return;
if (prov.http3_only && !reply.platform.http3_support) return;
_provider.value(prov.template, _(prov.title));
createProviderWidget(s, i, prov);
createBootstrapWidget(s, i, prov);
});
o = s.option(form.Value, "listen_addr", _("Listen Address"));
o.datatype = "ipaddr('nomask')";
o.default = "";
o.optional = true;
o.placeholder = "127.0.0.1";
o.textvalue = function (section_id) {
var value = this.cfgvalue(section_id);
if (value) return value;
var globalValue = this.map.data.get(this.map.config, "config", "listen_addr");
return globalValue || this.placeholder || _("auto");
};
o = s.option(form.Value, "listen_port", _("Listen Port"));
o.datatype = "port";
o.default = "";
o.optional = true;
o.placeholder = "5053";
o.textvalue = function (section_id) {
var value = this.cfgvalue(section_id);
return value || _("auto");
};
o = s.option(form.Value, "source_addr", _("Source (Bind To) Address"));
o.datatype = "ipaddr('nomask')";
o.optional = true;
o.textvalue = function (section_id) {
var value = this.cfgvalue(section_id);
return value || _("*");
};
o = s.option(form.Value, "user", _("Run As User"));
o.default = "";
o.modalonly = true;
o.optional = true;
o.placeholder = "nobody";
o = s.option(form.Value, "group", _("Run As Group"));
o.default = "";
o.modalonly = true;
o.optional = true;
o.placeholder = "nogroup";
o = s.option(form.Value, "dscp_codepoint", _("DSCP Codepoint"));
o.datatype = "range(0,63)";
o.default = "";
o.modalonly = true;
o.optional = true;
o = s.option(form.Value, "verbosity", _("Logging Verbosity"));
o.datatype = "range(0,4)";
o.default = "";
o = s.option(form.ListValue, "verbosity", _("Logging Verbosity Level"));
o.modalonly = true;
o.optional = true;
o.value("", _("0: Fatal"));
o.value("1", _("1: Error"));
o.value("2", _("2: Warning"));
o.value("3", _("3: Info"));
o.value("4", _("4: Debug"));
o.default = "";
o = s.option(form.Value, "logfile", _("Logging File Path"));
o.default = "";
o.modalonly = true;
o.optional = true;
o = s.option(form.Value, "polling_interval", _("Polling Interval"));
o.datatype = "range(5,3600)";
o.default = "";
o.modalonly = true;
o.optional = true;
o.placeholder = "120";
o = s.option(form.Value, "proxy_server", _("Proxy Server"));
o.modalonly = true;
o.optional = true;
o = s.option(form.Value, "proxy_server", _("Proxy Server"));
o.default = "";
o = s.option(form.Value, "ca_certs_file", _("CA Certs File"));
o.datatype = "file";
o.modalonly = true;
o.optional = true;
o = s.option(form.Value, "conn_loss_time", _("Connection Loss Time"));
o.datatype = "uinteger";
o.modalonly = true;
o.optional = true;
o.placeholder = "15";
o = s.option(form.Value, "log_limit", _("Log Limit"));
o.datatype = "uinteger";
o.modalonly = true;
o.optional = true;
o.placeholder = "0";
o = s.option(form.Value, "max_idle_time", _("Max Idle Time"));
o.datatype = "uinteger";
o.modalonly = true;
o.optional = true;
o.placeholder = "118";
o = s.option(form.Value, "statistic_interval", _("Statistic Interval"));
o.datatype = "uinteger";
o.modalonly = true;
o.optional = true;
o.placeholder = "0";
o = s.option(form.Value, "tcp_client_limit", _("TCP Client Limit"));
o.datatype = "uinteger";
o.modalonly = true;
o.optional = true;
o.placeholder = "20";
o = s.option(form.ListValue, "force_http1", _("Use HTTP/1"));
o.modalonly = true;
o.optional = true;
@@ -432,11 +646,16 @@ return view.extend({
o.value("1", _("Force use of HTTP/1"));
o.default = "";
o = s.option(
form.ListValue,
"force_ipv6_resolvers",
_("Use IPv6 resolvers")
);
o = s.option(form.ListValue, "force_http3", _("Use HTTP/3 (QUIC)"));
o.modalonly = true;
o.optional = true;
o.rmempty = true;
o.value("", _("Use negotiated HTTP version"));
o.value("1", _("Force use of HTTP/3 (QUIC)"));
o.default = "";
o.depends("force_http1", "");
o = s.option(form.ListValue, "force_ipv6_resolvers", _("Use IPv6 resolvers"));
o.modalonly = true;
o.optional = true;
o.rmempty = true;

View File

@@ -9,6 +9,35 @@ msgstr ""
msgid "%s%s%s proxy on port %s.%s"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:564
msgid "*"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:251
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:585
msgid "0: Fatal"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:252
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:586
msgid "1: Error"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:253
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:587
msgid "2: Warning"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:254
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:588
msgid "3: Info"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:255
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:589
msgid "4: Debug"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/co.oszx.dns.json:14
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/gr.libredns.doh.json:14
msgid "AdBlocking Filter"
@@ -74,22 +103,27 @@ msgstr ""
msgid "BlahDNS"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:154
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:161
msgid ""
"Blocks access to Mozilla Encrypted resolvers, forcing local devices to use "
"router for DNS resolution (%smore information%s)."
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:138
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:144
msgid ""
"Blocks access to iCloud Private Relay resolvers, forcing local devices to "
"use router for DNS resolution (%smore information%s)."
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:335
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:514
msgid "Bootstrap DNS"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:289
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:606
msgid "CA Certs File"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/net.cfiec.dns.json:2
msgid "CFIEC Public IPv6 Only DNS (CN)"
msgstr ""
@@ -98,11 +132,11 @@ msgstr ""
msgid "CIRA Canadian Shield"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:152
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:159
msgid "Canary Domains Mozilla"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:136
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:142
msgid "Canary Domains iCloud"
msgstr ""
@@ -122,6 +156,11 @@ msgstr ""
msgid "Comss DNS (RU)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:293
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:611
msgid "Connection Loss Time"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/com.controld.freedns.json:2
msgid "ControlD"
msgstr ""
@@ -146,7 +185,7 @@ msgstr ""
msgid "DNSlify DNS"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:399
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:577
msgid "DSCP Codepoint"
msgstr ""
@@ -174,7 +213,7 @@ msgstr ""
msgid "Disabling %s service"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:73
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:76
msgid "Do not update configs"
msgstr ""
@@ -228,25 +267,32 @@ msgstr ""
msgid "Force DNS ports:"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:121
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:126
msgid "Force Router DNS"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:130
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:145
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:164
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:135
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:151
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:171
msgid "Force Router DNS server to all local devices"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:432
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:221
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:646
msgid "Force use of HTTP/1"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:444
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:233
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:654
msgid "Force use of HTTP/3 (QUIC)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:246
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:663
msgid "Force use of IPv6 DNS resolvers"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:123
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:128
msgid ""
"Forces Router DNS use on local devices, also known as DNS Hijacking. Only "
"works on `lan` interface by default (%smore information%s)."
@@ -256,6 +302,10 @@ msgstr ""
msgid "Germany"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:52
msgid "Global Instance Options"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/google.dns.json:2
msgid "Google"
msgstr ""
@@ -272,7 +322,7 @@ msgstr ""
msgid "HTTPS DNS Proxy - Configuration"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:191
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:341
msgid "HTTPS DNS Proxy - Instances"
msgstr ""
@@ -284,6 +334,18 @@ msgstr ""
msgid "HTTPS DNS Proxy Instances"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:179
msgid "Heartbeat Domain"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:194
msgid "Heartbeat Sleep Timeout"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:205
msgid "Heartbeat Wait Timeout"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/net.he.ordns.json:2
msgid "Hurricane Electric"
msgstr ""
@@ -296,7 +358,7 @@ msgstr ""
msgid "IIJ Public DNS (JP)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:63
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:66
msgid ""
"If update option is selected, the %s'DNS Forwards' section of DHCP and DNS%s "
"will be automatically updated to use selected DoH providers (%smore "
@@ -319,15 +381,15 @@ msgstr ""
msgid "Lelux DNS (FI)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:163
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:170
msgid "Let local devices use Mozilla Private Relay"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:144
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:150
msgid "Let local devices use iCloud Private Relay"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:129
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:134
msgid "Let local devices use their own DNS servers if set"
msgstr ""
@@ -335,12 +397,13 @@ msgstr ""
msgid "LibreDNS (GR)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:377
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:258
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:539
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/status/include/71_https-dns-proxy.js:56
msgid "Listen Address"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:383
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:550
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/status/include/71_https-dns-proxy.js:57
msgid "Listen Port"
msgstr ""
@@ -350,18 +413,30 @@ msgstr ""
msgid "Location"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:411
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:298
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:617
msgid "Log Limit"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:276
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:592
msgid "Logging File Path"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:405
msgid "Logging Verbosity"
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:249
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:582
msgid "Logging Verbosity Level"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/com.controld.freedns.json:22
msgid "Malware Filter"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:303
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:623
msgid "Max Idle Time"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/net.mullvad.dns.json:2
msgid "Mullvad"
msgstr ""
@@ -406,8 +481,8 @@ msgstr ""
msgid "OpenNameServer"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:267
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:299
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:469
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:485
msgid "Parameter"
msgstr ""
@@ -415,8 +490,8 @@ msgstr ""
msgid "Please %sdonate%s to support development of this project."
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:172
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:181
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:322
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:331
msgid ""
"Please note that %s is not supported on this system (%smore information%s)."
msgstr ""
@@ -425,7 +500,8 @@ msgstr ""
msgid "Poland"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:416
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:281
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:596
msgid "Polling Interval"
msgstr ""
@@ -453,11 +529,12 @@ msgstr ""
msgid "Protective with child protection & ad-blocking"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:233
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:383
msgid "Provider"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:422
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:286
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:602
msgid "Proxy Server"
msgstr ""
@@ -489,11 +566,13 @@ msgstr ""
msgid "RubyFish (CN)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:394
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:267
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:572
msgid "Run As Group"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:389
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:263
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:567
msgid "Run As User"
msgstr ""
@@ -518,7 +597,7 @@ msgstr ""
msgid "See the %sREADME%s for details."
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:99
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:103
msgid "Select the DNSMASQ Configs to update"
msgstr ""
@@ -530,6 +609,10 @@ msgstr ""
msgid "Service Instances"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:51
msgid "Service Options"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/https-dns-proxy/status.js:191
msgid "Service Status"
msgstr ""
@@ -542,6 +625,14 @@ msgstr ""
msgid "Snopyta DNS (FI)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:559
msgid "Source (Bind To) Address"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:271
msgid "Source Address"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/net.ahadns.doh.json:22
msgid "Spain"
msgstr ""
@@ -564,6 +655,11 @@ msgstr ""
msgid "Starting %s service"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:308
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:629
msgid "Statistic Interval"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/https-dns-proxy/status.js:370
msgid "Stop"
msgstr ""
@@ -580,6 +676,15 @@ msgstr ""
msgid "Switzerland"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:313
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:635
msgid "TCP Client Limit"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:181
msgid "The domain used for connectivity checks (%smore information%s)."
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/status/include/71_https-dns-proxy.js:105
msgid "There are no active instances."
msgstr ""
@@ -588,6 +693,14 @@ msgstr ""
msgid "Tiarap Public DNS (JP)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:195
msgid "Time to wait before checking connectivity (seconds)."
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:206
msgid "Time to wait for connectivity check response (seconds)."
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/net.ahadns.doh.json:18
msgid "US/Chicago"
msgstr ""
@@ -605,7 +718,7 @@ msgstr ""
msgid "Unfiltered"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:229
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:379
msgid "Unknown"
msgstr ""
@@ -613,31 +726,42 @@ msgstr ""
msgid "Unsecured"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:61
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:64
msgid "Update DNSMASQ Config on Start/Stop"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:71
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:74
msgid "Update all configs"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:72
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:75
msgid "Update select configs"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:427
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:216
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:641
msgid "Use HTTP/1"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:438
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:228
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:649
msgid "Use HTTP/3 (QUIC)"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:241
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:658
msgid "Use IPv6 resolvers"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:443
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:245
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:662
msgid "Use any family DNS resolvers"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:431
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:220
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:232
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:645
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:653
msgid "Use negotiated HTTP version"
msgstr ""
@@ -675,6 +799,11 @@ msgstr ""
msgid "Wikimedia"
msgstr ""
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:547
#: applications/luci-app-https-dns-proxy/htdocs/luci-static/resources/view/https-dns-proxy/overview.js:556
msgid "auto"
msgstr ""
#: applications/luci-app-https-dns-proxy/root/usr/share/https-dns-proxy/providers/org.opennameserver.json:14
msgid "ns1: Germany - Baden-Baden"
msgstr ""