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
384 changes: 384 additions & 0 deletions docs/ConnectAuthorizationAttachTypes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,384 @@
# CONNECT_AUTHORIZATION Attach Types

## Overview

This document explains the purpose and rationale behind the `BPF_CGROUP_INET4_CONNECT_AUTHORIZATION` and `BPF_CGROUP_INET6_CONNECT_AUTHORIZATION` attach types that were added to eBPF for Windows.

## Background

eBPF for Windows already supports several attach types for socket address operations:

- `BPF_CGROUP_INET4_CONNECT` / `BPF_CGROUP_INET6_CONNECT` - Invoked at the redirect layer for outbound connections
- `BPF_CGROUP_INET4_RECV_ACCEPT` / `BPF_CGROUP_INET6_RECV_ACCEPT` - For incoming connections

However, there was a gap in functionality that required the addition of new attach points.

## Problem Statement

The existing `BPF_CGROUP_INET4_CONNECT` and `BPF_CGROUP_INET6_CONNECT` attach types operate at the **redirect layer** in the Windows Filtering Platform (WFP). This layer occurs **before route selection** in the network stack processing pipeline.

### Limitations of the Redirect Layer

At the redirect layer, certain critical outbound connection properties are not yet available, including:

- **Interface information** - Which network interface will be used for the outbound connection
- **Tunnel type** - Whether the outbound connection will use tunneling protocols
- **Route-dependent metadata** - Information that depends on the selected route

### Use Cases Requiring Route Information

eBPF programs that need to make authorization decisions based on these properties cannot function properly with the existing CONNECT attach types. Examples include:

1. **Interface-based policies** - Allowing or denying outbound connections based on which network interface will be used
2. **Tunnel-aware security** - Different policies for tunneled vs. non-tunneled traffic
3. **Route-dependent access control** - Authorization decisions that depend on the network path

## Solution: CONNECT_AUTHORIZATION Attach Types

The new `BPF_CGROUP_INET4_CONNECT_AUTHORIZATION` and `BPF_CGROUP_INET6_CONNECT_AUTHORIZATION` attach types address this limitation by operating at the **authorization layer** in WFP.

### Key Characteristics

- **Timing**: Invoked **after route selection** but **before outbound connection authorization**
- **Available Information**: Full outbound connection context including interface and tunnel information
- **Purpose**: Authorization decisions based on complete outbound connection metadata
- **Limitation**: **No redirection support** - outbound connections cannot be redirected at this layer since route selection has already occurred

### WFP Layer Mapping

- `BPF_CGROUP_INET4_CONNECT_AUTHORIZATION` → `FWPM_LAYER_ALE_AUTH_CONNECT_V4`
- `BPF_CGROUP_INET6_CONNECT_AUTHORIZATION` → `FWPM_LAYER_ALE_AUTH_CONNECT_V6`

## When to Use Each Attach Type

### Use CONNECT Attach Types When:
- You need to **redirect** outbound connections to different destinations (**redirection is only supported at these layers**)
- You only need basic outbound connection information (source/destination IP/port)
- Interface and route information is not relevant to your use case

### Use CONNECT_AUTHORIZATION Attach Types When:
- You need **interface information** for authorization decisions (via `bpf_sock_addr_get_interface_type()`)
- You need **tunnel type** information (via `bpf_sock_addr_get_tunnel_type()`)
- You need **next-hop interface** details (via `bpf_sock_addr_get_next_hop_interface_luid()`)
- You need **sub-interface** granularity (via `bpf_sock_addr_get_sub_interface_index()`)
- You want to **authorize or deny** outbound connections based on complete network context (**no redirection support**)
- Your policy depends on route-dependent metadata

## Implementation Details

### Program Type
Both CONNECT_AUTHORIZATION attach types use the `BPF_PROG_TYPE_CGROUP_SOCK_ADDR` program type, sharing the same context structure and helper functions as other sock_addr programs.

### Verdict Handling
CONNECT_AUTHORIZATION programs can return:
- `BPF_SOCK_ADDR_VERDICT_PROCEED_HARD` - Allow the outbound connection and skip further authorization checks
- `BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT` - Allow the outbound connection but continue with additional authorization checks
- `BPF_SOCK_ADDR_VERDICT_REJECT` - Deny the outbound connection

#### Verdict Types Explained

**PROCEED_HARD vs PROCEED_SOFT:**
- `PROCEED_HARD` provides an optimization by signaling to the WFP layer that no further authorization checks are needed for this outbound connection, potentially improving performance for trusted outbound connections
- `PROCEED_SOFT` allows the outbound connection but ensures that other WFP filters and authorization mechanisms continue to evaluate the outbound connection normally
- `PROCEED` (standard) behaves the same as `PROCEED_SOFT` - allows the outbound connection with normal authorization flow

**Use Cases:**
- Use `PROCEED_HARD` for outbound connections that have been thoroughly validated and are known to be safe, where bypassing additional checks improves performance
- Use `PROCEED_SOFT` or `PROCEED` for outbound connections that should be allowed but may still need evaluation by other security mechanisms
- Use `REJECT` to block outbound connections that violate security policies

**Important:** Redirect functionality is **not supported** at the CONNECT_AUTHORIZATION layer since route selection has already occurred. Outbound connection redirection can only be performed at the `BPF_CGROUP_INET4_CONNECT` and `BPF_CGROUP_INET6_CONNECT` layers.

### Additional Helper Functions
CONNECT_AUTHORIZATION and AUTH_RECV_ACCEPT attach types provide access to additional network layer properties through specialized helper functions:

#### `bpf_sock_addr_get_interface_type(ctx)`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggestion: a single helper function that returns a versioned struct that holds all the required information; with the provision new fields can be added for a future version.

Returns the network interface type for the connection. Available for CONNECT_AUTHORIZATION and AUTH_RECV_ACCEPT hooks.
- **Returns**: Interface type value, or -1 if not available
- **Use case**: Distinguish between different interface types (e.g., Ethernet, WiFi, VPN)
- **Note**: Interface type values are assigned by IANA as defined in the [Interface Types (ifType) registry](https://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib). Common values include `IF_TYPE_ETHERNET_CSMACD` (6) (ethernetCsmacd), `IF_TYPE_IEEE80211` (71) (ieee80211 for WiFi), `IF_TYPE_TUNNEL` (131) (tunnel), etc. These constants are defined in the Windows SDK header `ipifcons.h`.

#### `bpf_sock_addr_get_tunnel_type(ctx)`
Returns the tunnel type information for the connection. Available for CONNECT_AUTHORIZATION and AUTH_RECV_ACCEPT hooks.
- **Returns**: Tunnel type value, 0 if not a tunnel, or -1 if not available
- **Use case**: Apply different policies for tunneled vs. non-tunneled traffic
- **Note**: Tunnel type values are also assigned by IANA in the same registry. Common values include `3` (gre), `19` (ipsectunnelmode), `5` (l2tp), etc.

#### `bpf_sock_addr_get_next_hop_interface_luid(ctx)`
Returns the next-hop interface LUID for the outbound connection. Available for CONNECT_AUTHORIZATION hooks only.
- **Returns**: Next-hop interface LUID, or -1 if not available
- **Use case**: Route-dependent access control decisions

#### `bpf_sock_addr_get_sub_interface_index(ctx)`
Returns the sub-interface index for the connection. Available for CONNECT_AUTHORIZATION and AUTH_RECV_ACCEPT hooks.
- **Returns**: Sub-interface index, or -1 if not available
- **Use case**: Granular interface-based policies

### Selective Program Invocation
The implementation includes a filtering mechanism to ensure that:
- CONNECT_AUTHORIZATION programs are only invoked for CONNECT_AUTHORIZATION attach points
- CONNECT programs are only invoked for CONNECT attach points

This prevents cross-invocation and ensures programs run at the appropriate layer.

## Program Interaction: CONNECT and CONNECT_AUTHORIZATION Together

When both CONNECT and CONNECT_AUTHORIZATION programs are attached to the same cgroup, they operate in a coordinated sequence that provides comprehensive outbound connection control:

### Execution Order
1. **CONNECT Layer** (`BPF_CGROUP_INET4_CONNECT`/`BPF_CGROUP_INET6_CONNECT`)
- Executes first at the **redirect layer** (before route selection)
- Can **redirect** outbound connections to different destinations
- Has access to basic outbound connection information (source/dest IP/port)
- Produces a verdict that affects subsequent processing

2. **CONNECT_AUTHORIZATION Layer** (`BPF_CGROUP_INET4_CONNECT_AUTHORIZATION`/`BPF_CGROUP_INET6_CONNECT_AUTHORIZATION`)
- Executes second at the **authorization layer** (after route selection)
- **Cannot redirect** outbound connections (route already selected)
- Has access to enhanced network context (interface type, tunnel info, routing details)
- Makes final authorization decision

### Verdict Flow and Interaction

The verdict from the CONNECT layer determines whether CONNECT_AUTHORIZATION programs are invoked:

- **`BPF_SOCK_ADDR_VERDICT_REJECT`** from CONNECT → Outbound connection blocked, CONNECT_AUTHORIZATION programs **not invoked**
- **`BPF_SOCK_ADDR_VERDICT_PROCEED_HARD`** from CONNECT → Outbound connection authorized, CONNECT_AUTHORIZATION programs **not invoked** (optimization)
- **`BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT`** from CONNECT → CONNECT_AUTHORIZATION programs **are invoked** for additional authorization

### Use Case: Layered Security Policy

```c
// CONNECT layer program - handles redirection and basic filtering.
SEC("cgroup/connect4")
int redirect_and_basic_filter(struct bpf_sock_addr *ctx)
Copy link
Collaborator

Choose a reason for hiding this comment

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

bpf_sock_addr is writable for linux INET_CONNECT attach types. In the new attach type they are effectively not. Should the extension reject the verdict of a program at this attach layer that changed the sock_addr context by modifying the source or destiantion IP/port?

{
// Block known malicious destinations immediately.
if (is_blacklisted_destination(ctx->user_ip4)) {
return BPF_SOCK_ADDR_VERDICT_REJECT; // CONNECT_AUTHORIZATION will NOT run.
}

// Redirect to local proxy for inspection.
if (needs_proxy_inspection(ctx->user_ip4)) {
ctx->user_ip4 = PROXY_SERVER_IP;
ctx->user_port = PROXY_SERVER_PORT;
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT; // CONNECT_AUTHORIZATION WILL run.
}

// High-trust destinations can skip additional authorization.
if (is_highly_trusted_destination(ctx->user_ip4)) {
return BPF_SOCK_ADDR_VERDICT_PROCEED_HARD; // CONNECT_AUTHORIZATION will NOT run.
}

// Default: allow but require additional authorization.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT; // CONNECT_AUTHORIZATION WILL run.
}

// CONNECT_AUTHORIZATION layer program - handles interface-aware authorization.
SEC("cgroup/connect_authorization4")
int interface_aware_authorization(struct bpf_sock_addr *ctx)
{
// This program only runs for PROCEED_SOFT verdicts from CONNECT layer.

uint32_t interface_type = bpf_sock_addr_get_interface_type(ctx);
uint32_t tunnel_type = bpf_sock_addr_get_tunnel_type(ctx);

// Block outbound connections on public WiFi to sensitive destinations.
if (interface_type == IF_TYPE_IEEE80211 && is_sensitive_destination(ctx->user_ip4)) { // ieee80211.
return BPF_SOCK_ADDR_VERDICT_REJECT;
}

// Require VPN for external outbound connections.
if (!is_internal_network(ctx->user_ip4) && tunnel_type == 0) {
return BPF_SOCK_ADDR_VERDICT_REJECT;
}

return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}
```

### Benefits of Layered Approach

1. **Performance Optimization**: PROCEED_HARD verdicts skip unnecessary CONNECT_AUTHORIZATION processing for trusted outbound connections
2. **Comprehensive Control**: CONNECT handles redirection + basic filtering, CONNECT_AUTHORIZATION adds interface-aware policies
3. **Separation of Concerns**: Network topology changes (CONNECT) vs. authorization policies (CONNECT_AUTHORIZATION)
4. **Flexibility**: Each layer can be independently updated without affecting the other

### Important Considerations

- **Redirection must happen at CONNECT layer**: Once CONNECT_AUTHORIZATION runs, route selection is complete
- **Context preservation**: Outbound connection context from CONNECT layer is available to CONNECT_AUTHORIZATION programs
- **Verdict precedence**: REJECT verdicts are final; PROCEED_HARD optimizes by skipping CONNECT_AUTHORIZATION
- **Error handling**: Failures in either layer result in outbound connection blocking for security

## Example Scenarios

### Scenario 1: Interface-Based Access Control
```c
SEC("cgroup/connect_authorization4")
int connect_authorization_interface_policy(struct bpf_sock_addr *ctx)
{
// Get interface type using helper function.
uint32_t interface_type = bpf_sock_addr_get_interface_type(ctx);

// Apply interface-specific policy with appropriate verdict types.
if (interface_type == IF_TYPE_TUNNEL) { // tunnel(131) - VPN/tunnel interfaces.
// VPN connections are highly trusted - skip additional authorization.
return BPF_SOCK_ADDR_VERDICT_PROCEED_HARD;
} else if (interface_type == IF_TYPE_IEEE80211) { // ieee80211(71) - WiFi interfaces.
// Block outbound connections on public WiFi for sensitive applications.
return BPF_SOCK_ADDR_VERDICT_REJECT;
} else if (interface_type == IF_TYPE_ETHERNET_CSMACD) { // ethernetCsmacd(6) - Ethernet interfaces.
// Corporate wired network - allow but continue with normal authorization flow.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}

// Default: allow with normal authorization checks.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}
```

### Scenario 2: Tunnel-Aware Security
```c
SEC("cgroup/connect_authorization4")
int connect_authorization_tunnel_policy(struct bpf_sock_addr *ctx)
{
// Check if outbound connection will use tunneling.
uint32_t tunnel_type = bpf_sock_addr_get_tunnel_type(ctx);

if (tunnel_type != 0) {
// This is a tunneled outbound connection.
// Apply tunnel-specific security policy.
if (tunnel_type == 19) { // ipsectunnelmode(19) - IPSec tunnel mode.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
} else if (tunnel_type == 3) { // gre(3) - GRE encapsulation.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
} else {
// Unknown or unsupported tunnel type.
return BPF_SOCK_ADDR_VERDICT_REJECT;
}
}

return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}
```

### Scenario 3: Route-Dependent Authorization
```c
SEC("cgroup/connect_authorization4")
int connect_authorization_route_policy(struct bpf_sock_addr *ctx)
{
// Get next-hop interface information.
uint64_t next_hop_interface = bpf_sock_addr_get_next_hop_interface_luid(ctx);

if (next_hop_interface != 0) {
// Check if the next-hop interface is approved for this type of traffic.
if (!is_approved_interface(next_hop_interface)) {
return BPF_SOCK_ADDR_VERDICT_REJECT;
}
}

// Get sub-interface details for fine-grained control.
uint32_t sub_interface = bpf_sock_addr_get_sub_interface_index(ctx);
if (sub_interface != 0 && is_restricted_sub_interface(sub_interface)) {
return BPF_SOCK_ADDR_VERDICT_REJECT;
}

return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}
```

### Scenario 4: Verdict Type Demonstration
```c
SEC("cgroup/connect_authorization4")
int connect_authorization_verdict_demo(struct bpf_sock_addr *ctx)
{
uint32_t dest_ip = ctx->user_ip4;
uint32_t interface_type = bpf_sock_addr_get_interface_type(ctx);
uint32_t tunnel_type = bpf_sock_addr_get_tunnel_type(ctx);

// Trusted internal network with VPN - maximum trust.
if (is_internal_network(dest_ip) && tunnel_type == 19) { // ipsectunnelmode(19).
// Skip all further authorization checks for performance.
return BPF_SOCK_ADDR_VERDICT_PROCEED_HARD;
}

// Known malicious destination - immediate block.
if (is_blacklisted_destination(dest_ip)) {
return BPF_SOCK_ADDR_VERDICT_REJECT;
}

// Corporate wired network - allow but let other filters validate.
if (interface_type == IF_TYPE_ETHERNET_CSMACD) { // ethernetCsmacd(6) - Ethernet.
// Continue with normal authorization flow.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}

// External destinations on public WiFi networks - proceed with caution.
if (interface_type == IF_TYPE_IEEE80211) { // ieee80211(71) - WiFi.
// Allow but ensure other security mechanisms evaluate this.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}

// Default case - standard proceed.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}
```

### Scenario 5: Combined Network Context Analysis
```c
SEC("cgroup/connect_authorization4")
int connect_authorization_comprehensive_policy(struct bpf_sock_addr *ctx)
{
// Gather all available network context.
uint32_t interface_type = bpf_sock_addr_get_interface_type(ctx);
uint32_t tunnel_type = bpf_sock_addr_get_tunnel_type(ctx);
uint64_t next_hop_interface = bpf_sock_addr_get_next_hop_interface_luid(ctx);
uint32_t sub_interface = bpf_sock_addr_get_sub_interface_index(ctx);

// Create a comprehensive security decision based on all available context.
if (interface_type == IF_TYPE_AAL2 && tunnel_type == 0) { // aal2(187) - cellular without tunnel.
// On cellular without tunnel - apply data usage restrictions.
if (is_high_bandwidth_destination(ctx->user_ip4)) {
return BPF_SOCK_ADDR_VERDICT_REJECT;
}
// Allow low-bandwidth destinations but continue with authorization checks.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}

if (tunnel_type != 0 && next_hop_interface != 0) {
// Tunneled traffic with specific next-hop - enhanced validation.
if (!validate_tunnel_route(tunnel_type, next_hop_interface)) {
return BPF_SOCK_ADDR_VERDICT_REJECT;
}
// Validated tunnel outbound connections can skip additional checks.
return BPF_SOCK_ADDR_VERDICT_PROCEED_HARD;
}

// Default: allow with normal authorization flow.
return BPF_SOCK_ADDR_VERDICT_PROCEED_SOFT;
}
```

## Migration Considerations

### Existing Programs
Existing programs using `BPF_CGROUP_INET4_CONNECT` and `BPF_CGROUP_INET6_CONNECT` will continue to work unchanged. The new CONNECT_AUTHORIZATION attach types are additional, not replacements.

### Choosing the Right Attach Type
When developing new programs, consider:

1. **Do you need to redirect outbound connections?** → Use CONNECT attach types
2. **Do you need enhanced network context (interface type, tunnel info, routing details)?** → Use CONNECT_AUTHORIZATION attach types with the new helper functions
3. **Do you only need basic outbound connection info for authorization?** → Either type works, but CONNECT_AUTHORIZATION provides significantly more context

### Backward Compatibility
The new helper functions are designed to be backward compatible:
- They return -1 when information is not available (e.g., on CONNECT_REDIRECT layers)
- Existing programs that don't use these helpers continue to function normally
- The `bpf_sock_addr_t` context structure remains unchanged to maintain ABI compatibility

## See Also

- [eBPF Extensions Documentation](eBpfExtensions.md)
- [Windows Filtering Platform (WFP) Layer Reference](https://docs.microsoft.com/en-us/windows-hardware/drivers/network/filtering-layer-identifiers)
Loading