# How CubeSandbox Handles Egress Traffic Inspection and Auditing via the Security Proxy

> Learn how CubeSandbox's security proxy inspects egress traffic using eBPF for fine-grained policy enforcement and provides structured audit logs via the admin API for compliance.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: how-to-guide
- Published: 2026-07-11

---

**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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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.

```go
// 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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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.

```go
// 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`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/cubeegress/wire.go) (≈L188) handles serialization of the audit field into the JSON payload sent to the proxy.

```go
// 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`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/service/local_service.go) (≈L667) manages these listeners, ensuring proper cleanup when sandboxes terminate.

```go
// 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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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:

```json
{
  "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:

```go
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:

```go
// 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-agent` defines egress rules in [`network-agent/internal/service/types.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/service/types.go) (≈L151) with optional `Audit` labels 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.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/wire.go) file (≈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.lua`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeProxy/lua/proxy_registry.lua) and exposed via the admin HTTP API, consumed by [`cube-lifecycle-manager/internal/proxypush/client.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/cube-lifecycle-manager/internal/proxypush/client.go) for observability.
- **Lifecycle Integration**: The [`local_service.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/local_service.go) host 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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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`](https://github.com/TencentCloud/CubeSandbox/blob/main/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.