Architecture
Software-defined perimeter (SDP): how it works
The problem a software-defined perimeter sets out to solve fits in one sentence: your VPN gateway is being scanned right now.
Not targeted — scanned. It has a public address and an open port, and the world’s scanners sweep the entire IPv4 address space every day. They do not need to know who you are. They only need to know that something at that address answers.
SDP replaces the word “answers”. It is not a stricter set of firewall rules; it reverses the order. Prove who you are and the service exists. Fail, and there is nothing at that address at all — not even a refusal.
This article takes that reversal apart: three roles, five steps, one packet, and a closing section on what it cannot stop. The criterion-by-criterion comparison of the three remote access architectures lives in comparing traditional VPN, gateway-based ZTNA and SDP; this one stays inside SDP.
What a software-defined perimeter actually specifies
A software-defined perimeter is not an adjective. It is an architecture with a written specification: the Cloud Security Alliance has maintained the SDP specification since 2014, now at v2.0, and NIST SP 800-207 lists it as one route to implementing a zero trust architecture. So “is this vendor’s SDP the same thing as that vendor’s?” has an answer: check for the three roles, and for the one rule.
The three roles:
- SDP controller — the only place a decision gets made. It holds identity, device state and policy, and answers one question: which resources may this identity reach right now.
- Initiating host (IH) — the client on the user’s device. It holds X.509 certificates representing both the person and the machine.
- Accepting host (AH) — a node standing in front of each protected resource. One for ERP, one for the file server.
The one rule: drop-all. An accepting host discards every inbound packet by default, and opens no inbound port of its own — it dials out to the controller instead.
- Control plane: where authorisation happens
- Data plane: direct mTLS
- A resource this identity was not granted
Text version of this diagram
The three roles an SDP specification defines, and why authorisation and payload travel on two separate paths.
The three roles
- SDP controller, at the top: handles identity, device and policy, and works out which accepting hosts this identity gets.
- Initiating host (IH), bottom left: the client on the user device, holding a user certificate and a device certificate.
- Accepting hosts (AH), on the right: three of them, in front of ERP, a file server and a finance system. All drop every packet by default and open no inbound port.
Control plane (dashed)
- ① Each AH registers outbound to the controller at start-up, opening no port.
- ② The IH presents identity and device certificate and gets back the list it is authorised for.
- ③ The controller works out which AHs this identity gets.
- ④ The controller tells those AHs to expect a connection from this IH.
Data plane (solid)
- ⑤ The IH builds a mutual TLS tunnel straight to the AH in front of ERP and to the AH in front of the file server.
- No traffic passes through the controller; it is not on the data path.
- The third AH, in front of the finance system, has no line at all. It is registered and running — and to this IH it does not exist.
Of the five steps in the drawing, the fifth is the easiest to skim past and the one with the widest consequences: the controller is not on the data path. It takes part in the authorisation decision and then steps out, after which traffic runs point to point between client and host. That single fact decides where your bandwidth bottleneck is and who is technically capable of touching your data — both of which come back later.
Why a scanner cannot see what sits behind SDP
Start with what an ordinary firewall does. A strictly configured firewall receiving a packet it should not have will usually reply with a TCP RST, or an ICMP destination-unreachable. That is a refusal. A refusal is still a reply, and a reply is information: whoever sent the probe now knows there is a live machine at that address and that this particular port is shut.
Network service discovery runs on exactly that information. It asks “who answers”, then “what is answering”. Drop-all changes the answer to the first question.
- Unauthorised probes, all dropped
- The accepting host drop-all rule
- A path that exists only after verification
Text version of this diagram
One accepting host, one drop-all rule, and the two outcomes it produces — for an unauthorised probe and for a registered client.
Upper lane — the scanner
- The scanner has no identity and no key; this is ATT&CK T1046, service discovery.
- It sends TCP SYN packets at three ports: 443, 22 and 3389.
- All three are dropped.
- What comes back: no SYN-ACK, no RST, no ICMP.
- The scanner concludes there is nothing at this address, so the address never reaches a target list.
Lower lane — the registered client
- The client holds a device certificate and shares a single-packet-authorisation key with the accepting host.
- It first sends one SPA packet over UDP — a single packet, with no connection set up first.
- Only once that verifies does the accepting host open the rule.
- It opens for that source address only, and for the authorised port only.
- The two ends then complete an mTLS handshake to the resource behind the host.
What to take from it
- Both lanes meet the same rule; the host is not telling good people from bad ones.
- The only difference is whether a packet that verifies arrived first.
- Without a valid single packet, even a refusal never comes back.
To a scanner, “no reply” and “no host at this address” are the same observation. It will not stop to investigate, because it is sweeping tens of millions of addresses at once and has no reason to linger on a quiet one. The machine never reaches a target list, and the rest of the exploitation chain — fingerprint the version, match it to a known flaw, try default credentials — has nowhere to start.
This is why, during an attack surface inventory, the items that should be closed but cannot be usually need something other than hardening: they need to stop being reachable before authorisation. External remote services have been a leading initial-access route for years for one structural reason — they have to stay open to everyone.
How single packet authorisation differs from port knocking
Anyone asking this already knows port knocking: the client hits a sequence of closed ports, and the firewall opens up when it sees the right order. Same instinct, but with failure modes that bite. The sequence is fixed and in the clear, so anyone who can watch the traffic can record it and replay it. And a sequence needs several packets, which is itself an observable pattern.
Single packet authorisation (SPA) collapses that into one packet. It travels over UDP with no connection set up first, so verification finishes before the TCP three-way handshake ever starts — a packet that fails is discarded very early in the stack.
- Fields the packet actually carries
- The attack those fields defeat
Text version of this diagram
The field layout of a single-packet-authorisation packet, and which attack each group of fields defeats.
Packet fields, left to right
- Client ID: who is asking.
- One-time counter (HOTP counter): advances every time.
- Timestamp: short validity window.
- Source address: where it came from.
- Service and port: what is being asked for.
- Keyed hash (HMAC): computed with the shared key.
- The whole thing is one UDP packet, with no connection set up first.
Replay: capture it and resend
- The counter advances and the timestamp expires fast.
- The same packet is never taken twice.
Forgery: send one and hope
- Without the shared key the hash cannot be computed.
- A packet that fails is dropped, not answered.
Reuse: the same packet, elsewhere
- The packet is bound to one source and one service.
- Even on success, only that one port opens.
What to take from it
- Verification happens before the TCP handshake.
- A failure has no next step and no reply.
Three groups of fields, three jobs:
| Attack to stop | Port knocking | Single packet authorisation |
|---|---|---|
| Replay | Record the order, resend | Counter and timestamp make it single-use |
| Forgery | Guess the order | No key, no HMAC |
| Reuse elsewhere | Opens the whole port | Bound to one source address and one service |
The counter follows the incrementing logic of HOTP: client and accepting host each track a counter, and used values are never accepted again. The timestamp narrows the window further. Together they mean a perfectly captured packet is worth nothing on the second send.
The source address field quietly handles one more case. If someone spoofs a source address on an otherwise valid packet, the accepting host opens for the spoofed address — not for whoever actually sent it.
One misconception worth killing here: SPA is not encryption. It only decides whether a given source gets to see a given service. Confidentiality and two-way identity are the job of the mutual TLS session that follows. The two layers are separate and neither substitutes for the other.
Splitting the control plane from the data plane: the trade
Separating the authorisation decision from the traffic itself — a control plane and a data plane — is the sharpest divergence between SDP and gateway-based ZTNA. In a gateway architecture every byte transits the gateway. In SDP the controller issues a pass and leaves.
Three things you get:
- No central bandwidth bottleneck. Adding users does not slow everyone down, because there is no shared pipe to fill.
- The vendor is not on the data path. In cross-border transfer assessments and regulated-industry audits this tends to carry more weight than any throughput figure — “technically capable of accessing it” and “contractually promises not to” are answers at different levels.
- Connections take the short route. Two nodes in the same building do not detour through a regional gateway and back.
The cost needs saying just as plainly: the controller becomes the critical path for new connections. When it goes down, established sessions usually survive, but no new authorisation can be issued. High availability for the controller is therefore not an option to price later — it is a question to ask during evaluation, or you have merely swapped a single point of failure with an open port for one without.
The controller also has to be reachable by initiating hosts. Implementations commonly put it behind single packet authorisation too, or otherwise shrink its exposure, but it is not “zero exposure” — worth asking a vendor about directly.
One connection reaches exactly one resource
After a VPN authenticates you it hands you an internal address, so your reach is a network segment. After SDP authorises you it builds a tunnel to one accepting host, so your reach is that one service.
The difference only shows up during an incident. The same stolen credentials can be tried against every machine in the segment under the first model; under SDP they reach the handful of services that identity was granted, and lateral movement has no surface to extend across. This is the principle of least privilege landing at the network layer for the first time — historically it only ever landed in application role settings.
Granularity does not make anything safe on its own, though. It makes “what did we actually authorise” into something you are forced to write down. An SDP with sloppy policy and a VPN with an over-wide segment can end up equally bad. The full per-connection authorisation mechanism, and the places policy most often goes wrong, are in how the Merak zero trust network works.
What a software-defined perimeter does not stop
Any architecture write-up that skips the limits is not worth reading. These belong on the table during evaluation:
- A compromised endpoint bypasses all of it from the inside. Certificates and SPA keys live on the device. When the device is fully controlled, the attacker does not need to break an accepting host — they are the legitimate initiating host. Device posture checks and endpoint protection remain necessary, not optional.
- It does nothing about application-layer flaws. Once authorised, the application is still the application. SQL injection, broken access control and vulnerable components do not disappear because the transport changed.
- It does not replace in-app permissions. SDP answers whether this identity may reach this service. Who may read which record inside it is still the application’s job.
- Certificate lifecycle is a running cost. Issuance, rotation, revocation on departure, certificate revocation status checking — without those processes in place, a certificate is just a long-lived password in another format.
- Existing network monitoring goes partly blind. End-to-end encryption means intermediate nodes see nothing, so monitoring and data-loss prevention that inspected traffic at a gateway have to move to the endpoint or the application.
- Environments where nothing can be installed are out of scope. Legacy appliances and closed systems usually need a separate node standing in front of them, which is real deployment work.
Four questions to answer before you start
Where do the accepting hosts go? One per machine gives the finest granularity and the largest rollout; one front node covering a group of services deploys faster but leaves a small segment behind it. Most programmes end up mixing both, in batches.
Where does the controller live, and who operates it? Self-hosted, vendor-managed or hybrid. This decides both availability responsibility and your compliance narrative, so ask at the quoting stage rather than after.
Which services move first? Pick ones with few users, a clear blast radius, and current public exposure — usually remote desktop and management consoles.
How is the parallel period designed? The VPN does not switch off over a weekend. The practical path — inventory, run in parallel, migrate in batches, verify — is in choosing and replacing a VPN. Merak implements the SDP architecture described here; specifications and deployment options are on the Merak product page.
Terms and further reading
| Term | In one sentence | Source |
|---|---|---|
| Software-defined perimeter | Resources become reachable only after identity | NIST glossary |
| SDP specification | The source specification for the three roles | CSA SDP working group |
| Zero trust architecture | Trust that does not follow network location | What zero trust is |
| SDP controller | Holds identity and policy, makes the decision | CSA SDP spec v2.0 |
| Initiating host (IH) | The client that opens connections | CSA SDP spec v2.0 |
| Accepting host (AH) | The node in front of a protected resource | CSA SDP spec v2.0 |
| Drop-all | Unauthorised packets discarded with no reply | CSA SDP spec v2.0 |
| X.509 certificate | Standard format binding a public key to an ID | RFC 5280 |
| Network service discovery | Finding which services on a target answer | MITRE ATT&CK T1046 |
| External remote services | Entering through public remote access services | MITRE ATT&CK T1133 |
| Port knocking | Opening a port with a fixed knock sequence | Port knocking |
| Single packet authorisation | One signed packet grants pre-authorisation | CSA SDP spec v2.0 |
| UDP | Transport that needs no connection set-up | RFC 768 |
| TCP three-way handshake | The three steps that establish a TCP session | RFC 9293 |
| Replay attack | Capturing a valid message and sending it again | Replay attack |
| HMAC | Message authentication code from a shared key | RFC 2104 |
| HOTP | One-time password based on a moving counter | RFC 4226 |
| Source address spoofing | Faking the source address on a packet | IP address spoofing |
| Mutual TLS (mTLS) | TLS where both ends present a certificate | Mutual authentication |
| Control plane / data plane | Separating what decides from what carries | Forwarding plane |
| Single point of failure | One component failing takes the whole down | Single point of failure |
| Lateral movement | Spreading from one internal host to the next | MITRE ATT&CK TA0008 |
| Principle of least privilege | Granting only what is needed, nothing more | Principle of least privilege |
| Certificate revocation check | Confirming whether a certificate was revoked | RFC 6960 |
The diagrams here are simplified for explanation: controller high-availability topologies, the full field definition of an SPA packet, and the differences between implementations in counter and time-window handling have been left out for clarity, and the specifications govern actual behaviour. If you want to talk through how this architecture lands in a specific environment, get in touch.