LibWebView+RequestSever: Wire up a validate-DNSSEC setting option to RS

This commit is contained in:
Ali Mohammad Pur 2025-05-13 12:34:55 +02:00 committed by Ali Mohammad Pur
commit 4b5664f867
Notes: github-actions[bot] 2025-06-11 16:17:43 +00:00
9 changed files with 39 additions and 19 deletions

View file

@ -403,6 +403,10 @@
<option value="tls">TLS</option> <option value="tls">TLS</option>
</select> </select>
</div> </div>
<div class="card-group">
<label for="dnssec-toggle">Validate DNSSEC Locally</label>
<input id="dnssec-toggle" type="checkbox" switch />
</div>
<div class="card-group"> <div class="card-group">
<label for="dns-server">DNS Server (IP or hostname)</label> <label for="dns-server">DNS Server (IP or hostname)</label>
<input id="dns-server" type="text" /> <input id="dns-server" type="text" />

View file

@ -5,6 +5,7 @@ const dnsUpstream = document.querySelector("#dns-upstream");
const dnsType = document.querySelector("#dns-type"); const dnsType = document.querySelector("#dns-type");
const dnsServer = document.querySelector("#dns-server"); const dnsServer = document.querySelector("#dns-server");
const dnsPort = document.querySelector("#dns-port"); const dnsPort = document.querySelector("#dns-port");
const dnssecToggle = document.querySelector("#dnssec-toggle");
let DNS_SETTINGS = {}; let DNS_SETTINGS = {};
@ -20,12 +21,14 @@ function loadDnsSettings() {
dnsType.value = DNS_SETTINGS.type; dnsType.value = DNS_SETTINGS.type;
dnsServer.value = DNS_SETTINGS.server; dnsServer.value = DNS_SETTINGS.server;
dnsPort.value = DNS_SETTINGS.port; dnsPort.value = DNS_SETTINGS.port;
dnssecToggle.checked = DNS_SETTINGS.dnssec;
customDnsSettings.classList.remove("hidden"); customDnsSettings.classList.remove("hidden");
} else { } else {
dnsType.value = "udp"; dnsType.value = "udp";
dnsServer.value = ""; dnsServer.value = "";
dnsPort.value = "53"; dnsPort.value = "53";
dnssecToggle.checked = false;
customDnsSettings.classList.add("hidden"); customDnsSettings.classList.add("hidden");
} }
@ -37,6 +40,7 @@ function loadDnsSettings() {
dnsType.disabled = true; dnsType.disabled = true;
dnsServer.disabled = true; dnsServer.disabled = true;
dnsPort.disabled = true; dnsPort.disabled = true;
dnssecToggle.disabled = true;
} else { } else {
dnsForciblyEnabled.classList.add("hidden"); dnsForciblyEnabled.classList.add("hidden");
@ -44,6 +48,7 @@ function loadDnsSettings() {
dnsType.disabled = false; dnsType.disabled = false;
dnsServer.disabled = false; dnsServer.disabled = false;
dnsPort.disabled = false; dnsPort.disabled = false;
dnssecToggle.disabled = false;
} }
} }
@ -76,12 +81,14 @@ function updateDnsSettings() {
type: dnsType.value, type: dnsType.value,
server: dnsServer.value, server: dnsServer.value,
port: dnsPort.value | 0, port: dnsPort.value | 0,
dnssec: dnssecToggle.checked,
}); });
} }
dnsServer.addEventListener("change", updateDnsSettings); dnsServer.addEventListener("change", updateDnsSettings);
dnsPort.addEventListener("change", updateDnsSettings); dnsPort.addEventListener("change", updateDnsSettings);
dnsType.addEventListener("change", updateDnsSettings); dnsType.addEventListener("change", updateDnsSettings);
dnssecToggle.addEventListener("change", updateDnsSettings);
document.addEventListener("WebUIMessage", event => { document.addEventListener("WebUIMessage", event => {
if (event.detail.name === "loadSettings") { if (event.detail.name === "loadSettings") {

View file

@ -40,12 +40,12 @@ struct ApplicationSettingsObserver : public SettingsObserver {
Application::request_server_client().async_set_use_system_dns(); Application::request_server_client().async_set_use_system_dns();
}, },
[](DNSOverTLS const& dns_over_tls) { [](DNSOverTLS const& dns_over_tls) {
dbgln("Setting DNS server to {}:{} with TLS", dns_over_tls.server_address, dns_over_tls.port); dbgln("Setting DNS server to {}:{} with TLS ({} local dnssec)", dns_over_tls.server_address, dns_over_tls.port, dns_over_tls.validate_dnssec_locally ? "with" : "without");
Application::request_server_client().async_set_dns_server(dns_over_tls.server_address, dns_over_tls.port, true); Application::request_server_client().async_set_dns_server(dns_over_tls.server_address, dns_over_tls.port, true, dns_over_tls.validate_dnssec_locally);
}, },
[](DNSOverUDP const& dns_over_udp) { [](DNSOverUDP const& dns_over_udp) {
dbgln("Setting DNS server to {}:{}", dns_over_udp.server_address, dns_over_udp.port); dbgln("Setting DNS server to {}:{} ({} local dnssec)", dns_over_udp.server_address, dns_over_udp.port, dns_over_udp.validate_dnssec_locally ? "with" : "without");
Application::request_server_client().async_set_dns_server(dns_over_udp.server_address, dns_over_udp.port, false); Application::request_server_client().async_set_dns_server(dns_over_udp.server_address, dns_over_udp.port, false, dns_over_udp.validate_dnssec_locally);
}); });
} }
}; };
@ -110,6 +110,7 @@ ErrorOr<void> Application::initialize(Main::Arguments const& arguments)
Optional<u16> dns_server_port; Optional<u16> dns_server_port;
bool use_dns_over_tls = false; bool use_dns_over_tls = false;
bool layout_test_mode = false; bool layout_test_mode = false;
bool validate_dnssec_locally = false;
bool log_all_js_exceptions = false; bool log_all_js_exceptions = false;
bool disable_site_isolation = false; bool disable_site_isolation = false;
bool enable_idl_tracing = false; bool enable_idl_tracing = false;
@ -171,6 +172,7 @@ ErrorOr<void> Application::initialize(Main::Arguments const& arguments)
args_parser.add_option(dns_server_address, "Set the DNS server address", "dns-server", 0, "host|address"); args_parser.add_option(dns_server_address, "Set the DNS server address", "dns-server", 0, "host|address");
args_parser.add_option(dns_server_port, "Set the DNS server port", "dns-port", 0, "port (default: 53 or 853 if --dot)"); args_parser.add_option(dns_server_port, "Set the DNS server port", "dns-port", 0, "port (default: 53 or 853 if --dot)");
args_parser.add_option(use_dns_over_tls, "Use DNS over TLS", "dot"); args_parser.add_option(use_dns_over_tls, "Use DNS over TLS", "dot");
args_parser.add_option(validate_dnssec_locally, "Validate DNSSEC locally", "dnssec");
args_parser.add_option(Core::ArgsParser::Option { args_parser.add_option(Core::ArgsParser::Option {
.argument_mode = Core::ArgsParser::OptionArgumentMode::Required, .argument_mode = Core::ArgsParser::OptionArgumentMode::Required,
@ -220,8 +222,8 @@ ErrorOr<void> Application::initialize(Main::Arguments const& arguments)
.profile_helper_process = move(profile_process_type), .profile_helper_process = move(profile_process_type),
.dns_settings = (dns_server_address.has_value() .dns_settings = (dns_server_address.has_value()
? Optional<DNSSettings> { use_dns_over_tls ? Optional<DNSSettings> { use_dns_over_tls
? DNSSettings(DNSOverTLS(dns_server_address.release_value(), *dns_server_port)) ? DNSSettings(DNSOverTLS(dns_server_address.release_value(), *dns_server_port, validate_dnssec_locally))
: DNSSettings(DNSOverUDP(dns_server_address.release_value(), *dns_server_port)) } : DNSSettings(DNSOverUDP(dns_server_address.release_value(), *dns_server_port, validate_dnssec_locally)) }
: OptionalNone()), : OptionalNone()),
.devtools_port = devtools_port, .devtools_port = devtools_port,
}; };

View file

@ -220,12 +220,12 @@ ErrorOr<NonnullRefPtr<Requests::RequestClient>> launch_request_server_process()
WebView::Application::settings().dns_settings().visit( WebView::Application::settings().dns_settings().visit(
[](WebView::SystemDNS) {}, [](WebView::SystemDNS) {},
[&](WebView::DNSOverTLS const& dns_over_tls) { [&](WebView::DNSOverTLS const& dns_over_tls) {
dbgln("Setting DNS server to {}:{} with TLS", dns_over_tls.server_address, dns_over_tls.port); dbgln("Setting DNS server to {}:{} with TLS ({} local dnssec)", dns_over_tls.server_address, dns_over_tls.port, dns_over_tls.validate_dnssec_locally ? "with" : "without");
client->async_set_dns_server(dns_over_tls.server_address, dns_over_tls.port, true); client->async_set_dns_server(dns_over_tls.server_address, dns_over_tls.port, true, dns_over_tls.validate_dnssec_locally);
}, },
[&](WebView::DNSOverUDP const& dns_over_udp) { [&](WebView::DNSOverUDP const& dns_over_udp) {
dbgln("Setting DNS server to {}:{}", dns_over_udp.server_address, dns_over_udp.port); dbgln("Setting DNS server to {}:{} ({} local dnssec)", dns_over_udp.server_address, dns_over_udp.port, dns_over_udp.validate_dnssec_locally ? "with" : "without");
client->async_set_dns_server(dns_over_udp.server_address, dns_over_udp.port, false); client->async_set_dns_server(dns_over_udp.server_address, dns_over_udp.port, false, dns_over_udp.validate_dnssec_locally);
}); });
return client; return client;

View file

@ -56,10 +56,12 @@ struct SystemDNS { };
struct DNSOverTLS { struct DNSOverTLS {
ByteString server_address; ByteString server_address;
u16 port; u16 port;
bool validate_dnssec_locally;
}; };
struct DNSOverUDP { struct DNSOverUDP {
ByteString server_address; ByteString server_address;
u16 port; u16 port;
bool validate_dnssec_locally;
}; };
using DNSSettings = Variant<SystemDNS, DNSOverTLS, DNSOverUDP>; using DNSSettings = Variant<SystemDNS, DNSOverTLS, DNSOverUDP>;

View file

@ -209,7 +209,7 @@ JsonValue Settings::serialize_json() const
settings.set(do_not_track_key, m_do_not_track == DoNotTrack::Yes); settings.set(do_not_track_key, m_do_not_track == DoNotTrack::Yes);
// dnsSettings :: { mode: "system" } | { mode: "custom", server: string, port: u16, type: "udp" | "tls", forciblyEnabled: bool } // dnsSettings :: { mode: "system" } | { mode: "custom", server: string, port: u16, type: "udp" | "tls", forciblyEnabled: bool, dnssec: bool }
JsonObject dns_settings; JsonObject dns_settings;
m_dns_settings.visit( m_dns_settings.visit(
[&](SystemDNS) { [&](SystemDNS) {
@ -220,6 +220,7 @@ JsonValue Settings::serialize_json() const
dns_settings.set("server"sv, dot.server_address.view()); dns_settings.set("server"sv, dot.server_address.view());
dns_settings.set("port"sv, dot.port); dns_settings.set("port"sv, dot.port);
dns_settings.set("type"sv, "tls"sv); dns_settings.set("type"sv, "tls"sv);
dns_settings.set("dnssec"sv, dot.validate_dnssec_locally);
dns_settings.set("forciblyEnabled"sv, m_dns_override_by_command_line); dns_settings.set("forciblyEnabled"sv, m_dns_override_by_command_line);
}, },
[&](DNSOverUDP const& dns) { [&](DNSOverUDP const& dns) {
@ -227,6 +228,7 @@ JsonValue Settings::serialize_json() const
dns_settings.set("server"sv, dns.server_address.view()); dns_settings.set("server"sv, dns.server_address.view());
dns_settings.set("port"sv, dns.port); dns_settings.set("port"sv, dns.port);
dns_settings.set("type"sv, "udp"sv); dns_settings.set("type"sv, "udp"sv);
dns_settings.set("dnssec"sv, dns.validate_dnssec_locally);
dns_settings.set("forciblyEnabled"sv, m_dns_override_by_command_line); dns_settings.set("forciblyEnabled"sv, m_dns_override_by_command_line);
}); });
settings.set(dns_settings_key, move(dns_settings)); settings.set(dns_settings_key, move(dns_settings));
@ -441,12 +443,13 @@ DNSSettings Settings::parse_dns_settings(JsonValue const& dns_settings)
auto server = dns_settings_object.get_string("server"sv); auto server = dns_settings_object.get_string("server"sv);
auto port = dns_settings_object.get_u16("port"sv); auto port = dns_settings_object.get_u16("port"sv);
auto type = dns_settings_object.get_string("type"sv); auto type = dns_settings_object.get_string("type"sv);
auto validate_dnssec_locally = dns_settings_object.get_bool("dnssec"sv);
if (server.has_value() && port.has_value() && type.has_value()) { if (server.has_value() && port.has_value() && type.has_value()) {
if (*type == "tls"sv) if (*type == "tls"sv)
return DNSOverTLS { .server_address = server->to_byte_string(), .port = *port }; return DNSOverTLS { .server_address = server->to_byte_string(), .port = *port, .validate_dnssec_locally = validate_dnssec_locally.value_or(false) };
if (*type == "udp"sv) if (*type == "udp"sv)
return DNSOverUDP { .server_address = server->to_byte_string(), .port = *port }; return DNSOverUDP { .server_address = server->to_byte_string(), .port = *port, .validate_dnssec_locally = validate_dnssec_locally.value_or(false) };
} }
} }
} }

View file

@ -39,6 +39,7 @@ static struct {
Optional<ByteString> server_hostname; Optional<ByteString> server_hostname;
u16 port; u16 port;
bool use_dns_over_tls = true; bool use_dns_over_tls = true;
bool validate_dnssec_locally = false;
} g_dns_info; } g_dns_info;
static WeakPtr<Resolver> s_resolver {}; static WeakPtr<Resolver> s_resolver {};
@ -375,9 +376,9 @@ Messages::RequestServer::IsSupportedProtocolResponse ConnectionFromClient::is_su
return protocol == "http"sv || protocol == "https"sv; return protocol == "http"sv || protocol == "https"sv;
} }
void ConnectionFromClient::set_dns_server(ByteString host_or_address, u16 port, bool use_tls) void ConnectionFromClient::set_dns_server(ByteString host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally)
{ {
if (host_or_address == g_dns_info.server_hostname && port == g_dns_info.port && use_tls == g_dns_info.use_dns_over_tls) if (host_or_address == g_dns_info.server_hostname && port == g_dns_info.port && use_tls == g_dns_info.use_dns_over_tls && validate_dnssec_locally == g_dns_info.validate_dnssec_locally)
return; return;
auto result = [&] -> ErrorOr<void> { auto result = [&] -> ErrorOr<void> {
@ -393,6 +394,7 @@ void ConnectionFromClient::set_dns_server(ByteString host_or_address, u16 port,
g_dns_info.server_hostname = host_or_address; g_dns_info.server_hostname = host_or_address;
g_dns_info.port = port; g_dns_info.port = port;
g_dns_info.use_dns_over_tls = use_tls; g_dns_info.use_dns_over_tls = use_tls;
g_dns_info.validate_dnssec_locally = validate_dnssec_locally;
return {}; return {};
}(); }();
@ -419,7 +421,7 @@ void ConnectionFromClient::start_request(i32 request_id, ByteString method, URL:
{ {
auto host = url.serialized_host().to_byte_string(); auto host = url.serialized_host().to_byte_string();
m_resolver->dns.lookup(host, DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA }) m_resolver->dns.lookup(host, DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA }, { .validate_dnssec_locally = g_dns_info.validate_dnssec_locally })
->when_rejected([this, request_id](auto const& error) { ->when_rejected([this, request_id](auto const& error) {
dbgln("StartRequest: DNS lookup failed: {}", error); dbgln("StartRequest: DNS lookup failed: {}", error);
// FIXME: Implement timing info for DNS lookup failure. // FIXME: Implement timing info for DNS lookup failure.
@ -753,7 +755,7 @@ void ConnectionFromClient::ensure_connection(URL::URL url, ::RequestServer::Cach
} }
if (cache_level == CacheLevel::ResolveOnly) { if (cache_level == CacheLevel::ResolveOnly) {
[[maybe_unused]] auto promise = m_resolver->dns.lookup(url.serialized_host().to_byte_string(), DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA }); [[maybe_unused]] auto promise = m_resolver->dns.lookup(url.serialized_host().to_byte_string(), DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA }, { .validate_dnssec_locally = g_dns_info.validate_dnssec_locally });
if constexpr (REQUESTSERVER_DEBUG) { if constexpr (REQUESTSERVER_DEBUG) {
Core::ElapsedTimer timer; Core::ElapsedTimer timer;
timer.start(); timer.start();

View file

@ -40,7 +40,7 @@ private:
virtual Messages::RequestServer::InitTransportResponse init_transport(int peer_pid) override; virtual Messages::RequestServer::InitTransportResponse init_transport(int peer_pid) override;
virtual Messages::RequestServer::ConnectNewClientResponse connect_new_client() override; virtual Messages::RequestServer::ConnectNewClientResponse connect_new_client() override;
virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString) override; virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(ByteString) override;
virtual void set_dns_server(ByteString host_or_address, u16 port, bool use_tls) override; virtual void set_dns_server(ByteString host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally) override;
virtual void set_use_system_dns() override; virtual void set_use_system_dns() override;
virtual void start_request(i32 request_id, ByteString, URL::URL, HTTP::HeaderMap, ByteBuffer, Core::ProxyData) override; virtual void start_request(i32 request_id, ByteString, URL::URL, HTTP::HeaderMap, ByteBuffer, Core::ProxyData) override;
virtual Messages::RequestServer::StopRequestResponse stop_request(i32) override; virtual Messages::RequestServer::StopRequestResponse stop_request(i32) override;

View file

@ -9,7 +9,7 @@ endpoint RequestServer
connect_new_client() => (IPC::File client_socket) connect_new_client() => (IPC::File client_socket)
// use_tls: enable DNS over TLS // use_tls: enable DNS over TLS
set_dns_server(ByteString host_or_address, u16 port, bool use_tls) =| set_dns_server(ByteString host_or_address, u16 port, bool use_tls, bool validate_dnssec_locally) =|
set_use_system_dns() =| set_use_system_dns() =|
// Test if a specific protocol is supported, e.g "http" // Test if a specific protocol is supported, e.g "http"