How CubeSandbox Handles Egress Traffic Inspection and Auditing via the Security Proxy
The CubeSandbox security proxy enforces fine-grained egress policies by translating L7 rules into CubeEgress payloads, inspecting outbound traffic via eBPF kernel redirection, and emitting structured audit logs through the admin API for downstream compliance analysis.
The TencentCloud/CubeSandbox repository implements a defense-in-depth security model where the security proxy acts as a gatekeeper for all outbound connections. By combining kernel-level packet inspection with user-space policy enforcement, the system provides comprehensive egress traffic inspection and auditing capabilities that satisfy enterprise compliance requirements.
Policy Translation and Audit Labeling
The inspection pipeline begins in the network-agent, which converts declarative egress rules into concrete CubeEgress policies. Each rule can carry an optional audit label that identifies matched traffic for later analysis.
Defining Egress Rules with Audit Labels
Rule definitions are stored in network-agent/internal/service/types.go, where the EgressRule struct includes an Audit field. This field accepts a string identifier that propagates through the entire enforcement chain.
// network-agent/internal/service/types.go (≈L151)
type EgressRule struct {
Match EgressRuleMatch `json:"match"`
Action EgressRuleAction `json:"action"`
Audit *string `json:"audit,omitempty"` // Audit label for logging
}
Building the Policy Payload
The toEgressInput function in network-agent/internal/service/cubeegress_push.go (≈L116) transforms the high-level configuration into a cubeegress.PolicyInput structure. During this conversion, the optional Audit field is copied into the payload, ensuring the security proxy receives the labeling metadata required for log correlation.
// network-agent/internal/service/cubeegress_push.go (≈L116)
func toEgressInput(cfg *NetworkConfig) *cubeegress.PolicyInput {
// ... match translation ...
if rule.Audit != nil {
input.Audit = *rule.Audit // Copies audit label for later logging
}
return input
}
eBPF-Based Traffic Inspection and Redirection
Rather than copying every packet to userspace, the security proxy leverages eBPF for high-performance filtering. The CubeProxy sidecar installs kernel programs that redirect matching egress flows to a user-space inspection hook, minimizing latency while maintaining deep packet inspection capabilities.
Policy Delivery via the CubeEgress Admin API
Once constructed, policies are pushed to the CubeEgress service through the admin API. The wire format implementation in network-agent/internal/cubeegress/wire.go (≈L188) handles serialization of the audit field into the JSON payload sent to the proxy.
// network-agent/internal/cubeegress/wire.go (≈L188)
if a.Audit != nil {
out["audit"] = *a.Audit // Serializes audit label for proxy consumption
}
The security proxy maintains these rules in eBPF maps, allowing the kernel to match packets against L7 criteria—such as host, path, or SNI—without expensive context switches.
Host Proxy Lifecycle Management
For administrative traffic and policy updates, the system utilizes a host-local proxy. The newHostProxy implementation in network-agent/internal/service/local_service.go (≈L667) manages these listeners, ensuring proper cleanup when sandboxes terminate.
// network-agent/internal/service/local_service.go (≈L667)
proxy, err := newHostProxy(sandboxID, adminPort)
if err != nil {
return err
}
defer proxy.Close() // Ensures audit streams are flushed on exit
Structured Audit Logging and Exposure
When a packet matches an egress policy, the security proxy generates an audit entry containing the rule's audit label, the sandbox ID, and connection metadata. These entries are exposed via the proxy's administration interface for consumption by the cube-lifecycle-manager or external observability pipelines.
Serializing Audit Metadata
The audit trail captures the exact policy that permitted or denied the traffic. The cube-lifecycle-manager interacts with the proxy through cube-lifecycle-manager/internal/proxypush/client.go, pushing lifecycle metadata that includes audit context.
Additionally, the Lua-based registry in CubeProxy/lua/proxy_registry.lua maintains per-sandbox audit state, exposing entries through the admin HTTP server for real-time monitoring.
Consuming Audit Logs
Matched requests produce JSON log entries similar to the following structure:
{
"sandbox_id": "sb-12345",
"policy_id": "egress-allowlist-01",
"audit": "outbound-http-allow",
"host": "api.example.com",
"path": "/v1/data",
"sni": "api.example.com",
"timestamp": "2024-01-15T10:30:00Z"
}
These logs are available through the proxy's /audit endpoint, enabling integration with SIEM systems and compliance dashboards.
Practical Implementation Examples
Creating an egress rule with audit labeling via the Go SDK:
import "github.com/tencentcloud/CubeSandbox/sdk/go"
rule := sdk.EgressRule{
Match: sdk.EgressRuleMatch{
Host: sdk.String("example.com"),
Path: sdk.String("/api/*"),
},
Action: sdk.EgressRuleAction{
Allow: sdk.Bool(true),
Audit: sdk.String("compliance-tier-1"),
},
}
cfg := sdk.CubeNetworkConfig{
Rules: []sdk.EgressRule{rule},
}
Pushing the policy to the CubeEgress service:
// Inside network-agent/internal/service/cubeegress_push.go
in := toEgressInput(cfg) // Builds PolicyInput with Audit field
err := s.egress.PutPolicy(ctx, sandboxIP, in)
if err != nil {
log.Printf("Failed to push egress policy: %v", err)
}
Summary
- Policy Definition: The
network-agentdefines egress rules innetwork-agent/internal/service/types.go(≈L151) with optionalAuditlabels that identify traffic for compliance logging. - Kernel Enforcement: The security proxy uses eBPF redirection to inspect packets in the kernel, matching them against policies stored in BPF maps without copying full payloads to userspace.
- Audit Serialization: The
wire.gofile (≈L188) serializes audit labels into the CubeEgress admin API payloads, ensuring the proxy receives complete metadata. - Log Exposure: Audit entries are stored in
CubeProxy/lua/proxy_registry.luaand exposed via the admin HTTP API, consumed bycube-lifecycle-manager/internal/proxypush/client.gofor observability. - Lifecycle Integration: The
local_service.gohost proxy (≈L667) manages audit stream lifecycle, flushing logs when sandboxes terminate.
Frequently Asked Questions
How does the security proxy handle TLS-encrypted egress traffic?
The proxy inspects TLS metadata—specifically the Server Name Indication (SNI)—during the initial handshake before encryption is established. This allows the eBPF filter and userspace inspection hooks to apply host-based rules without terminating the TLS connection, preserving end-to-end encryption while still capturing the audit-relevant domain information.
What occurs when an egress rule does not specify an audit label?
If the Audit field is nil, the toEgressInput function in cubeegress_push.go omits the audit key from the policy payload. The security proxy will still enforce the allow/deny action, but the corresponding traffic flow will not generate a labeled audit entry in the proxy_registry.lua state, making it harder to correlate with compliance reports.
Can audit logs be exported to external SIEM systems?
Yes. The CubeProxy admin API exposes audit entries via standard HTTP endpoints. The cube-lifecycle-manager uses internal/proxypush/client.go to fetch these logs, which can then be forwarded to external systems through the manager's plugin interface. The JSON format includes standard fields like sandbox_id, audit, and timestamp for easy parsing.
How is the eBPF redirection mechanism configured for egress traffic?
The network-agent configures eBPF programs through the CubeEgress service, which interacts with the kernel via BPFRedirectFlagIngress patterns observed in the local_service.go implementation. When a packet matches a policy, the eBPF map redirects it to a userspace socket where the CubeProxy sidecar performs final inspection and audit logging before allowing the packet to exit the host.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →