ZPA packet flow

Hi Guys,

hope you all are good and safe.

I’m new to Zscaler so trying to put all the possible way to get this understand as some things in my pipe line for working with this solution.
so here i want to understand the ZPA packet flow from end user machine perspective.
how Zapp decide that which traffic i need to tunnel for ZPA etc.
how certificates fit into the ZPA picture.

Thank you.

Well, there’s a lot to that, depending on the level of detail you’re looking for. For now I’ll restrict myself to a high-level perspective (which indeed means that it’s not 100% correct, but close enough for the purpose of this question). Feel free to reach out for a more detailed discussion.

I’m presuming you’re already aware of the functional components (Zscaler Client Connector (ZCC), ZPA Service Edge nodes (ZPA SE) and App Connectors. At initiation, all these components enroll into their own Zscaler certificate which is used to establish mutual authenticated TLS connections.
In this example we’ll make a user set up an SSH session to server01.safemarch.com

  1. App Connectors establish a TLS connection to their closest ZPA SE at startup, which is used for configuration updates and signalling between Cloud and Connector
    Similarly, when started (and after authentication) ZCC establishes a TLS connection to its closest ZPA SE at startup and (among others) learns which traffic should be handled by ZPA. This is based on FQDNs, wildcard-domains and (occasionally) IP ranges, and is defined in the global ZPA admin Dashboard.

  2. The user starts the SSH client and initiates a session to server01.safemarch.com. ZCC intercepts the DNS request, sees that it matches the ZPA config and forwards it to the ZPA SE

  3. The ZPA cloud checks for policy, selects one or more App Connectors (based on policy & geographical distance to the user) and asks these candidates if they can resolve and connect to the requested host, and what their latency is towards the destination. Note that only the Connector needs to know the actual host IP address; the ZPA Cloud only needs to know if it was resolved & reachable.
    The ZPA Cloud then elects which App Connector will handle the request, provide a micro tunnel ID to the Connector and another to the ZCC and inform the ZPA SE that these are related

  4. The elected Connector sets up a TLS session to the ZPA SE to which the ZCC is already connected. It also builds the local SSH session to server01.safemarch.com, using its own interface IP address

  5. ZCC generates a synthetic IP address in the 100.64.x.x range and spoofs the DNS response. The SSH client sets up a TCP connection to this address to port 22. ZCC locally terminates the connection, graps the data-part (stripping all TCP/IP information), adds its mtunnel-ID and sends it through the TLS session to the ZPA SE

  6. The ZPA SE removes the ZCC mtunnel-ID, adds the App Connector mtunnel-ID and forwards the packet over the TLS session to the App Connector.

  7. The Connector takes the data-part and injects it into the previously established session to server01.safemarch.com.

  8. Responses from the server are picked up by the Connector & the data-part is send back to the ZPA SE which forwards it to the ZCC which, in turn, delivers the data to the SSH client

And that’s the short of it, hope it helps


Thanks, well explained, may I know how zpa detect the packet loss if tcp header stripped

That’s a good question.
In a regular session there’s a single TCP session between client and server, so signaling goes direct.
With ZPA there are multiple sessions:
-within the client (Connection is between application and ZCC)
-between ZCC and Broker (TLS session)
-between AppConnector and Broker (TLS session)
-between AppConnector and Server (application session)

The peers can handle their respective traffic flows themselves, but to your point, if a packet is lost in transit, the broker can’t resend the data since it doesn’t cache. Instead there’s still a packet counter in the m-tunnel flow, so ZCC (in case of the client) or the App Connector (for the application server) is aware if a packet is missed to it can signal the other end to ask (ACK) for that previous packet.
This also means that once ZPA moves to DTLS (TLS over UDP) nothing has to change; flow control is still covered end-to-end.

Thank you much,
May I know, how client certificate is distributed to the client system .

Can you explain the same flow with double encryption? and is it possible to use custom certificate instead of zscaler certificate?

The Zscaler client (ZCC) will automatically enroll into its certificate during the initial authentication (on a clean install or after the user has completely logged out). The private key is stored in a separate encrypted file in the ZCC folder, there is no interaction with the OS certificate vault. The certificate is validated by a system fingerprint; copying it to another system will render it invalid.
By default the Zscaler ZPA CA will be used for signing the client certificate, but you can set up another signing certificate in ZPA and use that instead. Note that this requires both ZCC, AppConnector, private ZPA Service Edge (if used) and Cloud Connectors (if used) to all use the private CA.

Tunnel-in-tunnel connections create an additional TLS session between ZCC and App Connector. This means that the mtunnel forwards TLS packets instead of the direct data. Its main purpose is to have an additional guarantee that the ZPA Service Edge doesn’t have any access to unencrypted data as it flows from one mtunnel to the other (Nb: this is already true from an architectural point-of-view, this provides an additional layer of protection).


Thank you so much for explaining this