diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4866ada..f72bb092 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,10 @@ NOTE: Add new changes BELOW THIS COMMENT.
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.23.6][go-1.23.6].
+### Added
+
+- The ability to specify the upstream timeout in the Web UI.
+
### Changed
- The *Fastest IP adddress* upstream mode now collects statistics for the all upstream DNS servers.
diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index c7428cdc..9634cf70 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -6,7 +6,7 @@
"upstream_parallel": "Use parallel queries to speed up resolving by querying all upstream servers simultaneously.",
"parallel_requests": "Parallel requests",
"load_balancing": "Load-balancing",
- "load_balancing_desc": "Query one upstream server at a time. AdGuard Home uses a weighted random algorithm to select servers with the lowest number of failed lookups and the lowest average lookup time.",
+ "load_balancing_desc": "Query one upstream server at a time. AdGuard Home uses a weighted random algorithm to select servers with the lowest number of failed lookups and the lowest average lookup time.",
"bootstrap_dns": "Bootstrap DNS servers",
"bootstrap_dns_desc": "IP addresses of DNS servers used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams. Comments are not permitted.",
"fallback_dns_title": "Fallback DNS servers",
@@ -294,6 +294,9 @@
"blocked_response_ttl": "Blocked response TTL",
"blocked_response_ttl_desc": "Specifies for how many seconds the clients should cache a filtered response",
"form_enter_blocked_response_ttl": "Enter blocked response TTL (seconds)",
+ "upstream_timeout": "Upstream timeout",
+ "upstream_timeout_desc": "Specifies the number of seconds to wait for a response from the upstream server",
+ "form_enter_upstream_timeout": "Enter the upstream server timeout duration in seconds",
"dnscrypt": "DNSCrypt",
"dns_over_https": "DNS-over-HTTPS",
"dns_over_tls": "DNS-over-TLS",
@@ -598,7 +601,7 @@
"disable_ipv6": "Disable resolving of IPv6 addresses",
"disable_ipv6_desc": "Drop all DNS queries for IPv6 addresses (type AAAA) and remove IPv6 hints from HTTPS responses.",
"fastest_addr": "Fastest IP address",
- "fastest_addr_desc": "Query all DNS servers and return the fastest IP address among all responses. This slows down DNS queries as AdGuard Home has to wait for responses from all DNS servers, but improves the overall connectivity.",
+ "fastest_addr_desc": "Wait for responses from all DNS servers, measure the TCP connection speed for each server, and return the IP address of the server with the fastest connection speed. This mode can significantly slow down DNS queries, if one or more upstream servers are not responding. Make sure that your upstream servers are stable and your upstream timeout is low.",
"autofix_warning_text": "If you click \"Fix\", AdGuard Home will configure your system to use AdGuard Home DNS server.",
"autofix_warning_list": "It will perform these tasks: <0>Deactivate system DNSStubListener0> <0>Set DNS server address to 127.0.0.10> <0>Replace symbolic link target of /etc/resolv.conf with /run/systemd/resolve/resolv.conf0> <0>Stop DNSStubListener (reload systemd-resolved service)0>",
"autofix_warning_result": "As a result all DNS requests from your system will be processed by AdGuard Home by default.",
diff --git a/client/src/components/Settings/Dns/Upstream/Form.tsx b/client/src/components/Settings/Dns/Upstream/Form.tsx
index f53a7038..db367507 100644
--- a/client/src/components/Settings/Dns/Upstream/Form.tsx
+++ b/client/src/components/Settings/Dns/Upstream/Form.tsx
@@ -7,8 +7,19 @@ import classnames from 'classnames';
import Examples from './Examples';
-import { renderRadioField, renderTextareaField, CheckboxField } from '../../../../helpers/form';
-import { DNS_REQUEST_OPTIONS, FORM_NAME, UPSTREAM_CONFIGURATION_WIKI_LINK } from '../../../../helpers/constants';
+import {
+ renderRadioField,
+ renderTextareaField,
+ CheckboxField,
+ renderInputField,
+ toNumber,
+} from '../../../../helpers/form';
+import {
+ DNS_REQUEST_OPTIONS,
+ FORM_NAME,
+ UINT32_RANGE,
+ UPSTREAM_CONFIGURATION_WIKI_LINK,
+} from '../../../../helpers/constants';
import { testUpstreamWithFormValues } from '../../../../actions';
@@ -17,6 +28,7 @@ import { removeEmptyLines, trimLinesAndRemoveEmpty } from '../../../../helpers/h
import { getTextareaCommentsHighlight, syncScroll } from '../../../../helpers/highlightTextareaComments';
import '../../../ui/texareaCommentsHighlight.css';
import { RootState } from '../../../../initialState';
+import { validateRequiredValue } from '../../../../helpers/validators';
const UPSTREAM_DNS_NAME = 'upstream_dns';
const UPSTREAM_MODE_NAME = 'upstream_mode';
@@ -301,7 +313,7 @@ const Form = ({ submitting, invalid, handleSubmit }: FormProps) => {