Architecture
How the Merak zero trust network works
Marketing has worn the phrase “zero trust” down to an attitude. It is not an attitude. It is a set of very specific engineering decisions: who opens the connection, what represents an identity, where the private key lives, at which layer authorisation happens, and what occurs when something fails.
This article takes a zero trust network access (ZTNA) network of the kind Merak builds and pulls it apart into eight mechanisms, one diagram each. If you know roughly how TCP opens a connection and roughly what a certificate is, you have enough to read it. Every term is listed again at the end with a link to its specification.
What problem this is solving
Traditional network security is a perimeter model: put the assets behind a wall, put one door in the wall (a VPN gateway or a firewall), and check people at the door. Whoever passes gets an internal IP address, and from then on what they can reach is decided by subnets and firewall rules — not by who they are.
The weakness is not that the door is flimsy. It is that there is no second decision behind it. Steal one set of working credentials and movement inside the network is close to unimpeded — the technique catalogued as lateral movement, and the stage that turns a single compromised laptop into a breach.
- paths open to the attacker
- the one authorised connection
- network perimeter
Text version of this diagram
Two trust models side by side: on the left, reachability follows network position; on the right, it follows per-connection authorisation.
Left — perimeter model (network first, permissions later)
- A stolen account passes the gateway from outside and lands inside the internal segment.
- The segment holds four hosts: file server, ERP, database, monitoring.
- Once the attacker has a foothold, they move laterally across the segment and reach all four hosts in turn.
- Authentication happens once at the door; the subnet decides who can reach whom afterwards.
- Result: one foothold equals every host on the segment.
Right — identity model (identity first, then a tunnel)
- The client holds a user certificate and a device certificate, presenting identity: alice.
- The same four services are on offer: file server, ERP, database, monitoring.
- Policy authorises ERP only, so exactly one connection is established.
- The other three services return nothing to this identity — a probe gets no answer at all.
- Result: a stolen identity reaches only what it could already reach; the blast radius does not grow.
The whole claim of zero trust fits in one sentence: a position on the network is not a reason to trust anything. Making that real starts with separating “can reach” from “is authorised” in the architecture itself.
1. Split deciding from carrying
The first structural decision is plane separation, borrowing the control plane and forwarding plane split from network hardware.
- The control plane handles enrolment, policy, certificate issuance and the authorisation decision for every connection. It decides — and it never touches application data.
- The data plane is a set of interconnected edge nodes forming a mesh that carries the traffic. It moves bytes, and makes no authorisation decisions of its own; it enforces what the control plane synchronised to it.
- control: node to control plane
- link: node to node
- edge: application to node
Text version of this diagram
How the control plane and the data plane divide the work, and the three link types that join them.
Control plane
- Handles enrolment, policy definition, certificate issuance and per-connection authorisation decisions.
- Never touches application data.
Data plane — mesh of edge nodes
- Edge nodes A, B and C form a mesh and carry the actual traffic.
- The client joins through an in-app SDK or a local proxy.
- The protected service has no inbound listener.
Three link types
- Control links, between an endpoint and the control plane, for enrolment, authorisation and policy.
- Link connections, between edge nodes, forming the mesh data path.
- Edge connections, between an endpoint and an edge node — the hop traffic actually travels.
- All three are mutual TLS: both ends present a certificate, and no hop is plaintext or anonymous.
Two consequences follow directly. First, the vendor is not on the data path — the control plane sees who asked to reach what and when, and nothing of the contents. In cross-border transfer reviews and regulated industries, that distinction usually matters more than any throughput number. Second, there is no central gateway in the data plane, and therefore no single point of failure whose loss disconnects everyone.
All three link types run mutual TLS. Ordinary web TLS authenticates only the server; the client stays anonymous. Mutual TLS requires a certificate from both ends, so the connection itself carries both identities. No hop is plaintext and no hop is anonymous.
2. An identity is a certificate, not a username
In a network like this, every principal — person, device, service, workload — has an identity that is an X.509 certificate.
If PKI is new to you, this is the model to hold: a certificate is a statement that “this public key belongs to this subject”, signed by a trusted issuer with the issuer’s own private key. Check the signature and you know the statement has not been altered. But a certificate is public information. Holding one proves nothing; proving an identity means proving you hold the matching private key.
Which makes the design goal of the enrolment flow singular: the private key must never leave the endpoint, from generation onward.
- messages that cross the network
- steps that happen only locally
- automatic renewal loop
Text version of this diagram
The full sequence by which an endpoint gains a certificate identity — seven steps, built so the private key never leaves the device.
Participants
- The endpoint (a person, device or service).
- The control plane.
Steps
- 1. A one-time enrolment token (a JWT) is delivered to the endpoint out of band.
- 2. The endpoint connects to the address inside the token and asks for the control plane certificate.
- 3. The certificate comes back; the endpoint verifies the holder really owns the matching private key.
- 4. The endpoint generates a key pair locally, writes the private key to local storage and wraps only the public key in a CSR.
- 5. The certificate signing request goes out together with the enrolment token.
- 6. Once verified, the control plane issues the certificate chain and the identity exists.
- 7. Steps 5 and 6 re-run automatically before expiry, with no manual reissue.
The point
- The private key never leaves the device — record the entire exchange and you still cannot clone the identity.
Step 4 is where it turns. The endpoint generates an asymmetric key pair locally, writes the private key to local storage, and wraps the public key in a certificate signing request (CSR, RFC 2986). The control plane verifies it and signs a certificate chain back.
So: recording the entire enrolment exchange still does not reconstruct the identity — all an observer captured was a public key. That is a categorically different security model from shipping a password or an API key over the wire, where a single weak point in transport or storage hands the credential over intact.
The one-time token in step 1 is typically a short-lived JWT (RFC 7519), usable once, whose only job is to tell the endpoint where to connect and let the control plane recognise this particular enrolment. It is spent the moment it becomes a certificate.
Worth knowing: even if your primary sign-in is OpenID Connect or a password, the client still has to obtain a short-lived certificate before it can reach an edge node — the data plane insists on mutual TLS end to end, and without a certificate there is no connection to make. How a human authenticates and what carries the connection’s identity are two separate things.
3. Why encrypt twice
Seeing both “mutual TLS everywhere” and “end-to-end encryption” usually prompts the same question: isn’t one of those redundant?
No. They protect different things, and they nest.
- mTLS: per hop, separate keys
- AEAD: end to end, keys at the ends only
- the original payload
Text version of this diagram
On the left, the order of encapsulation; on the right, what each node along the same path can actually decrypt.
Order of encapsulation (inside out)
- Innermost: the application payload — HTTP, SQL or any other protocol.
- Middle: an AEAD seal whose key exists only at the two ends.
- Outermost: mutual TLS 1.2 or later, with a separate key for every hop.
- The two layers are independent: replace one and the other is unaffected.
Who can decrypt what along the path
- The path runs App A → relay edge node → App B, split into mTLS hop 1 and mTLS hop 2.
- App A holds the end-to-end key Ke.
- App B holds the end-to-end key Ke.
- The relay edge node does not hold Ke and forwards ciphertext it cannot open.
- So compromising the relay still yields nothing but ciphertext.
- The transport layer is per hop. Client to node A is one segment; node A to node B is another, with its own keys. It answers “who is on the other end of this hop, and can anyone else hear it”.
- The application data layer is end to end. The payload is sealed at the source with authenticated encryption (AEAD, RFC 5116), and only the two endpoints hold that key. In practice that means an algorithm such as ChaCha20-Poly1305 (RFC 8439) that provides confidentiality and integrity together — “authenticated” meaning that a single flipped bit makes decryption fail outright rather than produce garbage.
The consequence is blunt: a relay node forwards ciphertext it cannot open. For the confidentiality of the payload, the data plane is an untrusted component; take a whole node and you still hold ciphertext.
Where the end-to-end boundary actually sits depends on how the application connects. Embed the encryption boundary in the application itself and it runs application to application. When a legacy system cannot be modified and a local proxy takes over instead, the boundary runs proxy to proxy — still covering the entire network path, with the short local hop from proxy to application outside it. That is a trade-off worth stating explicitly during a rollout rather than discovering later.
4. Every connection asks again
A valid certificate completes authentication — who you are. It says nothing about authorisation — what you may do. Conflating the two is where a great many access control designs go wrong.
Each time someone opens a new connection to a service, four checks run in order:
- the decision chain
- all four pass: tunnel to that service
- any failure: denied
Text version of this diagram
Every connection walks four checks in order, and only all four together open a tunnel.
Premise
- Holding a certificate only proves authentication. Every new connection walks all four gates again.
The four gates, in order
- 1. identity — the certificate is valid and the identity is enrolled.
- 2. policy — policy grants this identity access to this service.
- 3. path — the connection travels authorised nodes and routes.
- 4. posture — the endpoint posture meets what the policy requires.
Outcome
- All four pass → a tunnel opens, and it leads to that one service only.
- Any gate fails → denied, and nothing comes back that would confirm the service exists.
- The grant is the tunnel itself — it cannot reach a service nobody authorised.
What matters is the granularity and the timing. Granularity is a single service rather than a subnet; timing is every connection rather than every login. Together they are the principle of least privilege implemented at the network layer: compromise an endpoint and the attacker reaches only the services that identity was already authorised for. The unreachable boxes on the right of Figure 01 stay unreachable for them too.
A trap worth designing around: multiple policies granting the same service are usually combined as an OR union — one passing policy is enough. Attach both a policy with a posture check and a policy without one to the same identity and service, and the second silently disables the posture check. Nothing errors, because both policies are individually valid. Count the union in whenever you write policy.
5. Passing once is not enough
The fourth gate — the posture check — deserves its own section, because it is one of the few mechanisms that keeps acting after the connection is already up.
- evaluation passes
- endpoint state changes
- authorisation lost, connection closed
Text version of this diagram
Two posture models compared on the same timeline: checked once, versus evaluated for the life of the connection.
Top lane — checked once, at connection time
- The endpoint passes the check at the moment the connection is set up.
- Some time later it drifts out of compliance.
- The existing connection lives on regardless, until the user closes it.
Bottom lane — evaluated for the life of the connection
- After setup, every state comparison keeps passing.
- The moment the endpoint drifts out of compliance, that change is seen.
- Authorisation disappears and the existing connection is torn down on the spot.
How reporting works
- Reporting is change-driven: the endpoint compares its own state on a cycle and sends only what changed, rather than reporting everything on a timer.
Conventional access control checks at the door, so a laptop that was compliant this morning and had something installed on it this afternoon keeps its connection until the user closes it. Continuous evaluation changes exactly that: the moment the endpoint drifts, the existing connection closes — no waiting for the next reconnect.
The common check types look roughly like this:
| Check | What it evaluates | Typical use |
|---|---|---|
| Operating system / version | A named OS, optionally a version range (a Semver-style expression) | Keep out builds that no longer receive security updates |
| Network interface address | The endpoint’s interface address is on an allow list | Bind access to company-issued hardware |
| Multi-factor | The endpoint has passed TOTP (RFC 6238) verification, with a configurable timeout | Require recent verification for sensitive services |
| Process | Matched by executable path, binary hash or signing fingerprint | Confirm endpoint protection is actually running |
| Domain membership | The endpoint belongs to a named domain | Separate corporate assets from personal devices |
Multi-factor is the only one with time semantics: you can require verification within the last N seconds, and re-prompt after the device locks or wakes.
The reporting model is worth noting too. Posture reporting is change-driven — the endpoint compares its own state on a cycle and sends a report only when something changed, rather than uploading full state every few seconds. That is what makes it scale, and it also explains why drift detection lands in seconds rather than milliseconds.
6. Why the service cannot be scanned: reverse the direction
This is the least intuitive mechanism in the architecture and the most effective.
Start from a plain fact about opening a TCP connection. For a service to be reachable, it must open an inbound listening port — which is a broadcast to the entire network saying “I am here, and this port will talk to you”. Any open port shows up under a port scan: the scanner sends a SYN, and a SYN-ACK confirms something is there. Version fingerprinting, certificate probing, known-vulnerability matching and login brute force all follow. The first step of the whole attack chain is that answer.
The listener is the attack surface. So the answer a zero trust network gives is: do not have one.
- the scanner's probe
- an answer means it was found
- the connection the service opens
- traffic returning down that connection
Text version of this diagram
Two exposure models compared: a conventional inbound listener, versus a service that only dials out and never accepts inbound.
Top row — conventional: the service opens an inbound listener and waits
- The scanner can be anyone on the internet, and sends the service a TCP SYN.
- The firewall needs an allow rule for inbound traffic.
- The service host sits at :443 LISTEN.
- It answers with a SYN-ACK, which is exactly how it gets found.
- An answer is the starting point for fingerprinting, certificate probing and login brute force.
Bottom row — outbound dial: the service only dials out, never accepts inbound
- The service host has no listener at all.
- Inbound firewall rules can be default-deny across the board.
- The scanner sends a TCP SYN and gets no SYN-ACK, no RST — nothing at all.
- 1. The service dials out to an edge node over TCP, on its own initiative.
- 2. Authorised traffic travels back to the service down that same established connection.
The node hosting the service opens no inbound listener at all. It dials out to the data plane over TCP and, on that already-established connection, registers itself as the terminator for the service. Every authorised request for that service afterwards travels back down the existing channel from an edge node. The service side only ever dialled out, and never accepted an inbound connection from the internet.
From the scanner’s side:
| Aspect | Conventional inbound service | Outbound dial |
|---|---|---|
| Connection direction | client → service (inbound) | service → edge node (outbound) |
| Externally reachable port | required | no listener at all |
| Result of a SYN scan | SYN-ACK, service found | no answer; indistinguishable from nothing |
| Inbound firewall rules | needs an allow rule | can be entirely default-deny |
| Public IP / NAT configuration | usually required | not required |
Note the practical weight of the last two rows. Because only outbound needs to be permitted — usually 443, which is generally open already — the service side can deny all inbound. And because the connection is established from the inside out, it traverses NAT and CGNAT naturally. That is why a service can sit in a private range with no public address at all and still be reachable by authorised users: it never needed to be dialled into.
It is worth being precise about what this does and does not stop. It removes the possibility of being scanned and probed at all — the front of the attack chain. It does not make application bugs disappear. When an authorised identity connects, your SQL injection is still a SQL injection.
7. How traffic gets there: cost-based routing and failover
Once legitimate traffic is inside the data plane, one question remains: which way does it go?
- the original cheapest path
- failed link
- path after automatic failover
Text version of this diagram
Cost-based routing across the mesh data plane, and what happens when one link fails.
Topology
- Several edge nodes form a mesh between the client and the service, offering more than one viable path.
- Every link carries a cost value.
Normal state
- Traffic takes the cheapest total path, at a cost of 9 + 11 = 20.
After a link fails
- One link goes down and routing moves to the next-cheapest path on its own.
- The rerouted path costs 12 + 14 = 26.
- No central gateway has to fail over, so there is no single point of failure.
The point
- The path is computed: measured latency plus per-link cost, always taking the cheapest total.
The data plane keeps measuring per-link latency, and path selection is cost-based: measured latency, plus the operator-assigned cost of each link, plus the terminator’s own cost and precedence — lowest total wins. Conceptually it is a shortest path problem over a weighted graph whose weights move as conditions change.
When a link fails or congests, routing shifts to an alternative with almost nothing visible to the application above. The contrast with a single-gateway architecture is structural rather than incremental: when the gateway goes, everyone goes — and a mesh data plane has no “everyone”.
8. What this architecture costs you
Any document claiming an architecture has no trade-offs is not worth reading. These belong on the table during evaluation:
- A component has to be deployed on the endpoint or service side. An environment where nothing can be installed, and where no separate host can front the service either, is not a fit.
- Control plane availability is on the critical path. Authorisation decisions depend on it, so its high-availability design belongs in the architecture review rather than in an appendix.
- It does not replace application-level permissions. This machinery decides whether an identity may reach a service. Roles, row-level permissions and audit trails inside that service remain the application’s job.
- Existing network monitoring goes blind. End-to-end encryption means intermediate nodes see nothing, so monitoring and DLP that inspected traffic at a gateway need rethinking — usually by moving visibility to the endpoint or the application.
- The union semantics of policy invite mistakes. The OR-union trap above is the most common misconfiguration once policy counts grow, and it is worth a review process of its own.
Terms and further reading
| Term | One-line explanation | Source |
|---|---|---|
| Zero trust architecture | Treating network position as no basis for trust | NIST SP 800-207 |
| TLS 1.3 | The current transport encryption standard | RFC 8446 |
| Mutual TLS | TLS where both ends present a certificate | Mutual authentication |
| X.509 certificate | The standard binding of a public key to a subject | RFC 5280 |
| PKI | The system that issues, verifies and revokes certificates | Public key infrastructure |
| CSR | A signing request carrying only the public key | RFC 2986 |
| Revocation status | Checking whether a certificate has been revoked | RFC 6960 |
| JWT | A signed token format, used for enrolment and sign-in | RFC 7519 |
| OpenID Connect | An identity layer on top of OAuth 2.0 | OIDC Core |
| PKCE | Protects authorisation codes for public clients | RFC 7636 |
| AEAD | Encryption providing confidentiality and integrity together | RFC 5116 |
| ChaCha20-Poly1305 | A widely used AEAD algorithm | RFC 8439 |
| TOTP | Time-based one-time passwords, common in MFA | RFC 6238 |
| TCP connection setup | The three-way handshake, SYN and SYN-ACK | RFC 9293 |
| Port scanning | Probing which ports answer | Port scanner |
| NAT / CGNAT | Address translation, and carrier-grade shared space | RFC 3022 · RFC 6598 |
| Lateral movement | Spreading from one internal host to the next | MITRE ATT&CK TA0008 |
| Least privilege | Granting only what is needed | Principle of least privilege |
| Control / data plane | Separating what decides from what carries | Forwarding plane |
| Single point of failure | One component whose loss takes down the whole | Single point of failure |
| Semantic versioning | Version comparison rules, used by posture checks | Semantic Versioning |
The diagrams here are simplified for clarity: the full weighting of cost-based routing, posture reporting intervals and the high-availability topology of the control plane are left out, and product documentation is authoritative for actual values and behaviour. If you want to discuss a rollout for a specific environment, or need the fuller technical specification, get in touch.