Commit Graph

31 Commits

Author SHA1 Message Date
Ville Vesilehto
f3983c1111 perf(proxy): use mutex-based connection pool (#7790)
* perf(proxy): use mutex-based connection pool

The proxy package (used for example by the forward plugin) utilized
an actor model where a single connManager goroutine managed
connection pooling via unbuffered channels (dial, yield, ret). This
design serialized all connection acquisition and release operations
through a single goroutine, creating a bottleneck under high
concurrency. This was observable as a performance degradation when
using a single upstream backend compared to multiple backends
(which sharded the bottleneck).

Changes:
- Removed dial, yield, and ret channels from the Transport struct.
- Removed the connManager goroutine's request processing loop.
- Implemented Dial() and Yield() using a sync.Mutex to protect the
  connection slice, allowing for fast concurrent access without
  context switching.
- Downgraded connManager to a simple background cleanup loop that
  only handles connection expiration on a ticker.
- Updated plugin/pkg/proxy/connect.go to use direct method calls
  instead of channel sends.
- Updated tests to reflect the removal of internal channels.

Benchmarks show that this change eliminates the single-backend
bottleneck. Now a single upstream backend performs on par with
multiple backends, and overall throughput is improved.

The implementation aligns with standard Go patterns for connection
pooling (e.g., net/http.Transport).

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* fix: address PR review for persistent.go

- Named mutex field instead of embedding, to not expose
  Lock() and Unlock()
- Move stop check outside of lock in Yield()
- Close() without a separate goroutine
- Change stop channel to struct

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* fix: address code review feedback for conn pool

- Switch from LIFO to FIFO connection selection for source port
  diversity, reducing DNS cache poisoning risk (RFC 5452).
- Remove "clear entire cache" optimization as it was LIFO-specific.
  FIFO naturally iterates and skips expired connections.
- Remove all goroutines for closing connections; collect connections
  while holding lock, close synchronously after releasing lock.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* fix: remove unused error consts

No longer utilised after refactoring the channel based approach.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* feat(forward): add max_idle_conns option

Add configurable connection pool limit for the forward plugin via
the max_idle_conns Corefile option.

Changes:
- Add SetMaxIdleConns to proxy
- Add maxIdleConns field to Forward struct
- Add max_idle_conns parsing in forward plugin setup
- Apply setting to each proxy during configuration
- Update forward plugin README with new option

By default the value is 0 (unbounded). When set, excess
connections returned to the pool are closed immediately
rather than cached.

Also add a yield related test.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* chore(proxy): simple Dial by closing conns inline

Remove toClose slice collection to reduce complexity. Instead close
expired connections directly while iterating. Reduces complexity with
negligible lock-time impact.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

* chore: fewer explicit Unlock calls

Cleaner and less chance of forgetting to unlock on new possible
code paths.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>

---------

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2026-01-13 17:49:46 -08:00
Ville Vesilehto
c2894d47d6 feat(forward): add max connect attempts knob (#7722) 2025-12-01 18:06:52 -08:00
Endre Szabo
d68cbedbb1 plugin/forward: added support for per-nameserver TLS SNI (#7633) 2025-10-27 08:43:30 -07:00
Ville Vesilehto
f4ab631ae4 fix(forward): disallow NOERROR in failover (#7622)
Previously the parsing logic in the forward plugin setup failed to
recognise when NOERROR was used as a failover RCODE criteria. The
check was in the wrong code branch. This PR fixes it and adds
validation tests. Also updates the plugin README.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-10-17 14:37:02 +03:00
Ville Vesilehto
3c950b8552 fix(forward): deflake TestFailover (#7558)
In CI, the first two upstream attempts can stall on UDP and each
consume the default 2s read timeout. Possibly exhausting most of
the 5s forward deadline before the healthy third upstream is tried.
Lower the read timeout to make retries faster.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-09-15 14:28:26 -07:00
Ville Vesilehto
c916cf4259 fix(plugin): nilness findings (#7556)
Enable nilness linter in govet.

Plugin-by-plugin rationale:

- plugin/transfer: reuse error instead of shadowing it inside the for
  loop by declaring "ret" outside of the loop
- plugin/view: remove redundant err check
- plugin/dnstap: avoid possible nil dereference in error reporting
  path in setup test
- plugin/forward: prevent nil deference or empty-slice dereference on
  error paths in setup test

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-09-15 10:17:06 -07:00
Ville Vesilehto
c149567dbe fix: lint issues from plugin/forward and plugin/pkg/dnstest (#7539)
To fix CI pipeline issues on master.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-09-13 15:14:10 -07:00
Fitz_dev
9683de0feb fix: No failover to next upstream when receiving SERVFAIL or REFUSED response codes(#7457) (#7458) 2025-09-12 14:45:01 -07:00
Puneet Loya
4de8fb57b2 plugin/forward: added option failfast_all_unhealthy_upstreams to return servfail if all upstreams are down (#6999)
* feat: option to return servfail if upstreams are down

Signed-off-by: Puneet Loya <puneetloya@Puneets-MBP.attlocal.net>

* fix based on review comments and added to Readme

Signed-off-by: Puneet Loya <puneetloya@Puneets-MBP.attlocal.net>

* add tests to improve code coverage

Signed-off-by: Puneet Loya <puneetloya@Puneets-MBP.attlocal.net>

* added failfast_all_unhealthy_upstreams option to forward plugin

Signed-off-by: Puneet Loya <puneetloya@Puneets-MBP.attlocal.net>

---------

Signed-off-by: Puneet Loya <puneetloya@Puneets-MBP.attlocal.net>
Co-authored-by: Puneet Loya <puneetloya@Puneets-MBP.attlocal.net>
2025-03-07 11:37:25 -05:00
Jasper Bernhardt
2e9986c622 Add alternate option to forward plugin (#6681)
Allows the forward plugin to execute the next plugin based on the return code. Similar to the externally mainted alternate plugin https://github.com/coredns/alternate

Based on the idea of chrisohaver@ in #6549 (comment)
Also incoperated the request to rename `alternate` to `next` as an option

I am having issues adding a proper test for functionality. Primarily, I do not know the code base enough and having multiple `dnstest.NewServer` with ResponseWriter does not work. From my testing these are "Singletons'' and only the last defined response writer is used for all servers

Signed-off-by: Jasper Bernhardt <jasper.bernhardt@live.de>
2024-07-01 11:20:12 -04:00
Manuel Alejandro de Brito Fontes
5b6d8e356c [plugin/forward] Strip local zone from IPV6 nameservers (#6635)
Signed-off-by: Alejandro de Brito Fontes <aledbf@gmail.com>
2024-04-26 13:12:25 -04:00
Pat Downey
f823825f8a plugin/forward: Allow Proxy to be used outside of forward plugin. (#5951)
* plugin/forward: Move Proxy into pkg/plugin/proxy, to allow forward.Proxy to be used outside of forward plugin.

Signed-off-by: Patrick Downey <patrick.downey@dioadconsulting.com>
2023-03-24 08:55:51 -04:00
Vancl
4033d7aeba plugin/forward: health_check needs to normalize a specified domain name (#5543)
* plugin/forward: convert the specified domain of health_check to Fqdn
* plugin/forward: update readme for health check

Signed-off-by: vanceli <vanceli@tencent.com>
2022-08-15 10:16:15 -04:00
Chris O'Haver
513f27b9a9 plugin/forward: Enable multiple forward declarations (#5127)
* enable multiple declarations of forward plugin

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>
2022-07-20 10:35:04 -04:00
hansedong
0622a6c66c plugin/forward: configurable domain support for healthcheck (#5281)
* plugin/forward: configurable domain support for healthcheck

Signed-off-by: hansedong <admin@yinxiaoluo.com>
2022-04-12 12:39:48 -04:00
Chris O'Haver
f8a02aaf58 dont panic when from-zone cannot be normalized (#5170)
Signed-off-by: Chris O'Haver <cohaver@infoblox.com>
2022-02-17 15:13:18 -05:00
Zou Nengren
5191959bd7 cleanup deprecated package io/ioutil (#4920)
Signed-off-by: zounengren <zouyee1989@gmail.com>
2021-10-13 09:30:31 +02:00
Chris O'Haver
0348b019be plugin/forward: Document and warn for unsupported FROM CIDR notations (#4639)
* trap unsupported FROM cidr notations

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* make is a warning

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>
2021-05-20 09:24:36 +02:00
Miek Gieben
b003d06003 For caddy v1 in our org (#4018)
* For caddy v1 in our org

This RP changes all imports for caddyserver/caddy to coredns/caddy. This
is the v1 code of caddy.

For the coredns/caddy repo the following changes have been made:

* anything not needed by us is deleted
* all `telemetry` stuff is deleted
* all its import paths are also changed to point to coredns/caddy
* the v1 branch has been moved to the master branch
* a v1.1.0 tag has been added to signal the latest release

Signed-off-by: Miek Gieben <miek@miek.nl>

* Fix imports

Signed-off-by: Miek Gieben <miek@miek.nl>

* Group coredns/caddy with out plugins

Signed-off-by: Miek Gieben <miek@miek.nl>

* remove this file

Signed-off-by: Miek Gieben <miek@miek.nl>

* Relax import ordering

github.com/coredns is now also a coredns dep, this makes
github.com/coredns/caddy fit more natural in the list.

Signed-off-by: Miek Gieben <miek@miek.nl>

* Fix final import

Signed-off-by: Miek Gieben <miek@miek.nl>
2020-09-24 18:14:41 +02:00
kadern0
e410760a49 plugin/forward: crash if using https (#3817)
Signed-off-by: kadern0 <kaderno@gmail.com>
2020-04-09 11:26:28 -07:00
Miek Gieben
c52a51fac8 parse.HostPortorFile: return error when 0 found (#3742)
* parse.HostPortorFile: return error when 0 found

Return an error when we haven't found any nameservers. This is the
alternative considered in #3735. It's also slighly less code to be
changing.

Replaces: #3741
Closes: #3741 #3735

Signed-off-by: Miek Gieben <miek@miek.nl>

* Add extra test case here as well

Signed-off-by: Miek Gieben <miek@miek.nl>
2020-03-13 14:23:10 +01:00
Christian Tryti
116bda4d27 Add configuration flag to set if RecursionDesired should be set on health checkers in Forward-plugin (#3679)
* Make the RD-flag in health-checks in the Forward-plugin configurable

Introduces a new configuration flag; `health_check_non_recursive`. This
flag makes the health-checker do non-recursive requests when checking
the health of upstream servers.

Signed-off-by: Geir Haugom <ghagit@haugom.org>
Signed-off-by: Christian Tryti <ctryti@gmail.com>

* Changes after feedback from reviewer

* Better tests of health-checks with and without recursion
* Removed the health_check_non_recursive configuration in favor of
extending the existing health_check configuration. Now supports an
optional `no_rec` argument.

Signed-off-by: Christian Tryti <ctryti@gmail.com>

* Add new test that checks setup of health_check.

Signed-off-by: Christian Tryti <ctryti@gmail.com>
2020-03-06 11:52:43 +01:00
Chris O'Haver
22cd28a798 plugins/forward: Add max_concurrent option (#3640)
* count and limit concurrent queries

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* add option

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* return servfail when limit exceeded

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* docs

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* docs

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* docs

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* review feedback

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* move atomic counter to beginning of struct

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* add comment for ErrLimitExceeded

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* rename option to max_concurrent

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* add metric

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* response REFUSED; incl max in error; add more docs

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* avoid err setup race

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>

* respond SERVFAIL; doc memory usage

Signed-off-by: Chris O'Haver <cohaver@infoblox.com>
2020-02-04 13:59:08 +01:00
Yong Tang
f8bba51f84 Update Caddy to 1.0.1, and update import path (#2961)
* Update Caddy to 1.0.1, and update import path

This fix updates caddy to 1.0.1 and also
updates the import path to github.com/caddyserver/caddy

This fix fixes 2959

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>

* Also update plugin.cfg

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>

* Update and bump zplugin.go

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2019-07-03 09:04:47 +08:00
Miek Gieben
1697ab359d Add test for #2003 (#2115)
This adds a test for cleanup in c349446a

Signed-off-by: Miek Gieben <miek@miek.nl>
2018-09-22 13:25:31 +01:00
Miek Gieben
a536833546 plugin/forward: add HealthChecker interface (#1950)
* plugin/forward: add HealthChecker interface

Make the HealthChecker interface and morph the current DNS health
checker into that interface.

Remove all whole bunch of method on Forward that didn't make sense.

This is done in preparation of adding a DoH client to forward - which
requires a completely different healthcheck implementation (and more,
but lets start here)

Signed-off-by: Miek Gieben <miek@miek.nl>

* Use protocol

Signed-off-by: Miek Gieben <miek@miek.nl>

* Dial doesnt need to be method an Forward either

Signed-off-by: Miek Gieben <miek@miek.nl>

* Address comments

Address various comments on the PR.

Signed-off-by: Miek Gieben <miek@miek.nl>
2018-07-09 15:14:55 +01:00
Ruslan Drozhdzh
bc50901234 plugin/forward: add prefer_udp option (#1944)
* plugin/forward: add prefer_udp option

* updated according to code review

 - fixed linter warning
 - removed metric parameter in Proxy.Connect()
2018-07-07 08:14:21 +01:00
Miek Gieben
ce084012df plugin/forward: fix TLS setup (#1714)
* plugin/forward: fix TLS setup

Way smaller PR than #1679. Fixes same thing.

* remove println

* put overwritten test back

* context

* update tests
2018-04-24 18:18:26 +01:00
Miek Gieben
cff0c9fb4c plugin/forward: test TLS setup (#1677) 2018-04-13 17:02:54 +01:00
Miek Gieben
f697b33283 return an error for multiple use of some plugins (#1559)
* plugins: Return error for multiple use of some

Return plugin.ErrOnce when a plugin that doesn't support it, is called
mutliple times.

This now adds it for: cache, dnssec, errors, forward, hosts, nsid.
And changes it slightly in kubernetes, pprof, reload, root.

* more tests
2018-02-28 18:16:05 -08:00
Miek Gieben
5b844b5017 plugin/forward: add it (#1447)
* plugin/forward: add it

This moves coredns/forward into CoreDNS. Fixes as a few bugs, adds a
policy option and more tests to the plugin.

Update the documentation, test IPv6 address and add persistent tests.

* Always use random policy when spraying

* include scrub fix here as well

* use correct var name

* Code review

* go vet

* Move logging to metrcs

* Small readme updates

* Fix readme
2018-02-05 22:00:47 +00:00