Back to Opennhp

Message Types

docs/protocol/messages.md

0.7.313.7 KB
Original Source

NHP Message Types

{: .fs-9 }

Every packet carries a 2-byte Message Type ID in the header. That ID routes the packet to a logical handler on the receiver. Twenty-eight IDs are defined today: seventeen NHP types (IDs 0–16) covering the knock/auth/access flow, AC lifecycle, relay, registration, OTP, and explicit session exit; plus eleven DHP types (IDs 17–27) used by the Data-content Hiding Protocol. {: .fs-6 .fw-300 }

Implements CSA Stealth Mode SDP §NHP Message Types (Table 4) and Appendix 2. IDs and string names defined in nhp/core/packet.go; payload structs in nhp/common/nhpmsg.go.

Message envelope

Every message type uses the same header (see [Message Header]({{ '/protocol/header/' | relative_url }})) followed by an encrypted payload. Payloads are JSON, optionally zlib-compressed (see the NHP_FLAG_COMPRESS flag), then AEAD-encrypted using the session key derived during header parsing — unless the type description says otherwise (e.g., NHP-KPL has no body; NHP-RLY carries a raw inner packet).

Index

NHP — Network-infrastructure Hiding Protocol

IDNameDirectionPurpose
0NHP-KPLAgent ↔ Server, AC ↔ ServerKeepalive. Empty body.
1NHP-KNKAgent → ServerKnock: request access to a Protected Resource.
2NHP-ACKServer → AgentResponse to a knock. Carries resource address and session parameters on success.
3NHP-AOPServer → ACInstruct the AC to open (or deny) access for a given agent → resource flow.
4NHP-ARTAC → ServerAC response to NHP-AOP.
5NHP-LSTAgent → ServerRequest the list of services an agent is entitled to.
6NHP-LRTServer → AgentResponse to NHP-LST.
7NHP-COKServer → AgentRate-limit / DDoS-defence cookie issued when the server is overloaded.
8NHP-RKNAgent → ServerSecond knock, HMAC'd with the cookie from NHP-COK.
9NHP-RLYRelay → ServerForward a raw NHP packet from an NHP-Relay, preserving source address.
10NHP-AOLAC → ServerAC announces its online status and the resources it protects.
11NHP-AAKServer → ACServer confirms the AC's registration. Carries the AC's public IP/port.
12NHP-OTPAgent → ServerRequest an out-of-band OTP for registration.
13NHP-REGAgent → ServerAgent registers its static public key, authenticated by the OTP.
14NHP-RAKServer → AgentConfirmation (or failure code) for NHP-REG.
15NHP-ACCAgent → ACAgent presents its temporary access token to the AC's listener.
16NHP-EXTAgent → ServerRequest early closure of an active session. Empty body.

DHP — Data-content Hiding Protocol (documented here for completeness; detailed DHP semantics live with the DHP docs)

{: .note } DHP entries are shown under their Go constant names (e.g., NHP_DRG) rather than as hyphenated mnemonics, and are not yet anchored to per-type subsections. A dedicated DHP Reference page will expand each row with a payload-field table matching the NHP format above. Wire-name quirk: in nhp/core/packet.go the DHP string labels are a mix — IDs 17–26 render as NHP_DRGNHP_DBA (underscore, NHP prefix; differs from the NHP block above which uses hyphens), while ID 27 renders as "DHP-KNK" (hyphen, DHP prefix; its Go constant is DHP_KNK). Implementers decoding the HeaderTypeToString output should match the exact strings shown in the table below.

IDConstantDirectionPurpose
17NHP_DRGDB → ServerRegister a data object with the NHP-Server.
18NHP_DAKServer → DBAcknowledgement / error code for NHP_DRG.
19NHP_DARDHP-Agent → ServerRequest access to a registered data object.
20NHP_DAGServer → DHP-AgentAuthorization decision for NHP_DAR.
21NHP_DSAServer → DHP-AgentRequest a self-attestation (TEE / evidence).
22NHP_DAVDHP-Agent → ServerAttestation proof returned to the server.
23NHP_DWRServer → DBAsk the DB for the wrapped data-object private key.
24NHP_DWADB → ServerDB returns the wrapped key (Key Access Object).
25NHP_DOLDB → ServerDB online / status announcement.
26NHP_DBAServer → DBAcknowledgement of NHP_DOL.
27DHP_KNKDHP-Agent → ServerDHP-flavoured knock carrying attestation evidence.

NHP-KPL — Keepalive {#nhp-kpl--keepalive}

ID: 0 · Direction: bidirectional (Agent ↔ Server, AC ↔ Server) · Body: empty (header only)

Keeps the NAT binding / TCP connection alive between Agent/AC and Server. Receivers do nothing beyond accepting the packet. Relay nodes do not forward keepalives.

NHP-KNK — Knock {#nhp-knk--knock}

ID: 1 · Direction: Agent → Server · Payload struct: common.AgentKnockMsg

JSON keyFieldDescription
headerTypeHeader TypeEcho of the on-wire message type.
usrIdUser IDPer-user identifier tying the request to a human or service principal.
devIdDevice IDPer-device identifier for multi-device / posture policies.
orgIdOrganization IDOptional tenant scope.
aspIdASP IDWhich Authorization Service Provider the Server should consult.
resIdResource IDThe Protected Resource being requested (domain, service name, or opaque ID).
resultsCheck ResultsOptional {checkID: result} map reflecting client-side posture checks.
usrDataUser DataOptional free-form data passed through to the ASP plugin.

The knock is the only message that initiates an NHP exchange from a cold start.

NHP-ACK — Acknowledge {#nhp-ack--acknowledge}

ID: 2 · Direction: Server → Agent · Payload struct: common.ServerKnockAckMsg

JSON keyFieldDescription
errCode / errMsgError code / message"0" (or empty) on success; any other value indicates the failure reason.
resHostResource HostsMap of resource name → host address.
opnTimeOpen TimeSeconds the open-door window remains valid.
aspTokenASP TokenOptional token for AC-side backend validation.
agentAddrAgent AddressThe agent's public tuple as the server saw it.
acTokensAC TokensMap of resource name → short-lived token used with NHP-ACC.
preActionsPre-access ActionsOptional per-resource PreAccessInfo (AC IP, port, pubkey, token, cipher scheme) used when the deployment requires an NHP-ACC step.
redirectUrlRedirect URLOptional HTTPS redirect (e.g., login flow) instead of direct connect.

NHP-AOP — AC Operation {#nhp-aop--ac-operation}

ID: 3 · Direction: Server → AC · Payload struct: common.ServerACOpsMsg

JSON keyFieldDescription
usrId / devId / orgIdAgent identityAttribution fields.
aspId / resIdASP + ResourceCorrelates to the original knock.
srcAddrsSource addressesList of NetAddress the AC should allow.
dstAddrsDestination addressesProtected-resource tuples.
opnTimeOpen TimeSeconds; 0 means deny / close.

NAT note: behind CGNAT or shared egress the Source IP is not unique per agent. Deployments should layer an application-layer token/cookie between AC and the Protected Resource (the NHP-ACC path does exactly this), or prefer IPv6 end-to-end.

NHP-ART — AC Result {#nhp-art--ac-result}

ID: 4 · Direction: AC → Server · Payload struct: common.ACOpsResultMsg

Carries errCode / errMsg, the granted opnTime (0 = denied), the AC-issued token, and an optional preAct (PreAccessInfo). Only after ART reaches the Server does the Server send NHP-ACK to the Agent.

NHP-LST — List {#nhp-lst--list}

ID: 5 · Direction: Agent → Server · Payload struct: common.AgentListMsg

Carries usrId, devId, optional orgId, aspId, and free-form usrData.

NHP-LRT — List Result {#nhp-lrt--list-result}

ID: 6 · Direction: Server → Agent · Payload struct: common.ServerListResultMsg

Carries errCode / errMsg and a list map whose shape is defined by the ASP plugin.

ID: 7 · Direction: Server → Agent · Payload struct: common.ServerCookieMsg

Carries the server-echoed trxId and a server-generated cookie. Issued when the Server is under load. The Agent must re-knock using NHP-RKN and include this cookie in the HMAC calculation to prove a round-trip and survive early-drop.

NHP-RKN — Re-Knock {#nhp-rkn--re-knock}

ID: 8 · Direction: Agent → Server · Payload: identical to NHP-KNK.

Difference from NHP-KNK: the header HMAC is keyed with the NHP-COK cookie in addition to the normal chaining key (see addHMAC(sumCookie: true) in nhp/core/initiator.go).

NHP-RLY — Relay {#nhp-rly--relay}

ID: 9 · Direction: Relay → Server · Payload: the raw inner NHP packet from the origin.

Preserves the origin source address through the relay, which most other message types do not need (they are forwarded transparently).

NHP-AOL — AC Online {#nhp-aol--ac-online}

ID: 10 · Direction: AC → Server · Payload struct: common.ACOnlineMsg

Carries aspId, the list of resIds the AC protects, and an optional acId. Announces an AC joining the control plane.

NHP-AAK — AC Acknowledge {#nhp-aak--ac-acknowledge}

ID: 11 · Direction: Server → AC · Payload struct: common.ServerACAckMsg

Carries errCode / errMsg and acAddr. Confirms AC registration and echoes back the AC's public address (useful when the AC is behind NAT and learns its external tuple from the Server).

NHP-OTP — One-Time Password {#nhp-otp--one-time-password}

ID: 12 · Direction: Agent → Server · Payload struct: common.AgentOTPMsg

Carries usrId, devId, optional orgId, aspId, an optional pass (pre-shared passcode), and free-form usrData. Triggers the ASP plugin to issue an OTP out-of-band (SMS, email, QR). The server does not reply with a dedicated message type; success is signalled by the ASP delivering the OTP through its own channel.

NHP-REG — Register {#nhp-reg--register}

ID: 13 · Direction: Agent → Server · Payload struct: common.AgentRegisterMsg

Carries usrId, devId, optional orgId, aspId, the otp received out-of-band, and free-form usrData. Registers the Agent's static public key (carried in the encrypted header) against its identity.

NHP-RAK — Register Acknowledge {#nhp-rak--register-acknowledge}

ID: 14 · Direction: Server → Agent · Payload struct: common.ServerRegisterAckMsg

Carries errCode ("0" on success), errMsg, and aspId. Failures during registration are reported here explicitly via a non-zero errCode — see HandleRegisterRequest.

NHP-ACC — Access {#nhp-acc--access}

ID: 15 · Direction: Agent → AC · Payload struct: common.AgentAccessMsg

Carries usrId, devId, optional orgId, acToken (from NHP-ACK's acTokens), and usrData. Presented directly to the AC's short-lived listener when the deployment uses per-session temporary endpoints (PreAccessInfo) rather than long-lived allow-lists. After verifying the token, the AC installs the firewall rule for the observed source address and closes the temporary port — see tcpTempAccessHandler / udpTempAccessHandler. No NHP-level reply is emitted on this path; success is signalled implicitly by the subsequent data-plane connection succeeding against the Protected Resource. The common.ACAccessAckMsg struct is defined but not currently wired up on the send path; treat it as reserved for future use.

NHP-EXT — Exit {#nhp-ext--exit}

ID: 16 · Direction: Agent → Server · Body: empty.

Agent explicitly requests early teardown of an active session. The Server then sends an NHP-AOP with opnTime = 0 to close the AC rule.


DHP message types {#dhp}

The Data-content Hiding Protocol reuses the NHP wire format for a separate set of flows around data-object registration, access, attestation, and key wrapping. They are listed here so the ID table is complete; their payload fields (DRGMsg, DAKMsg, DARMsg, DAGMsg, DSAMsg, DAVMsg, DWRMsg, DWAMsg, DBOnlineMsg, ServerDBAckMsg, DHPKnockMsg) are defined in nhp/common/nhpmsg.go. A dedicated DHP reference page will expand these; for now, see the [DHP Quick Start]({{ '/dhp_quick_start/' | relative_url }}).


See also

  • [Message Header]({{ '/protocol/header/' | relative_url }}) — the envelope every type shares
  • [Cryptography]({{ '/cryptography/' | relative_url }}) — how the payload is encrypted
  • [Glossary]({{ '/glossary/' | relative_url }}) — canonical names for every role that appears here