syntax = "proto3"; import "google/protobuf/timestamp.proto"; import "google/protobuf/duration.proto"; option go_package = "/proto"; package management; service ManagementService { // Login logs in peer. In case server returns codes.PermissionDenied this endpoint can be used to register Peer providing LoginRequest.setupKey // Returns encrypted LoginResponse in EncryptedMessage.Body rpc Login(EncryptedMessage) returns (EncryptedMessage) {} // Sync enables peer synchronization. Each peer that is connected to this stream will receive updates from the server. // For example, if a new peer has been added to an account all other connected peers will receive this peer's Wireguard public key as an update // The initial SyncResponse contains all of the available peers so the local state can be refreshed // Returns encrypted SyncResponse in EncryptedMessage.Body rpc Sync(EncryptedMessage) returns (stream EncryptedMessage) {} // Exposes a Wireguard public key of the Management service. // This key is used to support message encryption between client and server rpc GetServerKey(Empty) returns (ServerKeyResponse) {} // health check endpoint rpc isHealthy(Empty) returns (Empty) {} // Exposes a device authorization flow information // This is used for initiating a Oauth 2 device authorization grant flow // which will be used by our clients to Login. // EncryptedMessage of the request has a body of DeviceAuthorizationFlowRequest. // EncryptedMessage of the response has a body of DeviceAuthorizationFlow. rpc GetDeviceAuthorizationFlow(EncryptedMessage) returns (EncryptedMessage) {} // Exposes a PKCE authorization code flow information // This is used for initiating a Oauth 2 authorization grant flow // with Proof Key for Code Exchange (PKCE) which will be used by our clients to Login. // EncryptedMessage of the request has a body of PKCEAuthorizationFlowRequest. // EncryptedMessage of the response has a body of PKCEAuthorizationFlow. rpc GetPKCEAuthorizationFlow(EncryptedMessage) returns (EncryptedMessage) {} // SyncMeta is used to sync metadata of the peer. // After sync the peer if there is a change in peer posture check which needs to be evaluated by the client, // sync meta will evaluate the checks and update the peer meta with the result. // EncryptedMessage of the request has a body of Empty. rpc SyncMeta(EncryptedMessage) returns (Empty) {} // Logout logs out the peer and removes it from the management server rpc Logout(EncryptedMessage) returns (Empty) {} // Executes a job on a target peer (e.g., debug bundle) rpc Job(stream EncryptedMessage) returns (stream EncryptedMessage) {} // ExtendAuthSession refreshes the peer's session expiry deadline using a fresh JWT. // Same JWT validation pipeline as Login (including jwt.UserID == peer.UserID check), // but does not redo the network-map sync. Only valid for SSO-registered peers where // login expiration is enabled. The tunnel remains up. // EncryptedMessage of the request has a body of ExtendAuthSessionRequest. // EncryptedMessage of the response has a body of ExtendAuthSessionResponse. rpc ExtendAuthSession(EncryptedMessage) returns (EncryptedMessage) {} // CreateExpose creates a temporary reverse proxy service for a peer rpc CreateExpose(EncryptedMessage) returns (EncryptedMessage) {} // RenewExpose extends the TTL of an active expose session rpc RenewExpose(EncryptedMessage) returns (EncryptedMessage) {} // StopExpose terminates an active expose session rpc StopExpose(EncryptedMessage) returns (EncryptedMessage) {} } message EncryptedMessage { // Wireguard public key string wgPubKey = 1; // encrypted message Body bytes body = 2; // Version of the Netbird Management Service protocol int32 version = 3; } message JobRequest { bytes ID = 1; oneof workload_parameters { BundleParameters bundle = 10; //OtherParameters other = 11; } } enum JobStatus { unknown_status = 0; //placeholder succeeded = 1; failed = 2; } message JobResponse{ bytes ID = 1; JobStatus status=2; bytes Reason=3; oneof workload_results { BundleResult bundle = 10; //OtherResult other = 11; } } message BundleParameters { bool bundle_for = 1; int64 bundle_for_time = 2; int32 log_file_count = 3; bool anonymize = 4; } message BundleResult { string upload_key = 1; } message SyncRequest { // Meta data of the peer PeerSystemMeta meta = 1; } // SyncResponse represents a state that should be applied to the local peer (e.g. Netbird servers config as well as local peer and remote peers configs) message SyncResponse { // Global config NetbirdConfig netbirdConfig = 1; // Deprecated. Use NetworkMap.PeerConfig PeerConfig peerConfig = 2; // Deprecated. Use NetworkMap.RemotePeerConfig repeated RemotePeerConfig remotePeers = 3; // Indicates whether remotePeers array is empty or not to bypass protobuf null and empty array equality. // Deprecated. Use NetworkMap.remotePeersIsEmpty bool remotePeersIsEmpty = 4; NetworkMap NetworkMap = 5; // Posture checks to be evaluated by client repeated Checks Checks = 6; // 3-state session deadline. Carried on every Sync snapshot so admin-side // changes propagate live without a client reconnect. // field unset (nil) → snapshot carries no info; client keeps the // deadline it already had // set, seconds=0 nanos=0 → explicit "expiry disabled" or peer is not // SSO-registered; client clears its anchor // set, valid timestamp → new absolute UTC deadline google.protobuf.Timestamp sessionExpiresAt = 7; // NetworkMapEnvelope carries the component-based wire format for peers that // advertise PeerCapabilityComponentNetworkMap. When set, NetworkMap (field 5) // is left empty: management ships components and the client runs Calculate() // locally instead of receiving an expanded NetworkMap. NetworkMapEnvelope NetworkMapEnvelope = 8; int32 Version = 9; } message SyncMetaRequest { // Meta data of the peer PeerSystemMeta meta = 1; } message LoginRequest { // Pre-authorized setup key (can be empty) string setupKey = 1; // Meta data of the peer (e.g. name, os_name, os_version, PeerSystemMeta meta = 2; // SSO token (can be empty) string jwtToken = 3; // Can be absent for now. PeerKeys peerKeys = 4; repeated string dnsLabels = 5; } // PeerKeys is additional peer info like SSH pub key and WireGuard public key. // This message is sent on Login or register requests, or when a key rotation has to happen. message PeerKeys { // sshPubKey represents a public SSH key of the peer. Can be absent. bytes sshPubKey = 1; // wgPubKey represents a public WireGuard key of the peer. Can be absent. bytes wgPubKey = 2; } // Environment is part of the PeerSystemMeta and describes the environment the agent is running in. message Environment { // cloud is the cloud provider the agent is running in if applicable. string cloud = 1; // platform is the platform the agent is running on if applicable. string platform = 2; } // File represents a file on the system. message File { // path is the path to the file. string path = 1; // exist indicate whether the file exists. bool exist = 2; // processIsRunning indicates whether the file is a running process or not. bool processIsRunning = 3; } message Flags { bool rosenpassEnabled = 1; bool rosenpassPermissive = 2; bool serverSSHAllowed = 3; bool disableClientRoutes = 4; bool disableServerRoutes = 5; bool disableDNS = 6; bool disableFirewall = 7; bool blockLANAccess = 8; bool blockInbound = 9; bool lazyConnectionEnabled = 10; bool enableSSHRoot = 11; bool enableSSHSFTP = 12; bool enableSSHLocalPortForwarding = 13; bool enableSSHRemotePortForwarding = 14; bool disableSSHAuth = 15; bool disableIPv6 = 16; } // PeerCapability represents a feature the client binary supports. // Reported in PeerSystemMeta.capabilities on every login/sync. enum PeerCapability { PeerCapabilityUnknown = 0; // Client reads SourcePrefixes instead of the deprecated PeerIP string. PeerCapabilitySourcePrefixes = 1; // Client handles IPv6 overlay addresses and firewall rules. PeerCapabilityIPv6Overlay = 2; // Client receives NetworkMap as components and assembles it locally. PeerCapabilityComponentNetworkMap = 3; } // PeerSystemMeta is machine meta data like OS and version. message PeerSystemMeta { string hostname = 1; string goOS = 2; string kernel = 3; string core = 4; string platform = 5; string OS = 6; string netbirdVersion = 7; string uiVersion = 8; string kernelVersion = 9; string OSVersion = 10; repeated NetworkAddress networkAddresses = 11; string sysSerialNumber = 12; string sysProductName = 13; string sysManufacturer = 14; Environment environment = 15; repeated File files = 16; Flags flags = 17; repeated PeerCapability capabilities = 18; int32 syncMessageVersion = 19; } message LoginResponse { // Global config NetbirdConfig netbirdConfig = 1; // Peer local config PeerConfig peerConfig = 2; // Posture checks to be evaluated by client repeated Checks Checks = 3; // 3-state session deadline; same encoding as SyncResponse.sessionExpiresAt. // field unset (nil) → no info; client keeps any deadline it had // set, seconds=0 nanos=0 → explicit "expiry disabled" / non-SSO peer // set, valid timestamp → new absolute UTC deadline google.protobuf.Timestamp sessionExpiresAt = 4; } // ExtendAuthSessionRequest carries a fresh JWT to refresh the peer's session deadline. // The encrypted body of an EncryptedMessage with this payload is sent to the // ExtendAuthSession RPC. message ExtendAuthSessionRequest { // SSO token (must be a fresh, valid JWT for the peer's owning user) string jwtToken = 1; // Meta data of the peer (used for IdP user info refresh consistent with Login) PeerSystemMeta meta = 2; } // ExtendAuthSessionResponse contains the refreshed session deadline. message ExtendAuthSessionResponse { // 3-state session deadline; same encoding as SyncResponse.sessionExpiresAt. // In practice ExtendAuthSession only succeeds for SSO peers with expiry // enabled, so this carries a valid timestamp on the success path. The // 3-state encoding is documented here for symmetry with Login/Sync. google.protobuf.Timestamp sessionExpiresAt = 1; } message ServerKeyResponse { // Server's Wireguard public key string key = 1; // Key expiration timestamp after which the key should be fetched again by the client google.protobuf.Timestamp expiresAt = 2; // Version of the Netbird Management Service protocol int32 version = 3; } message Empty {} // NetbirdConfig is a common configuration of any Netbird peer. It contains STUN, TURN, Signal and Management servers configurations message NetbirdConfig { // a list of STUN servers repeated HostConfig stuns = 1; // a list of TURN servers repeated ProtectedHostConfig turns = 2; // a Signal server config HostConfig signal = 3; RelayConfig relay = 4; FlowConfig flow = 5; MetricsConfig metrics = 6; } // HostConfig describes connection properties of some server (e.g. STUN, Signal, Management) message HostConfig { // URI of the resource e.g. turns://stun.netbird.io:4430 or signal.netbird.io:10000 string uri = 1; Protocol protocol = 2; enum Protocol { UDP = 0; TCP = 1; HTTP = 2; HTTPS = 3; DTLS = 4; } } message RelayConfig { repeated string urls = 1; string tokenPayload = 2; string tokenSignature = 3; } message FlowConfig { string url = 1; string tokenPayload = 2; string tokenSignature = 3; google.protobuf.Duration interval = 4; bool enabled = 5; // counters determines if flow packets and bytes counters should be sent bool counters = 6; // exitNodeCollection determines if event collection on exit nodes should be enabled bool exitNodeCollection = 7; // dnsCollection determines if DNS event collection should be enabled bool dnsCollection = 8; } message MetricsConfig { bool enabled = 1; } // JWTConfig represents JWT authentication configuration for validating tokens. message JWTConfig { string issuer = 1; // Deprecated: audience is kept for backwards compatibility only. Use audiences instead in the client code but populate this field. string audience = 2; string keysLocation = 3; int64 maxTokenAge = 4; // audiences contains the list of valid audiences for JWT validation. // Tokens matching any audience in this list are considered valid. repeated string audiences = 5; } // ProtectedHostConfig is similar to HostConfig but has additional user and password // Mostly used for TURN servers message ProtectedHostConfig { HostConfig hostConfig = 1; string user = 2; string password = 3; } // PeerConfig represents a configuration of a "our" peer. // The properties are used to configure local Wireguard message PeerConfig { // Peer's virtual IP address within the Netbird VPN (a Wireguard address config) string address = 1; // Netbird DNS server (a Wireguard DNS config) string dns = 2; // SSHConfig of the peer. SSHConfig sshConfig = 3; // Peer fully qualified domain name string fqdn = 4; bool RoutingPeerDnsResolutionEnabled = 5; bool LazyConnectionEnabled = 6; int32 mtu = 7; // Auto-update config AutoUpdateSettings autoUpdate = 8; // IPv6 overlay address as compact bytes: 16 bytes IP + 1 byte prefix length. bytes address_v6 = 9; } message AutoUpdateSettings { string version = 1; /* alwaysUpdate = true → Updates are installed automatically in the background alwaysUpdate = false → Updates require user interaction from the UI */ bool alwaysUpdate = 2; } // NetworkMap represents a network state of the peer with the corresponding configuration parameters to establish peer-to-peer connections message NetworkMap { // Serial is an ID of the network state to be used by clients to order updates. // The larger the Serial the newer the configuration. // E.g. the client app should keep track of this id locally and discard all the configurations with a lower value uint64 Serial = 1; // PeerConfig represents configuration of a peer PeerConfig peerConfig = 2; // RemotePeerConfig represents a list of remote peers that the receiver can connect to repeated RemotePeerConfig remotePeers = 3; // Indicates whether remotePeers array is empty or not to bypass protobuf null and empty array equality. bool remotePeersIsEmpty = 4; // List of routes to be applied repeated Route Routes = 5; // DNS config to be applied DNSConfig DNSConfig = 6; // RemotePeerConfig represents a list of remote peers that the receiver can connect to repeated RemotePeerConfig offlinePeers = 7; // FirewallRule represents a list of firewall rules to be applied to peer repeated FirewallRule FirewallRules = 8; // firewallRulesIsEmpty indicates whether FirewallRule array is empty or not to bypass protobuf null and empty array equality. bool firewallRulesIsEmpty = 9; // RoutesFirewallRules represents a list of routes firewall rules to be applied to peer repeated RouteFirewallRule routesFirewallRules = 10; // RoutesFirewallRulesIsEmpty indicates whether RouteFirewallRule array is empty or not to bypass protobuf null and empty array equality. bool routesFirewallRulesIsEmpty = 11; repeated ForwardingRule forwardingRules = 12; // SSHAuth represents SSH authorization configuration SSHAuth sshAuth = 13; } message SSHAuth { // UserIDClaim is the JWT claim to be used to get the users ID string UserIDClaim = 1; // AuthorizedUsers is a list of hashed user IDs authorized to access this peer via SSH repeated bytes AuthorizedUsers = 2; // MachineUsers is a map of machine user names to their corresponding indexes in the AuthorizedUsers list map machine_users = 3; } message MachineUserIndexes { repeated uint32 indexes = 1; } // RemotePeerConfig represents a configuration of a remote peer. // The properties are used to configure WireGuard Peers sections message RemotePeerConfig { // A WireGuard public key of a remote peer string wgPubKey = 1; // WireGuard allowed IPs of a remote peer e.g. [10.30.30.1/32] repeated string allowedIps = 2; // SSHConfig is a SSH config of the remote peer. SSHConfig.sshPubKey should be ignored because peer knows it's SSH key. SSHConfig sshConfig = 3; // Peer fully qualified domain name string fqdn = 4; string agentVersion = 5; } // SSHConfig represents SSH configurations of a peer. message SSHConfig { // sshEnabled indicates whether a SSH server is enabled on this peer bool sshEnabled = 1; // sshPubKey is a SSH public key of a peer to be added to authorized_hosts. // This property should be ignore if SSHConfig comes from PeerConfig. bytes sshPubKey = 2; JWTConfig jwtConfig = 3; } // DeviceAuthorizationFlowRequest empty struct for future expansion message DeviceAuthorizationFlowRequest {} // DeviceAuthorizationFlow represents Device Authorization Flow information // that can be used by the client to login initiate a Oauth 2.0 device authorization grant flow // see https://datatracker.ietf.org/doc/html/rfc8628 message DeviceAuthorizationFlow { // An IDP provider , (eg. Auth0) provider Provider = 1; ProviderConfig ProviderConfig = 2; enum provider { HOSTED = 0; } } // PKCEAuthorizationFlowRequest empty struct for future expansion message PKCEAuthorizationFlowRequest {} // PKCEAuthorizationFlow represents Authorization Code Flow information // that can be used by the client to login initiate a Oauth 2.0 authorization code grant flow // with Proof Key for Code Exchange (PKCE). See https://datatracker.ietf.org/doc/html/rfc7636 message PKCEAuthorizationFlow { ProviderConfig ProviderConfig = 1; } // ProviderConfig has all attributes needed to initiate a device/pkce authorization flow message ProviderConfig { // An IDP application client id string ClientID = 1; // Deprecated: use embedded IdP for providers that require a client secret (e.g. Google Workspace). string ClientSecret = 2 [deprecated = true]; // An IDP API domain // Deprecated. Use a DeviceAuthEndpoint and TokenEndpoint string Domain = 3; // An Audience for validation string Audience = 4; // DeviceAuthEndpoint is an endpoint to request device authentication code. string DeviceAuthEndpoint = 5; // TokenEndpoint is an endpoint to request auth token. string TokenEndpoint = 6; // Scopes provides the scopes to be included in the token request string Scope = 7; // UseIDToken indicates if the id token should be used for authentication bool UseIDToken = 8; // AuthorizationEndpoint is the endpoint of an IDP manager where clients can obtain authorization code. string AuthorizationEndpoint = 9; // RedirectURLs handles authorization code from IDP manager repeated string RedirectURLs = 10; // DisablePromptLogin makes the PKCE flow to not prompt the user for login bool DisablePromptLogin = 11; // LoginFlags sets the PKCE flow login details uint32 LoginFlag = 12; } // Route represents a route.Route object message Route { string ID = 1; string Network = 2; int64 NetworkType = 3; string Peer = 4; int64 Metric = 5; bool Masquerade = 6; string NetID = 7; repeated string Domains = 8; bool keepRoute = 9; bool skipAutoApply = 10; } // DNSConfig represents a dns.Update message DNSConfig { bool ServiceEnable = 1; repeated NameServerGroup NameServerGroups = 2; repeated CustomZone CustomZones = 3; int64 ForwarderPort = 4 [deprecated = true]; } // CustomZone represents a dns.CustomZone message CustomZone { string Domain = 1; repeated SimpleRecord Records = 2; bool SearchDomainDisabled = 3; // NonAuthoritative indicates this is a user-created zone (not the built-in peer DNS zone). // Non-authoritative zones will fallthrough to lower-priority handlers on NXDOMAIN and skip PTR processing. bool NonAuthoritative = 4; } // SimpleRecord represents a dns.SimpleRecord message SimpleRecord { string Name = 1; int64 Type = 2; string Class = 3; int64 TTL = 4; string RData = 5; } // NameServerGroup represents a dns.NameServerGroup message NameServerGroup { repeated NameServer NameServers = 1; bool Primary = 2; repeated string Domains = 3; bool SearchDomainsEnabled = 4; } // NameServer represents a dns.NameServer message NameServer { string IP = 1; int64 NSType = 2; int64 Port = 3; } enum RuleProtocol { UNKNOWN = 0; ALL = 1; TCP = 2; UDP = 3; ICMP = 4; CUSTOM = 5; // NETBIRD_SSH (types.PolicyRuleProtocolType "netbird-ssh") is the marker // policy rule that drives SSH-server activation in Calculate(). The legacy // proto.FirewallRule path doesn't ship this value (Calculate already // expands SSH rules into TCP/22 before encoding), but the components path // ships RAW policies — the client must see this protocol to derive // AuthorizedUsers locally. NETBIRD_SSH = 6; } enum RuleDirection { IN = 0; OUT = 1; } enum RuleAction { ACCEPT = 0; DROP = 1; } // FirewallRule represents a firewall rule message FirewallRule { // Use sourcePrefixes instead. string PeerIP = 1 [deprecated = true]; RuleDirection Direction = 2; RuleAction Action = 3; RuleProtocol Protocol = 4; string Port = 5; PortInfo PortInfo = 6; // PolicyID is the ID of the policy that this rule belongs to bytes PolicyID = 7; // CustomProtocol is a custom protocol ID when Protocol is CUSTOM. uint32 customProtocol = 8; // Compact source IP prefixes for this rule, supersedes PeerIP. // Each entry is 5 bytes (v4) or 17 bytes (v6): [IP bytes][1 byte prefix_len]. repeated bytes sourcePrefixes = 9; } message NetworkAddress { string netIP = 1; string mac = 2; } message Checks { repeated string Files = 1; } message PortInfo { oneof portSelection { uint32 port = 1; Range range = 2; } message Range { uint32 start = 1; uint32 end = 2; } } // RouteFirewallRule signifies a firewall rule applicable for a routed network. message RouteFirewallRule { // sourceRanges IP ranges of the routing peers. repeated string sourceRanges = 1; // Action to be taken by the firewall when the rule is applicable. RuleAction action = 2; // Network prefix for the routed network. string destination = 3; // Protocol of the routed network. RuleProtocol protocol = 4; // Details about the port. PortInfo portInfo = 5; // IsDynamic indicates if the route is a DNS route. bool isDynamic = 6; // Domains is a list of domains for which the rule is applicable. repeated string domains = 7; // CustomProtocol is a custom protocol ID. uint32 customProtocol = 8; // PolicyID is the ID of the policy that this rule belongs to bytes PolicyID = 9; // RouteID is the ID of the route that this rule belongs to string RouteID = 10; } message ForwardingRule { // Protocol of the forwarding rule RuleProtocol protocol = 1; // portInfo is the ingress destination port information, where the traffic arrives in the gateway node PortInfo destinationPort = 2; // IP address of the translated address (remote peer) to send traffic to bytes translatedAddress = 3; // Translated port information, where the traffic should be forwarded to PortInfo translatedPort = 4; } enum ExposeProtocol { EXPOSE_HTTP = 0; EXPOSE_HTTPS = 1; EXPOSE_TCP = 2; EXPOSE_UDP = 3; EXPOSE_TLS = 4; } message ExposeServiceRequest { uint32 port = 1; ExposeProtocol protocol = 2; string pin = 3; string password = 4; repeated string user_groups = 5; string domain = 6; string name_prefix = 7; uint32 listen_port = 8; } message ExposeServiceResponse { string service_name = 1; string service_url = 2; string domain = 3; bool port_auto_assigned = 4; } message RenewExposeRequest { string domain = 1; } message RenewExposeResponse {} message StopExposeRequest { string domain = 1; } message StopExposeResponse {} // ===================================================================== // Component-based NetworkMap wire format (PeerCapabilityComponentNetworkMap). // // Peers that advertise this capability receive NetworkMap building blocks // (peers + groups + policies + routes + dns + ssh + forwarding) and run the // expansion (Calculate) locally instead of receiving a fully-expanded // NetworkMap from the server. // ===================================================================== // NetworkMapEnvelope wraps either a full snapshot or a delta. Only Full is // emitted today; Delta is reserved for the incremental-update work. message NetworkMapEnvelope { oneof payload { NetworkMapComponentsFull full = 1; NetworkMapComponentsDelta delta = 2; } } // NetworkMapComponentsFull is the full per-peer component snapshot. The // client decodes it into a types.NetworkMapComponents and runs Calculate() // locally to produce the same NetworkMap the legacy server path would have // produced. Every field carries RAW component data — no server-side // expansion (firewall rules, DNS config, SSH auth, route firewall rules, // forwarding rules) is shipped; the client computes those itself. message NetworkMapComponentsFull { uint64 serial = 1; // Peer config for the receiving peer (legacy proto.PeerConfig kept as-is — // it carries the receiving peer's own overlay address, FQDN, SSH config). PeerConfig peer_config = 2; // Account-level network metadata (id, IPv4/IPv6 overlay subnets, DNS, // serial). Mirrors types.Network. AccountNetwork network = 3; // Account-level settings the client needs for its local Calculate(). AccountSettingsCompact account_settings = 4; // Account DNS settings (mirrors types.DNSSettings). DNSSettingsCompact dns_settings = 5; // Domain shared across all peers in this account, e.g. "netbird.cloud". // Each peer's FQDN is dns_label + "." + dns_domain. string dns_domain = 6; // Custom-zone domain for this peer's view (c.CustomZoneDomain). Empty when // the peer has no custom zone records. string custom_zone_domain = 7; // Deduplicated agent versions; PeerCompact.agent_version_idx indexes here. // Empty string at index 0 if any peer has no version. repeated string agent_versions = 8; // All peers (deduplicated). The client splits peers into online / offline // locally using account_settings.peer_login_expiration on receive. repeated PeerCompact peers = 9; // Indexes into peers for the subset that may act as routers. repeated uint32 router_peer_indexes = 10; // Policies that affect the receiving peer. repeated PolicyCompact policies = 11; // Groups in unspecified order — clients key off id (public_id). repeated GroupCompact groups = 12; // Routes relevant to this peer, raw shape (mirrors []*route.Route). repeated RouteRaw routes = 13; // Nameserver groups (mirrors []*nbdns.NameServerGroup). repeated NameServerGroupRaw nameserver_groups = 14; // All DNS records the client needs to assemble its custom zone. Reuses // the existing SimpleRecord wire shape. repeated SimpleRecord all_dns_records = 15; // Custom zones (typically the peer's own zone). Reuses the existing // CustomZone wire shape. repeated CustomZone account_zones = 16; // Network resources (mirrors []*resourceTypes.NetworkResource). repeated NetworkResourceRaw network_resources = 17; // Routers per network. Outer key: network public_id. Each entry is // the set of routers backing that network for this peer's view. map routers_map = 18; // For each NetworkResource public_id, the indexes into policies[] // that apply to it. map resource_policies_map = 19; // Group-id (public_id) → user ids authorized for SSH on members. map group_id_to_user_ids = 20; // Account-level allowed user ids (used by Calculate() when assembling SSH // authorized users for the receiving peer). repeated string allowed_user_ids = 21; // Per posture-check public_id, the set of peer indexes that failed // the check. Server-side evaluation result; clients do not re-evaluate. map posture_failed_peers = 22; // Account-level DNS forwarder port (mirrors the legacy // proto.DNSConfig.ForwarderPort). Computed by the controller from peer // versions; clients fold it into their Calculate() DNS output. int64 dns_forwarder_port = 23; // Pre-expanded NetworkMap fragments injected post-Calculate by external // controllers (BYOP / port-forwarding proxies). The receiving client // merges these into its locally-computed NetworkMap the same way the // legacy server does via NetworkMap.Merge — so downstream consumers see // a unified merged result regardless of source. ProxyPatch proxy_patch = 24; // SSH UserIDClaim — server-side HttpServerConfig.AuthUserIDClaim, or // "sub" by default. Populated in proto.SSHAuth.UserIDClaim when the // client rebuilds the NetworkMap from this envelope. Empty when the // account has no AuthorizedUsers (and thus no SshAuth to populate). string user_id_claim = 25; // Reserved for future component additions (incremental_serial, parent_seq, // etc.) without forcing a renumber. reserved 26 to 50; } // ProxyPatch carries NetworkMap fragments that don't fit the component-graph // model — they're pre-expanded by external controllers (BYOP / // port-forwarding proxies) and injected post-Calculate. Fields use the // legacy wire types because the proxy delivers them pre-formed; there is // no raw component shape to convert from. Empty when no proxy is active. message ProxyPatch { repeated RemotePeerConfig peers = 1; repeated RemotePeerConfig offline_peers = 2; repeated FirewallRule firewall_rules = 3; repeated Route routes = 4; repeated RouteFirewallRule route_firewall_rules = 5; repeated ForwardingRule forwarding_rules = 6; } // AccountSettingsCompact carries the account-level settings the client needs // to evaluate locally. Mirrors the subset of types.AccountSettingsInfo that // Calculate() actually reads — login-expiration (used to filter expired // peers). Inactivity expiration is purely server-side bookkeeping and is not // shipped. message AccountSettingsCompact { bool peer_login_expiration_enabled = 1; // Login expiration window. Unit is nanoseconds (matches time.Duration). int64 peer_login_expiration_ns = 2; } // AccountNetwork is the account-level overlay metadata. Mirrors types.Network // so the client can populate NetworkMap.Network without a server round-trip. message AccountNetwork { string identifier = 1; // IPv4 overlay subnet in CIDR form (e.g. "100.64.0.0/16"). string net_cidr = 2; // IPv6 ULA overlay subnet in CIDR form (e.g. "fd00:4e42::/64"). Empty when // the account has no IPv6 overlay yet. string net_v6_cidr = 3; string dns = 4; uint64 serial = 5; } // NetworkMapComponentsDelta is reserved for the incremental update // protocol. Field numbers 1–100 are pre-allocated to keep room for the // planned event types without needing a renumber. message NetworkMapComponentsDelta { reserved 1 to 100; } // PeerCompact is the wire-shape of a remote peer used by the component // format. It carries every field of types.Peer that the client's local // Calculate() reads — including the trio needed to evaluate // LoginExpired() (added_with_sso_login + login_expiration_enabled + // last_login_unix_nano). Fields the client does not consume (Status, // CreatedAt, etc.) are not shipped. message PeerCompact { // Raw 32-byte WireGuard public key (no base64 wrapping). bytes wg_pub_key = 1; // Raw 4-byte IPv4 overlay address. Always a /32 host route, so no prefix // byte is needed. bytes ip = 2; // Raw 16-byte IPv6 overlay address; always a /128 host route. Empty when // the peer has no IPv6 overlay address. bytes ipv6 = 3; // Raw SSH public key bytes (or empty). bytes ssh_pub_key = 4; // DNS label without the account's domain suffix. Full FQDN is // dns_label + "." + NetworkMapComponentsFull.dns_domain. string dns_label = 5; string agent_version = 6; // True iff the peer was added via SSO login (i.e., types.Peer.UserID is // non-empty). Combined with login_expiration_enabled and // last_login_unix_nano this lets the client reproduce // (*Peer).LoginExpired() locally. bool added_with_sso_login = 7; // True when the peer's login can expire — mirrors // types.Peer.LoginExpirationEnabled. bool login_expiration_enabled = 8; // Unix-nanosecond timestamp of the peer's last login. 0 when the peer has // never logged in (server stores nil; client treats 0 as "epoch", which // makes a fresh peer immediately expired iff login_expiration_enabled is // true — the same semantics as types.Peer.GetLastLogin). int64 last_login_unix_nano = 9; // True when the peer has an SSH server enabled locally. Used by the // legacy SSH path in Calculate() (`policyRuleImpliesLegacySSH`): a rule // with protocol ALL/TCP-with-SSH-ports activates SSH for the receiving // peer when this bit is set, even without an explicit NetbirdSSH rule. bool ssh_enabled = 10; // Mirror of types.Peer.SupportsIPv6() — !Meta.Flags.DisableIPv6 && // HasCapability(PeerCapabilityIPv6Overlay). Used by the local peer's // Calculate() when deciding whether to emit IPv6 firewall rules // (appendIPv6FirewallRule) against this peer's IPv6 address. bool supports_ipv6 = 11; // Mirror of types.Peer.SupportsSourcePrefixes() — // HasCapability(PeerCapabilitySourcePrefixes). Determines whether the // local peer's Calculate() emits SourcePrefixes alongside legacy PeerIP // fields in proto.FirewallRule. bool supports_source_prefixes = 12; // Mirror of types.Peer.Meta.Flags.ServerSSHAllowed. Read by Calculate() // when expanding TCP port-22 firewall rules — the native SSH companion // (port 22022) is only added when this flag is set and the peer agent // version supports it. bool server_ssh_allowed = 13; } // PolicyCompact is the compact form of a policy rule. Group references use // the public_ids; the client resolves // them against NetworkMapComponentsFull.groups. Direction is derived per-peer // on the client (ingress when the peer is in destination_group_ids, egress // when in source_group_ids; both when bidirectional). message PolicyCompact { // public_id. Used as a stable reference for // ResourcePoliciesMap.indexes and future delta updates. string id = 1; RuleAction action = 2; RuleProtocol protocol = 3; bool bidirectional = 4; // Single ports referenced by the rule. repeated uint32 ports = 5; // Port ranges (start..end) referenced by the rule. repeated PortInfo.Range port_ranges = 6; // Group ids (public_ids) of source / destination groups. repeated string source_group_ids = 7; repeated string destination_group_ids = 8; // SSH authorization fields. PolicyRule.AuthorizedGroups maps the rule's // applicable group ids (public_ids) to a list of local-user names — // when a peer in one of those groups is the SSH destination, the named // local users gain access. AuthorizedUser is the single-user form // (legacy: rule scopes SSH to one specific user id). // // Both fields are only consumed by Calculate() when the rule's protocol // is NetbirdSSH (or the legacy implicit-SSH heuristic). map authorized_groups = 9; string authorized_user = 10; // Resource-typed rule sources/destinations. When a rule targets a specific // peer (rather than groups), Calculate() reads SourceResource / // DestinationResource — without these the rule's connection resources // can't be produced on the client. ResourceCompact's peer_index refers to // NetworkMapComponentsFull.peers; type is the raw ResourceType string // ("peer", "host", "subnet", "domain"). Only "peer" is meaningful for // Calculate's resource-typed rule path today. ResourceCompact source_resource = 11; ResourceCompact destination_resource = 12; // Posture-check ids gating this policy's source peers. Calculate() // reads them when filtering rule peers (peers that fail any listed check // are dropped from sourcePeers). Match keys in // NetworkMapComponentsFull.posture_failed_peers. repeated string source_posture_check_ids = 13; } // ResourceCompact mirrors types.Resource. Used by PolicyCompact to carry // rule.SourceResource / rule.DestinationResource when the rule targets a // specific resource (typically a peer) rather than groups. // peer_index_set tells whether peer_index is valid (proto3 uint32 cannot // disambiguate "0" from "unset"); set only when type == "peer". message ResourceCompact { string type = 1; bool peer_index_set = 2; uint32 peer_index = 3; reserved 4; // future: host/subnet/domain references when needed } // UserNameList is a list of local-user names — used as the value type in // PolicyCompact.authorized_groups. message UserNameList { repeated string names = 1; } // GroupCompact is the wire-shape of a group: public id, optional // name, and indexes into NetworkMapComponentsFull.peers identifying members. message GroupCompact { // id comes from PublicID. Used by PolicyCompact.source_group_ids / destination_group_ids. string id = 1; // Indexes into NetworkMapComponentsFull.peers. repeated uint32 peer_indexes = 2; // True when the group is named "All" (types.Group.IsGroupAll). The // client-side Calculate short-circuits group→peer expansion on such // groups exactly like the server does; without this bit the decoded // groups lose that property and the two sides expand policy // destinations differently. bool is_all = 3; } // DNSSettingsCompact mirrors types.DNSSettings. message DNSSettingsCompact { // Group ids (public_id) whose DNS management is disabled. repeated string disabled_management_group_ids = 1; } // RouteRaw mirrors *route.Route (the domain type), trimmed to fields that // types.NetworkMapComponents.Calculate() reads. Group references are // public_ids; the routing peer (when set) is referenced by index into // NetworkMapComponentsFull.peers. message RouteRaw { string id = 1; // public_id string net_id = 2; string description = 3; // Either network_cidr (e.g. "10.0.0.0/16") or domains is set, not both. string network_cidr = 4; repeated string domains = 5; bool keep_route = 6; // Routing peer reference: peer_index_set tells whether peer_index is valid // (proto3 uint32 cannot disambiguate "0" from "unset"). Mutually exclusive // with peer_group_ids. // // peer_index decodes back to types.Peer.ID (the peer's xid string), NOT // to its WireGuard public key. This matches the server-side data flow: // c.Routes carry route.Peer = peer.ID, and getRoutingPeerRoutes mutates // it to peer.Key only after the route has been admitted to the network // map. Decoders MUST set Route.Peer = peer.ID; the legacy Calculate() // path will substitute the WG key downstream. bool peer_index_set = 7; uint32 peer_index = 8; repeated string peer_group_ids = 9; int32 network_type = 10; bool masquerade = 11; int32 metric = 12; bool enabled = 13; repeated string group_ids = 14; repeated string access_control_group_ids = 15; bool skip_auto_apply = 16; } // NameServerGroupRaw mirrors *nbdns.NameServerGroup. Distinct from the // legacy NameServerGroup (which is the wire-trimmed shape consumed by // proto.DNSConfig and lacks the Name/Description/Groups/Enabled fields). message NameServerGroupRaw { string id = 1; // Reuses the legacy NameServer wire shape (IP as string). repeated NameServer nameservers = 2; // Group ids the NSG distributes nameservers to. repeated string group_ids = 3; bool primary = 4; repeated string domains = 5; bool enabled = 6; bool search_domains_enabled = 7; } // NetworkResourceRaw mirrors *resourceTypes.NetworkResource. // message NetworkResourceRaw { string id = 1; string network_seq = 2; string name = 3; string description = 4; // Resource type: "host" / "subnet" / "domain". string type = 5; string address = 6; string domain_value = 7; // resource.Domain string prefix_cidr = 8; bool enabled = 9; } // NetworkRouterList carries the routers backing one network. message NetworkRouterList { // Routers in this network, keyed by peer_index (the routing peer). repeated NetworkRouterEntry entries = 1; } // NetworkRouterEntry mirrors a single *routerTypes.NetworkRouter; the routing // peer is referenced by index into NetworkMapComponentsFull.peers. message NetworkRouterEntry { string id = 1; uint32 peer_index = 2; bool peer_index_set = 3; repeated string peer_group_ids = 4; bool masquerade = 5; int32 metric = 6; bool enabled = 7; } message PolicyIds { repeated string ids = 1; } // UserIDList is a list of user ids — used as the value type in // NetworkMapComponentsFull.group_id_to_user_ids. message UserIDList { repeated string user_ids = 1; } // PeerIndexSet is a set of peer indexes — used as the value type in // NetworkMapComponentsFull.posture_failed_peers. message PeerIndexSet { repeated uint32 peer_indexes = 1; }