Skip to content

fix(networkproxy): translate catch-all host "*" to match-any everywhere#338

Merged
Danny-Wei merged 1 commit into
mainfrom
wildcard-host
Jun 12, 2026
Merged

fix(networkproxy): translate catch-all host "*" to match-any everywhere#338
Danny-Wei merged 1 commit into
mainfrom
wildcard-host

Conversation

@Danny-Wei

@Danny-Wei Danny-Wei commented Jun 12, 2026

Copy link
Copy Markdown
Member

Summary

Fix a bug where egress httpRule hosts ["*"] (catch-all) were translated into literal exact: "*" string matchers instead of Envoy's any: true matcher. This caused catch-all rules to silently match nothing, producing no enforcement or audit records for both plaintext HTTP and TLS traffic.

The defect affected three independent code paths:

  1. TLS SNI matcher (httpRuleToSNIPermissions): emitted requested_server_name: {exact: "*"}, which never matches real SNI values.
  2. HTTP :authority matcher (authorityMatcherForHostPort, portAgnosticHostRules): emitted exact/prefix matchers on "*", which never match real :authority values.
  3. MITM chain rule scoping (filterHTTPRulesForDomains): dropped "*" rules from MITM chains because "*" was not in the MITM domain set, so MITM-terminated TLS traffic produced no audit records.

Fix

  • Add isMatchAllHost() helper to distinguish "*" from suffix wildcards like "*.example.com".
  • Special-case "*" before suffix/exact branches in SNI and authority matcher generation, emitting PermissionRule{Type: "any", Value: true}.
  • Preserve "*" hosts in filterHTTPRulesForDomains so catch-all rules survive onto every MITM chain; downstream matchers correctly render them as match-any.
  • Explicit ports on "*" rules are still enforced via the separate destination_port rule.

Tests

  • TestWildcardHostMatchAll: verifies any: true and no literal exact: "*" for allow/deny defaults and audit variants.
  • TestWildcardHostMatchAllWithPort: verifies port binding via destination_port while authority matches any.
  • TestMITMWildcardHostAudit: verifies MITM chains carry shadow RBAC + access_log for catch-all audit rules.

Also includes a minor gofmt alignment fix in pkg/lsm/bpfenforcer/enforcer.go.

Impact

Restores the intended behavior of defaultAction: allow + qualifiers: [audit] + hosts: ["*"] for domain discovery, and ensures catch-all allow/deny rules correctly match all egress HTTP/HTTPS traffic.

A catch-all host ("*") in an egress httpRule was handled as a literal string
instead of "match any host", so catch-all rules silently matched nothing and
produced no enforcement or audit records. The defect had three independent
locations:

1. SNI matcher (tls_chain): httpRuleToSNIPermissions emitted
   `requested_server_name: {exact: "*"}`. Envoy compares that literally
   against the SNI, which never equals "*", so the shadow_rules produced no
   metadata and the access_log CEL
   (`'shadow_effective_policy_id' in metadata.filter_metadata[...]`) never
   fired for TLS traffic.

2. :authority matcher (http_chain): authorityMatcherForHostPort and
   portAgnosticHostRules emitted exact/prefix string matchers on "*", which
   likewise never match a real :authority, so plaintext HTTP catch-all rules
   produced no audit records either.

3. MITM chain rule scoping (mitm_tls_dns_chain / mitm_tls_ip_chain):
   filterHTTPRulesForDomains did an exact domainSet lookup on each host. The
   literal "*" was never in a MITM chain's domain set, so the whole rule was
   dropped and the MITM HCM emitted no shadow RBAC and no access_log. As a
   result, a domain that is both a MITM target and covered by a "*" rule
   (e.g. httpbin.org) was audited nowhere: the MITM chain steals its TLS
   traffic by SNI, but that chain had no audit rule.

This broke the intended workflow of defaultAction: allow + qualifiers:
[audit] + hosts: ["*"], which is used to discover the set of domains a
legitimate application talks to. The defect is independent of defaultAction
(allow and deny behave identically) and the L7 route virtual_host already
used domains: ["*"] correctly; only RBAC matcher generation and MITM rule
scoping were wrong.

Fix: add isMatchAllHost() and special-case "*" before the suffix-wildcard
(`*.example.com`) and exact-host branches in httpRuleToSNIPermissions,
authorityMatcherForHostPort and portAgnosticHostRules, emitting a match-any
rule (any: true). When an explicit port accompanies "*", the port is still
enforced via the separate destination_port rule. In filterHTTPRulesForDomains
keep a "*" host verbatim so the catch-all rule survives onto every MITM
chain; the reverse pruning (filterHTTPRulesForTLSChain) already keeps "*"
since it matches no MITM target, so the rule also stays on tls_chain/http_chain
for non-MITM domains.

Tests: add TestWildcardHostMatchAll (allow/deny defaults, audit variants),
TestWildcardHostMatchAllWithPort and TestMITMWildcardHostAudit, asserting no
literal exact:"*" matcher is generated, that a match-any rule is present, and
that MITM chains carry shadow RBAC + access_log for catch-all audit rules.
@Danny-Wei Danny-Wei merged commit b5f2efb into main Jun 12, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants