Communication Layer (vsock)ΒΆ

OverviewΒΆ

Bunkers uses a layered communication architecture for inter-environment communication between Open World and the hardened Bunker OS.

The design separates concerns into three layers: transport (vsock over virtio), framing and serialization (Protocol Buffers), and the RPC protocol (Turmux). Applications interact through language-native bindings - C/C++, Rust, or Python - rather than dealing with raw sockets.

vsock is the low-level transport. It is a kernel-native socket family (AF_VSOCK) that operates over a virtio device. vsock supports two socket types: SOCK_STREAM (connection-oriented, ordered, reliable delivery) and SOCK_DGRAM (connectionless, datagram-based). Both are isolated by the hypervisor and cannot be routed outside the VM boundary.

Turmux is the reference RPC implementation. It sits on top of vsock framing and provides method routing, service registration, and a synchronous request/response model. All of the language bindings (Python, C/C++, Rust) are wrappers around the same Turmux core, ensuring consistent protocol behaviour regardless of the implementation language.

Virtual Sockets over Virtio (vsockets)ΒΆ

vsock is a Linux socket family (AF_VSOCK) designed for communication between virtual machines and the host in hypervisor environments. It provides a high-level abstraction over the underlying virtio transport.

ArchitectureΒΆ

vsock operates over the virtio-vsock kernel device. According to BCA, Open World runs as a guest VM and Bunker OS acts as the host. However, vsock is flexible: both client and server roles can be deployed on either side, using either SOCK_STREAM or SOCK_DGRAM.

  • SOCK_STREAM: Connection-oriented (like TCP). Establishes a connection, sends/receives an ordered stream of bytes, then closes. Used by Turmux RPC for reliable request/response patterns.

  • SOCK_DGRAM: Connectionless (like UDP). Sends individual datagrams without connection setup. Useful for low-overhead, fire-and-forget patterns or when connection semantics are not needed.

Both Open World and Bunker OS can initiate connections or send datagrams to each other; the architecture does not restrict this flexibility. Higher-level protocol handling (RPC, framing, routing) is introduced in the next section.

Why vsock? Unlike TCP/IP sockets, vsock connections are scoped to the hypervisor and cannot escape to an external network. Unlike Unix domain sockets, they work across VM boundaries without requiring shared filesystems. The virtio transport is accessed directly by the kernel, making per-message overhead comparable to local IPC rather than a full network stack traversal.

Addressing SchemeΒΆ

Every vsock endpoint is identified by a CID (Context ID) and a port number. CIDs uniquely identify virtual machines and are issued by the system; they cannot be forged by guest-side code.

vsock CID AssignmentsΒΆ

CID

Name

Description

0

VMADDR_CID_HYPERVISOR

Reserved for services built into the hypervisor

1

VMADDR_CID_LOCAL

Loopback; used for local communication within the same VM

2

VMADDR_CID_HOST (Bunker OS)

Fixed; the host/trusted side in the reference design

3+

Guest VMs

Assigned dynamically by the hypervisor; Open World typically receives CID 3 in the reference design

SOCK_STREAM: Connection FlowΒΆ

Opening a SOCK_STREAM vsock connection follows the standard POSIX socket API. The guest creates a stream socket with AF_VSOCK, connects to the host CID and port, and the host accepts the connection. From that point on, the connection behaves as an ordered, reliable byte stream β€” conceptually identical to a TCP stream but scoped to the hypervisor.

        sequenceDiagram
    participant ML as Open World App
    participant HV as virtio-vsock (vhost-device-vsock)
    participant LC as Bunker OS (CID 2)

    ML->>HV: socket(AF_VSOCK, SOCK_STREAM, 0)
    ML->>HV: connect(CID=2, port=5555)
    HV->>LC: forward connection request
    LC-->>HV: accept()
    HV-->>ML: connection established

    ML->>HV: send(framed_request)
    HV->>LC: forward bytes
    LC-->>HV: send(framed_response)
    HV-->>ML: recv(response)

    ML->>HV: close()
    HV->>LC: EOF propagated
    

Comparison with Other TransportsΒΆ

Transport

Isolation model

Overhead

Cross-VM reach

Unix Socket (UDS)

File system permissions; no VM boundary enforcement

Minimal

Host only; cannot cross VM boundaries

vsock (virtio)

Hypervisor-enforced; cannot escape hypervisor scope

Low; direct virtio path

VM-to-VM and VM-to-Host; CID-scoped

TCP/IP

Network stack; permeable via routing and firewall bypass

High; full IP/TCP stack traversal

Unrestricted, but requires explicit firewall rules for containment

For development purposes, Turmux also supports Unix domain sockets so that the full RPC stack can be exercised on a standard Linux machine without a hypervisor.

Raw vsock CommunicationΒΆ

vsock provides low-level access when custom protocols or non-standard communication patterns are needed. While higher-level abstractions like Turmux RPC (covered in the next section) handle serialization, routing, and error handling automatically, raw vsock is appropriate in several scenarios:

  • Custom binary protocols optimized for specific use cases (e.g., high-throughput streaming, specialized encoding)

  • Applications already using a different RPC framework (gRPC, Cap’n Proto, etc.)

  • Fire-and-forget or low-overhead messaging patterns (SOCK_DGRAM)

  • Bidirectional communication patterns not naturally expressed as request/response

Direct vsock usage means you manage framing, serialization, connection semantics, and error handling yourself. This adds complexity but offers full control.

SOCK_STREAM Example (Connection-Oriented):

Using SOCK_STREAM from Open World to connect to a service in Bunker OS:

import socket

# Open World application using raw vsock STREAM
sock = socket.socket(socket.AF_VSOCK, socket.SOCK_STREAM)

# Connect to Bunker OS service
# CID=2 (Bunker OS), Port=5000 (custom service)
sock.connect((2, 5000))

# Send custom protocol data
request = b'custom_binary_data'
sock.send(request)

# Receive response
response = sock.recv(4096)
sock.close()

SOCK_DGRAM Example (Connectionless):

Using SOCK_DGRAM for datagram-based communication:

import socket

# Open World sender using vsock DGRAM
sock = socket.socket(socket.AF_VSOCK, socket.SOCK_DGRAM)

# Send a datagram directly to Bunker OS (no connection setup)
# CID=2 (Bunker OS), Port=6000 (datagram service)
message = b'sensor_reading: 42.5'
sock.sendto(message, (2, 6000))

# Optionally receive a response
response, addr = sock.recvfrom(4096)
sock.close()

For most structured inter-domain communication, Turmux RPC (documented in the next section) uses SOCK_STREAM and is recommended. It provides automatic serialization (Protocol Buffers), method routing, service registration, and error propagation, significantly reducing implementation burden while maintaining the security benefits of vsock transport.

All other validation (message framing, size limits, error handling) is the responsibility of the application. When using Turmux RPC, additional protections are applied at the RPC layer; see Reference RPC Implementation: Turmux for details.

Next StepsΒΆ

The vsock layer provides the transport foundation. The higher-level RPC semantics, language bindings, and service development workflow are described in the companion page: