Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/features/logforwarding/outputs/http-proxy-support.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,57 @@ When a destination is listed in the cluster-wide `NO_PROXY` environment variable

This means setting `proxyURL` on an output is an intentional override that routes traffic through the specified proxy regardless of any cluster-wide proxy exclusions.

== Known Limitation: NO_PROXY Domain Matching Behavior

The Vector log collector uses a Rust library (`no-proxy` crate) to evaluate `NO_PROXY` entries. This library handles plain domain entries differently than Go's `httpproxy` package used by OpenShift and most Kubernetes components:

[cols="1,2,2",options="header"]
|===
| NO_PROXY Entry | Go (OpenShift behavior) | Vector (collector behavior)

| `example.com`
| Matches `example.com` **and all subdomains** (e.g., `sub.example.com`)
| Matches `example.com` **only** (exact match)

| `.example.com`
| Matches subdomains only (e.g., `sub.example.com`), **not** `example.com` itself
| Matches subdomains only (e.g., `sub.example.com`), **not** `example.com` itself

| `10.0.0.1`
| Exact IP match
| Exact IP match

| `10.0.0.0/24`
| CIDR range match
| CIDR range match

| `*`
| Matches all hosts
| Matches all hosts
|===
Comment on lines +172 to +199
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Rust no-proxy crate NO_PROXY domain matching behavior for plain domains

💡 Result:

In the context of Rust crates that implement NO_PROXY parsing (such as the popular no-proxy crate [1] or the NoProxy implementation found in reqwest [2]), the matching behavior for plain domains is designed to be inclusive of subdomains. Specifically, for these implementations: 1. Domain Equivalence: A plain domain (e.g., example.com) and its variant with a leading dot (e.g., .example.com) are treated as equivalent [3][4][2]. 2. Subdomain Matching: Both example.com and .example.com will match the domain itself as well as all of its subdomains (e.g., sub.example.com, a.b.example.com) [3][4][2]. This behavior is consistent with common expectations for NO_PROXY handling in many modern libraries, where the goal is to simplify configuration by ensuring that a single entry covers a domain and its entire hierarchy [3][2]. If you are using a specific crate, you can verify this behavior by checking its documentation for NoProxy::from_string or NoProxy::from_env, which typically outlines these rules explicitly [3][4][2]. For example, the no-proxy crate documentation confirms that it parses and evaluates these configurations to match both the specified domain and its subdomains [1][5].

Citations:


🌐 Web query:

Go httpproxy package NO_PROXY domain matching behavior for plain domains

💡 Result:

In Go's net/http (via the golang.org/x/net/http/httpproxy package), the NO_PROXY environment variable defines a comma-separated list of hosts that should be excluded from proxying [1][2]. The matching behavior for plain domain names is as follows: 1. Domain Matching: A plain domain name (e.g., example.com) matches that specific domain and all of its subdomains [1][3]. For example, example.com will match both example.com and sub.example.com [1][3]. 2. Leading Dot: If a domain name is specified with a leading dot (e.g., .example.com), it matches subdomains only, not the domain itself [1][3]. For example, .example.com matches sub.example.com but does not match example.com [1][3]. 3. Implementation Detail: Internally, the package processes these rules by checking if the request host ends with the specified domain string [1][3]. If a domain is provided without a leading dot, the implementation effectively treats it as a match for the host itself or any host that has the specified domain as a suffix [1][3]. 4. Special Case: A single asterisk (*) in the NO_PROXY list indicates that no proxying should be performed for any request [1][3]. It is important to note that NO_PROXY matching is performed against the host portion of the request URL [1][3]. The package does not perform DNS lookups to resolve hostnames to IP addresses when evaluating these rules [4]. If you need to exclude IP addresses, you should provide them directly or use CIDR notation, which the package also supports [1][5].

Citations:


CRITICAL: The Rust no-proxy crate behavior claim is incorrect.

The comparison table states that Vector (using Rust no-proxy crate) treats plain domains like example.com as exact-match-only, differing from Go's behavior. However, according to the no-proxy crate documentation, example.com and .example.com are treated as equivalent and both match the domain and all subdomains—identical to Go's httpproxy behavior. This means the documented "Known Limitation" does not actually exist.

The incorrect claim undermines the entire section and the workaround guidance (lines 203-220). If Vector and Go handle plain domains identically, the workaround may be unnecessary. Remove or correct this section based on actual library behavior verification.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/features/logforwarding/outputs/http-proxy-support.adoc` around lines 172
- 199, The "Known Limitation: NO_PROXY Domain Matching Behavior" section
incorrectly claims the Rust no-proxy crate treats plain domains (e.g.,
example.com) as exact-match-only; verify the no-proxy crate behavior against its
docs/source and then update or remove this section accordingly: if the crate
treats example.com and .example.com equivalently (matching domain and subdomains
like Go's httpproxy), delete or rewrite the table rows and the workaround text
(the paragraph and lines referenced as the workaround) to reflect parity with
Go's behavior, and remove any admonitions or workaround instructions that assume
differing behavior; keep references to the no-proxy crate and Go's httpproxy in
the explanation so readers know what was verified.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vparfonov if this is correct then that means there is either a documentation error in the crate or an implementation error. Let's figure out which is correct

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upstream no-proxy crate v0.3.6
File: src/lib.rs, line 111 in jdrouet/no-proxy

Self::Plain(source) => source == value

This is exact match only, no subdomain matching.
So "Known Limitation" is correct at the moment


This means that if the cluster-wide proxy configuration sets `noProxy: apps.example.com`, OpenShift components (using Go) will bypass the proxy for both `apps.example.com` and `elasticsearch.apps.example.com`, but the Vector collector will only bypass the proxy for `apps.example.com` exactly — traffic to `elasticsearch.apps.example.com` will still be sent through the proxy.

=== Workaround

To ensure both the domain itself and all its subdomains bypass the proxy in Vector, include both the plain domain and the leading-dot form in your `NO_PROXY` / `noProxy` configuration:

For example, in the cluster-wide proxy configuration:

[source,yaml]
----
apiVersion: config.openshift.io/v1
kind: Proxy
metadata:
name: cluster
spec:
noProxy: "apps.example.com,.apps.example.com"
----

IMPORTANT: Using only `.apps.example.com` (with leading dot) will match subdomains like `elasticsearch.apps.example.com` but will **not** match `apps.example.com` itself. You need both entries for full coverage.

NOTE: This is a known upstream issue in the `no-proxy` Rust crate used by Vector. Once the upstream fix is released and adopted by Vector, plain domain entries will match subdomains as expected.

== Validation

The `proxyURL` field is validated to be a valid URL. An invalid URL will be rejected by the API server:
Expand Down