Understanding the Two OpenFlux Endpoint Roles: Tunnel Link vs. Raw Socket

OpenFlux implements two distinct link-endpoint roles—the Tunnel Link Endpoint and the Raw Socket Endpoint—that serve as the bridge between the gVisor virtual network stack and the host's underlying transport mechanisms.

OpenFlux is an open-source user-space VPN framework that leverages gVisor's network stack to create isolated virtual network interfaces. Understanding the two OpenFlux endpoint roles is critical for developers building cross-platform tunneling solutions, as these components separate virtual network abstraction from raw packet I/O operations.

The Tunnel Link Endpoint acts as the virtual network interface for the gVisor stack, receiving packets injected from the tunnel ("inbound") and forwarding outbound packets to the transport layer. This role is implemented in [tunnel/endpoint.go](https://github.com/p1neappleXpress/OpenFlux/blob/main/tunnel/endpoint.go) and serves as the primary interface that the VPN client interacts with.

According to the OpenFlux source code, this endpoint implements the stack.LinkEndpoint interface from gVisor. Key methods include:

  • InjectInbound: Injects incoming packets from the tunnel into the gVisor network stack.
  • WritePackets: Called by the gVisor stack to emit outbound packets, which are then handed over to a configurable onOutgoingPacket callback.

The endpoint creation and callback configuration follows this pattern:

// Creating the virtual tunnel endpoint
tunnelEP := tunnel.NewTunnelLinkEndpoint()

// Hook to forward outbound packets to the raw-socket transport
tunnelEP.onOutgoingPacket = func(pkt []byte) {
    // … send pkt via RawSocketEndpoint …
}

Raw Socket Endpoint: The Physical Transport Layer

The Raw Socket Endpoint provides low-level raw-socket transport that reads and writes raw IP packets directly on the host's network interface. This endpoint handles the actual transmission of packets over the physical network, bypassing higher-level networking APIs to operate as a true user-space VPN.

OpenFlux implements this role across multiple platforms:

Like the Tunnel Link Endpoint, the Raw Socket Endpoint implements stack.LinkEndpoint. It reads raw IP packets from the host interface and forwards them into the gVisor stack, while sending packets produced by the stack out through the raw socket.

How the Endpoint Roles Interact

Together, these two endpoints enable OpenFlux to function as a user-space VPN. The TunnelLinkEndpoint provides the virtual interface that the VPN application sees, while the RawSocketEndpoint manages the physical network transmission.

The connection between them is established through attachment:

// Raw-socket endpoint (Linux example)
rawEP := tunnel.NewRawSocketEndpoint()
rawEP.Attach(tunnelEP) // Connect raw socket to the virtual tunnel

This architecture separates concerns: the virtual endpoint handles gVisor stack integration and packet queuing, while the raw socket endpoint manages platform-specific kernel bypass and network interface access.

Platform-Specific Implementation Details

While the Tunnel Link Endpoint remains platform-agnostic in tunnel/endpoint.go, the Raw Socket Endpoint requires operating-system-specific implementations to handle raw socket creation and packet framing. Each platform-specific file implements the same stack.LinkEndpoint interface but uses native system calls for socket creation, binding, and raw packet I/O operations.

Summary

  • Tunnel Link Endpoint: The virtual network interface in tunnel/endpoint.go that bridges the gVisor stack with the VPN application, handling inbound injection via InjectInbound and outbound routing via WritePackets callbacks.
  • Raw Socket Endpoint: The physical transport layer implemented in platform-specific files (rawsocket_linux.go, rawsocket_windows.go, rawsocket_darwin.go) that performs raw IP packet I/O directly on host network interfaces.
  • Integration: Both endpoints implement stack.LinkEndpoint and work together to create a complete user-space VPN solution, with the Tunnel Link handling virtual abstraction and the Raw Socket managing physical transmission.

Frequently Asked Questions

What are the two endpoint roles in OpenFlux?

OpenFlux defines two link-endpoint roles: the Tunnel Link Endpoint, which serves as the virtual network interface for the gVisor stack, and the Raw Socket Endpoint, which handles low-level raw IP packet transmission on the host's physical network interface. Together, these roles separate virtual network abstraction from physical transport operations.

According to the source code in tunnel/endpoint.go, the Tunnel Link Endpoint uses an onOutgoingPacket callback function configured during initialization. When the gVisor stack calls WritePackets to emit outbound traffic, the endpoint invokes this callback to hand packets over to the Raw Socket Endpoint for physical transmission.

Which source files contain the Raw Socket Endpoint implementations?

The Raw Socket Endpoint implementations are platform-specific and located in three separate files: tunnel/rawsocket_linux.go for Linux systems, tunnel/rawsocket_windows.go for Windows, and tunnel/rawsocket_darwin.go for macOS. Each file contains OS-specific logic for creating raw sockets and performing packet I/O.

Do both OpenFlux endpoint roles implement the same gVisor interface?

Yes, both the Tunnel Link Endpoint and the Raw Socket Endpoint implement the stack.LinkEndpoint interface from the gVisor network stack. This shared implementation pattern allows the virtual and physical transport layers to communicate seamlessly while maintaining distinct responsibilities for packet handling and network I/O.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →