Gate VPN fabric session transport config

This commit is contained in:
2026-05-16 00:56:11 +03:00
parent 9cd0cb5ea9
commit e16f456fe8
11 changed files with 189 additions and 149 deletions
@@ -1115,6 +1115,7 @@ func meshListenerConfigKey(cfg config.Config) string {
strings.TrimSpace(cfg.MeshNATType), strings.TrimSpace(cfg.MeshNATType),
strings.TrimSpace(cfg.MeshRegion), strings.TrimSpace(cfg.MeshRegion),
fmt.Sprintf("%t", cfg.MeshProductionForwardingEnabled), fmt.Sprintf("%t", cfg.MeshProductionForwardingEnabled),
fmt.Sprintf("%t", cfg.VPNFabricSessionTransportEnabled),
}, "|") }, "|")
} }
@@ -2480,6 +2481,18 @@ func heartbeatPayload(cfg config.Config, identity state.Identity, meshState *syn
payload.Capabilities["fabric_session_websocket_endpoint"] = true payload.Capabilities["fabric_session_websocket_endpoint"] = true
payload.Capabilities["fabric_data_session_v1"] = true payload.Capabilities["fabric_data_session_v1"] = true
} }
if cfg.VPNFabricSessionTransportEnabled {
payload.Metadata["vpn_fabric_session_transport_report"] = map[string]any{
"schema_version": "rap.vpn_fabric_session_transport_report.v1",
"enabled": true,
"transport": "fabric_session_websocket_binary_frames",
"packet_payload": "rap.vpn_packet_batch.fabric.v1",
"gated": true,
"observed_at": observedAt.UTC().Format(time.RFC3339Nano),
}
payload.Capabilities["vpn_fabric_session_transport"] = true
payload.Capabilities["vpn_packet_batch_binary_frames"] = true
}
if meshState != nil && meshState.ConfigLoadError != "" { if meshState != nil && meshState.ConfigLoadError != "" {
payload.HealthStatus = "warning" payload.HealthStatus = "warning"
} }
@@ -3724,6 +3737,7 @@ func advertisedEndpointCandidates(cfg config.Config, identity state.Identity, me
"runtime": "c17z7", "runtime": "c17z7",
"synthetic_runtime": cfg.MeshSyntheticRuntimeEnabled, "synthetic_runtime": cfg.MeshSyntheticRuntimeEnabled,
"production_forwarding": cfg.MeshProductionForwardingEnabled, "production_forwarding": cfg.MeshProductionForwardingEnabled,
"vpn_fabric_session": cfg.VPNFabricSessionTransportEnabled,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@@ -635,6 +635,7 @@ func TestHeartbeatPayloadIncludesMeshEndpointReport(t *testing.T) {
MeshSyntheticRuntimeEnabled: true, MeshSyntheticRuntimeEnabled: true,
MeshProductionForwardingEnabled: true, MeshProductionForwardingEnabled: true,
MeshFabricSessionEnabled: true, MeshFabricSessionEnabled: true,
VPNFabricSessionTransportEnabled: true,
}, state.Identity{ }, state.Identity{
ClusterID: "cluster-1", ClusterID: "cluster-1",
NodeID: "node-a", NodeID: "node-a",
@@ -659,6 +660,12 @@ func TestHeartbeatPayloadIncludesMeshEndpointReport(t *testing.T) {
if report, ok := payload.Metadata["fabric_session_endpoint_report"].(map[string]any); !ok || report["path"] != "/mesh/v1/fabric/session/ws" { if report, ok := payload.Metadata["fabric_session_endpoint_report"].(map[string]any); !ok || report["path"] != "/mesh/v1/fabric/session/ws" {
t.Fatalf("fabric session endpoint report missing: %+v", payload.Metadata) t.Fatalf("fabric session endpoint report missing: %+v", payload.Metadata)
} }
if payload.Capabilities["vpn_fabric_session_transport"] != true || payload.Capabilities["vpn_packet_batch_binary_frames"] != true {
t.Fatalf("vpn fabric session capabilities missing: %+v", payload.Capabilities)
}
if report, ok := payload.Metadata["vpn_fabric_session_transport_report"].(map[string]any); !ok || report["packet_payload"] != "rap.vpn_packet_batch.fabric.v1" {
t.Fatalf("vpn fabric session report missing: %+v", payload.Metadata)
}
} }
func TestHeartbeatPayloadReportsMeshListenerFailureWithoutKillingHeartbeat(t *testing.T) { func TestHeartbeatPayloadReportsMeshListenerFailureWithoutKillingHeartbeat(t *testing.T) {
@@ -27,6 +27,7 @@ type Config struct {
MeshSyntheticRuntimeEnabled bool MeshSyntheticRuntimeEnabled bool
MeshProductionForwardingEnabled bool MeshProductionForwardingEnabled bool
MeshFabricSessionEnabled bool MeshFabricSessionEnabled bool
VPNFabricSessionTransportEnabled bool
MeshProductionObservationSinkCapacity int MeshProductionObservationSinkCapacity int
MeshListenAddr string MeshListenAddr string
MeshListenPortMode string MeshListenPortMode string
@@ -65,6 +66,7 @@ func Load(args []string, env map[string]string) (Config, error) {
fs.BoolVar(&cfg.MeshSyntheticRuntimeEnabled, "mesh-synthetic-runtime-enabled", getEnvBool(env, "RAP_MESH_SYNTHETIC_RUNTIME_ENABLED", false), "Enable C17A synthetic fabric probe runtime. Disabled by default.") fs.BoolVar(&cfg.MeshSyntheticRuntimeEnabled, "mesh-synthetic-runtime-enabled", getEnvBool(env, "RAP_MESH_SYNTHETIC_RUNTIME_ENABLED", false), "Enable C17A synthetic fabric probe runtime. Disabled by default.")
fs.BoolVar(&cfg.MeshProductionForwardingEnabled, "mesh-production-forwarding-enabled", getEnvBool(env, "RAP_MESH_PRODUCTION_FORWARDING_ENABLED", false), "Enable production fabric-control direct next-hop forwarding gate. Disabled by default.") fs.BoolVar(&cfg.MeshProductionForwardingEnabled, "mesh-production-forwarding-enabled", getEnvBool(env, "RAP_MESH_PRODUCTION_FORWARDING_ENABLED", false), "Enable production fabric-control direct next-hop forwarding gate. Disabled by default.")
fs.BoolVar(&cfg.MeshFabricSessionEnabled, "mesh-fabric-session-enabled", getEnvBool(env, "RAP_MESH_FABRIC_SESSION_ENABLED", false), "Enable authenticated fabric session WebSocket endpoint. Disabled by default.") fs.BoolVar(&cfg.MeshFabricSessionEnabled, "mesh-fabric-session-enabled", getEnvBool(env, "RAP_MESH_FABRIC_SESSION_ENABLED", false), "Enable authenticated fabric session WebSocket endpoint. Disabled by default.")
fs.BoolVar(&cfg.VPNFabricSessionTransportEnabled, "vpn-fabric-session-transport-enabled", getEnvBool(env, "RAP_VPN_FABRIC_SESSION_TRANSPORT_ENABLED", false), "Route VPN packet transport over persistent fabric session when explicitly enabled. Disabled by default.")
fs.IntVar(&cfg.MeshProductionObservationSinkCapacity, "mesh-production-observation-sink-capacity", getEnvSignedInt(env, "RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY", 0), "Bounded local metadata-only production envelope observation sink capacity. Disabled when 0.") fs.IntVar(&cfg.MeshProductionObservationSinkCapacity, "mesh-production-observation-sink-capacity", getEnvSignedInt(env, "RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY", 0), "Bounded local metadata-only production envelope observation sink capacity. Disabled when 0.")
fs.StringVar(&cfg.MeshListenAddr, "mesh-listen-addr", getEnv(env, "RAP_MESH_LISTEN_ADDR", ""), "Listen address for disabled-by-default C17E synthetic mesh HTTP endpoint.") fs.StringVar(&cfg.MeshListenAddr, "mesh-listen-addr", getEnv(env, "RAP_MESH_LISTEN_ADDR", ""), "Listen address for disabled-by-default C17E synthetic mesh HTTP endpoint.")
fs.StringVar(&cfg.MeshListenPortMode, "mesh-listen-port-mode", getEnv(env, "RAP_MESH_LISTEN_PORT_MODE", "manual"), "Mesh listen port behavior: manual, auto, or disabled.") fs.StringVar(&cfg.MeshListenPortMode, "mesh-listen-port-mode", getEnv(env, "RAP_MESH_LISTEN_PORT_MODE", "manual"), "Mesh listen port behavior: manual, auto, or disabled.")
@@ -21,6 +21,7 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
"RAP_MESH_SYNTHETIC_RUNTIME_ENABLED": "true", "RAP_MESH_SYNTHETIC_RUNTIME_ENABLED": "true",
"RAP_MESH_PRODUCTION_FORWARDING_ENABLED": "true", "RAP_MESH_PRODUCTION_FORWARDING_ENABLED": "true",
"RAP_MESH_FABRIC_SESSION_ENABLED": "true", "RAP_MESH_FABRIC_SESSION_ENABLED": "true",
"RAP_VPN_FABRIC_SESSION_TRANSPORT_ENABLED": "true",
"RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY": "5", "RAP_MESH_PRODUCTION_OBSERVATION_SINK_CAPACITY": "5",
"RAP_MESH_LISTEN_ADDR": "127.0.0.1:19001", "RAP_MESH_LISTEN_ADDR": "127.0.0.1:19001",
"RAP_MESH_LISTEN_PORT_MODE": "auto", "RAP_MESH_LISTEN_PORT_MODE": "auto",
@@ -70,6 +71,9 @@ func TestLoadConfigFromEnvAndArgs(t *testing.T) {
if !cfg.MeshFabricSessionEnabled { if !cfg.MeshFabricSessionEnabled {
t.Fatal("MeshFabricSessionEnabled = false, want true") t.Fatal("MeshFabricSessionEnabled = false, want true")
} }
if !cfg.VPNFabricSessionTransportEnabled {
t.Fatal("VPNFabricSessionTransportEnabled = false, want true")
}
if cfg.MeshProductionObservationSinkCapacity != 5 { if cfg.MeshProductionObservationSinkCapacity != 5 {
t.Fatalf("MeshProductionObservationSinkCapacity = %d, want 5", cfg.MeshProductionObservationSinkCapacity) t.Fatalf("MeshProductionObservationSinkCapacity = %d, want 5", cfg.MeshProductionObservationSinkCapacity)
} }
@@ -30,6 +30,7 @@ type RuntimeConfig struct {
MeshSyntheticRuntimeEnabled bool MeshSyntheticRuntimeEnabled bool
MeshProductionForwardingEnabled bool MeshProductionForwardingEnabled bool
MeshFabricSessionEnabled bool MeshFabricSessionEnabled bool
VPNFabricSessionTransportEnabled bool
MeshListenAddr string MeshListenAddr string
MeshListenPortMode string MeshListenPortMode string
MeshListenAutoPortStart int MeshListenAutoPortStart int
@@ -265,6 +265,7 @@ func NodeAgentEnvWithStateDir(cfg RuntimeConfig, stateDir string) []string {
"RAP_MESH_SYNTHETIC_RUNTIME_ENABLED=" + boolString(cfg.MeshSyntheticRuntimeEnabled), "RAP_MESH_SYNTHETIC_RUNTIME_ENABLED=" + boolString(cfg.MeshSyntheticRuntimeEnabled),
"RAP_MESH_PRODUCTION_FORWARDING_ENABLED=" + boolString(cfg.MeshProductionForwardingEnabled), "RAP_MESH_PRODUCTION_FORWARDING_ENABLED=" + boolString(cfg.MeshProductionForwardingEnabled),
"RAP_MESH_FABRIC_SESSION_ENABLED=" + boolString(cfg.MeshFabricSessionEnabled), "RAP_MESH_FABRIC_SESSION_ENABLED=" + boolString(cfg.MeshFabricSessionEnabled),
"RAP_VPN_FABRIC_SESSION_TRANSPORT_ENABLED=" + boolString(cfg.VPNFabricSessionTransportEnabled),
} }
if cfg.JoinToken != "" { if cfg.JoinToken != "" {
env = append(env, "RAP_JOIN_TOKEN="+cfg.JoinToken) env = append(env, "RAP_JOIN_TOKEN="+cfg.JoinToken)
@@ -73,6 +73,7 @@ func LinuxInstallConfigFromProfile(profile LinuxInstallProfile) LinuxInstallConf
MeshSyntheticRuntimeEnabled: profile.MeshSyntheticRuntimeEnabled, MeshSyntheticRuntimeEnabled: profile.MeshSyntheticRuntimeEnabled,
MeshProductionForwardingEnabled: profile.MeshProductionForwardingEnabled, MeshProductionForwardingEnabled: profile.MeshProductionForwardingEnabled,
MeshFabricSessionEnabled: profile.MeshFabricSessionEnabled, MeshFabricSessionEnabled: profile.MeshFabricSessionEnabled,
VPNFabricSessionTransportEnabled: profile.VPNFabricSessionTransportEnabled,
MeshListenAddr: profile.MeshListenAddr, MeshListenAddr: profile.MeshListenAddr,
MeshListenPortMode: profile.MeshListenPortMode, MeshListenPortMode: profile.MeshListenPortMode,
MeshListenAutoPortStart: profile.MeshListenAutoPortStart, MeshListenAutoPortStart: profile.MeshListenAutoPortStart,
@@ -31,6 +31,7 @@ type DockerInstallProfile struct {
MeshSyntheticRuntimeEnabled bool `json:"mesh_synthetic_runtime_enabled"` MeshSyntheticRuntimeEnabled bool `json:"mesh_synthetic_runtime_enabled"`
MeshProductionForwardingEnabled bool `json:"mesh_production_forwarding_enabled"` MeshProductionForwardingEnabled bool `json:"mesh_production_forwarding_enabled"`
MeshFabricSessionEnabled bool `json:"mesh_fabric_session_enabled"` MeshFabricSessionEnabled bool `json:"mesh_fabric_session_enabled"`
VPNFabricSessionTransportEnabled bool `json:"vpn_fabric_session_transport_enabled"`
MeshListenAddr string `json:"mesh_listen_addr"` MeshListenAddr string `json:"mesh_listen_addr"`
MeshListenPortMode string `json:"mesh_listen_port_mode"` MeshListenPortMode string `json:"mesh_listen_port_mode"`
MeshListenAutoPortStart int `json:"mesh_listen_auto_port_start"` MeshListenAutoPortStart int `json:"mesh_listen_auto_port_start"`
@@ -74,6 +75,7 @@ type WindowsInstallProfile struct {
MeshSyntheticRuntimeEnabled bool `json:"mesh_synthetic_runtime_enabled"` MeshSyntheticRuntimeEnabled bool `json:"mesh_synthetic_runtime_enabled"`
MeshProductionForwardingEnabled bool `json:"mesh_production_forwarding_enabled"` MeshProductionForwardingEnabled bool `json:"mesh_production_forwarding_enabled"`
MeshFabricSessionEnabled bool `json:"mesh_fabric_session_enabled"` MeshFabricSessionEnabled bool `json:"mesh_fabric_session_enabled"`
VPNFabricSessionTransportEnabled bool `json:"vpn_fabric_session_transport_enabled"`
MeshListenAddr string `json:"mesh_listen_addr"` MeshListenAddr string `json:"mesh_listen_addr"`
MeshListenPortMode string `json:"mesh_listen_port_mode"` MeshListenPortMode string `json:"mesh_listen_port_mode"`
MeshListenAutoPortStart int `json:"mesh_listen_auto_port_start"` MeshListenAutoPortStart int `json:"mesh_listen_auto_port_start"`
@@ -107,6 +109,7 @@ type LinuxInstallProfile struct {
MeshSyntheticRuntimeEnabled bool `json:"mesh_synthetic_runtime_enabled"` MeshSyntheticRuntimeEnabled bool `json:"mesh_synthetic_runtime_enabled"`
MeshProductionForwardingEnabled bool `json:"mesh_production_forwarding_enabled"` MeshProductionForwardingEnabled bool `json:"mesh_production_forwarding_enabled"`
MeshFabricSessionEnabled bool `json:"mesh_fabric_session_enabled"` MeshFabricSessionEnabled bool `json:"mesh_fabric_session_enabled"`
VPNFabricSessionTransportEnabled bool `json:"vpn_fabric_session_transport_enabled"`
MeshListenAddr string `json:"mesh_listen_addr"` MeshListenAddr string `json:"mesh_listen_addr"`
MeshListenPortMode string `json:"mesh_listen_port_mode"` MeshListenPortMode string `json:"mesh_listen_port_mode"`
MeshListenAutoPortStart int `json:"mesh_listen_auto_port_start"` MeshListenAutoPortStart int `json:"mesh_listen_auto_port_start"`
@@ -285,6 +288,7 @@ func RuntimeConfigFromProfile(profile DockerInstallProfile) RuntimeConfig {
MeshSyntheticRuntimeEnabled: profile.MeshSyntheticRuntimeEnabled, MeshSyntheticRuntimeEnabled: profile.MeshSyntheticRuntimeEnabled,
MeshProductionForwardingEnabled: profile.MeshProductionForwardingEnabled, MeshProductionForwardingEnabled: profile.MeshProductionForwardingEnabled,
MeshFabricSessionEnabled: profile.MeshFabricSessionEnabled, MeshFabricSessionEnabled: profile.MeshFabricSessionEnabled,
VPNFabricSessionTransportEnabled: profile.VPNFabricSessionTransportEnabled,
MeshListenAddr: profile.MeshListenAddr, MeshListenAddr: profile.MeshListenAddr,
MeshListenPortMode: profile.MeshListenPortMode, MeshListenPortMode: profile.MeshListenPortMode,
MeshListenAutoPortStart: profile.MeshListenAutoPortStart, MeshListenAutoPortStart: profile.MeshListenAutoPortStart,
@@ -595,6 +595,7 @@ func (m DockerManager) runtimeConfigFromContainer(ctx context.Context, runner Co
MeshSyntheticRuntimeEnabled: true, MeshSyntheticRuntimeEnabled: true,
MeshProductionForwardingEnabled: parseBool(env["RAP_MESH_PRODUCTION_FORWARDING_ENABLED"]), MeshProductionForwardingEnabled: parseBool(env["RAP_MESH_PRODUCTION_FORWARDING_ENABLED"]),
MeshFabricSessionEnabled: parseBool(env["RAP_MESH_FABRIC_SESSION_ENABLED"]), MeshFabricSessionEnabled: parseBool(env["RAP_MESH_FABRIC_SESSION_ENABLED"]),
VPNFabricSessionTransportEnabled: parseBool(env["RAP_VPN_FABRIC_SESSION_TRANSPORT_ENABLED"]),
MeshListenAddr: env["RAP_MESH_LISTEN_ADDR"], MeshListenAddr: env["RAP_MESH_LISTEN_ADDR"],
MeshListenPortMode: env["RAP_MESH_LISTEN_PORT_MODE"], MeshListenPortMode: env["RAP_MESH_LISTEN_PORT_MODE"],
MeshListenAutoPortStart: parseInt(env["RAP_MESH_LISTEN_AUTO_PORT_START"]), MeshListenAutoPortStart: parseInt(env["RAP_MESH_LISTEN_AUTO_PORT_START"]),
@@ -67,6 +67,7 @@ func WindowsInstallConfigFromProfile(profile WindowsInstallProfile) WindowsInsta
MeshSyntheticRuntimeEnabled: profile.MeshSyntheticRuntimeEnabled, MeshSyntheticRuntimeEnabled: profile.MeshSyntheticRuntimeEnabled,
MeshProductionForwardingEnabled: profile.MeshProductionForwardingEnabled, MeshProductionForwardingEnabled: profile.MeshProductionForwardingEnabled,
MeshFabricSessionEnabled: profile.MeshFabricSessionEnabled, MeshFabricSessionEnabled: profile.MeshFabricSessionEnabled,
VPNFabricSessionTransportEnabled: profile.VPNFabricSessionTransportEnabled,
MeshListenAddr: profile.MeshListenAddr, MeshListenAddr: profile.MeshListenAddr,
MeshListenPortMode: profile.MeshListenPortMode, MeshListenPortMode: profile.MeshListenPortMode,
MeshListenAutoPortStart: profile.MeshListenAutoPortStart, MeshListenAutoPortStart: profile.MeshListenAutoPortStart,
@@ -280,6 +280,10 @@ VPN packet inbox by stream id.
stream ACK from the remote node. stream ACK from the remote node.
Mesh has a peer session manager that reuses one pump per peer endpoint, giving Mesh has a peer session manager that reuses one pump per peer endpoint, giving
VPN transport selection a stable place to acquire long-lived fabric sessions. VPN transport selection a stable place to acquire long-lived fabric sessions.
Node config now carries a separate gated
`RAP_VPN_FABRIC_SESSION_TRANSPORT_ENABLED` switch and heartbeat report for the
binary VPN packet transport, keeping endpoint exposure and VPN dataplane
rollout independently controllable.
Deliverables: Deliverables: