[Bug Report] CubeEgress domain allow rules do not bind Host/SNI to the original destination

Author: UgOrangeCreated Sep 10, 2026Updated Sep 16, 2026
Labelsbugarea/CubeNetneeds-triagebug-report-need-input

Summary

For requests that reach CubeEgress's L7 proxy, a matching Host/SNI does not establish that the original destination IP belongs to that name. Client-side hosts or curl --resolve overrides can preserve the allowed name while changing the destination. I am opening this issue to discuss the intended authorization boundary and agree on an approach before proceeding with #1695, as requested in the PR review.

Environment

  • Baseline: CubeSandbox commit 62da0187 (v0.7.1-rc1).
  • Relevant components: CubeEgress access policy/proxy routing; CubeVS determines which flows reach L7.
  • Reproduction: isolated Docker socket fixture on LinuxKit 6.12.76, OpenResty 1.31.1.1, real DNS and HTTP/TLS backends.
  • KVM/deployment mode: not used; this is not a deployed sandbox test. The patched production OpenResty 1.29.2.5 image and the complete guest/TPROXY/eBPF path have not been runtime-verified here.

Steps to Reproduce

  1. In an isolated fixture, configure an allow rule for *.example.test; proxy-side DNS resolves allowed.example.test only to 127.0.0.2. Run a second backend at 127.0.0.3.
  2. Keep Host/SNI as allowed.example.test, but connect to 127.0.0.3 using a client-container hosts entry or these commands inside the fixture network:
bash
curl --noproxy '*' --resolve allowed.example.test:80:127.0.0.3 http://allowed.example.test/
curl --noproxy '*' --cacert /fixture/cert.pem --resolve allowed.example.test:443:127.0.0.3 https://allowed.example.test/

For the HTTPS case, the unrelated backend deliberately presents a certificate valid for the allowed name and trusted by the test proxy. This demonstrates the DNS-binding gap even when upstream certificate verification succeeds; an arbitrary backend without a valid certificate is not claimed to pass HTTPS verification.

  1. Separately, use an HTTPS Host-only allow rule with Host: allowed.example.test, SNI blocked.example.test, and a shared destination IP. The policy matches the first name, while nginx uses SNI for upstream TLS and rewrites upstream Host to the second name.

The reproducible harness is in #1695: python3 CubeEgress/tests/dns_auth_integration.py --baseline-ref 62da0187. It retains production access/audit modules and proxy locations but substitutes policy storage, static certificates, direct listeners, and backend ports.

Expected Behavior

A domain-constrained allow should authorize the identity actually used upstream, with an explicit policy for how that identity is bound to the original destination. An unrelated destination or unauthorized Host/SNI identity change should be denied before forwarding or credential injection.

Actual Behavior

The baseline returned 200 for all four HTTP/HTTPS × hosts/--resolve cases. The Host-only HTTPS identity mismatch also returned 200. The proposed implementation in #1695 returns 403 for these cases while normal requests return 200. This evidence applies to the socket fixture, not arbitrary IP reachability through CubeVS. Flows rejected before L7 remain rejected; ordinary SNAT flows are outside this check.

Additional Context: Design Discussion

The current proposal preserves the original IP/port and checks membership against trusted proxy-side DNS, with asynchronous resolution, bounded concurrency/deadlines, validated CNAME ownership and TTL-respecting caching. HTTPS Host constraints must agree with the SNI used upstream.

Points to agree on:

  • Is proxy-side DNS membership the desired authorization contract? CDN, split-DNS and rotation can give guest and proxy different valid address sets and cause false denials.
  • Should the binding instead use trusted DNS results already observed by CubeVS? This would require defining provenance, expiration and access from CubeEgress.
  • If the proxy selects a new resolved IP, the new destination must undergo L4/CIDR authorization again; silently replacing the original IP would bypass that boundary.
  • Should HTTPS Host/SNI disagreement be rejected for all Host-constrained allow rules, including rules without credential injection?

DNS membership alone does not prove tenant ownership on shared hosting or restrict an attacker-controlled subdomain already covered by an allowed wildcard. TLS verification and destination restrictions remain necessary. #1695 is a concrete implementation for discussion, not an assumption that these semantics have already been agreed.

Source: TencentCloud/CubeSandbox