Why does HTTPS work through the OpenZiti Tunnel but fail when using the SDK?

Hi everyone,

I’m evaluating OpenZiti for HTTPS traffic and have run into a puzzling issue: HTTPS requests work flawlessly when routed through the Ziti Tunnel but consistently fail when using the OpenZiti SDK.

Has anyone experienced this? Some questions I have:

  • Why does HTTPS succeed over the Ziti Tunnel but break in the SDK?
  • How does the Tunnel’s TLS handling differ from the SDK’s transport layer?
  • Is the SDK stripping or re‑terminating SSL/TLS in a way that disrupts end‑to‑end encryption?
  • Are there SDK settings or hooks to preserve the original TLS handshake?
  • What identity or authentication checks does the SDK enforce that the Tunnel bypasses?

Any examples, advice, or documentation pointers would be greatly appreciated!

Thanks in advance!

1 Like

I'm guessing the failure you encountered involved the client software verifying that the server's certificate contains an SAN that matches the requested server name.

Or, was it a problem with the TLS handshake?

If it was the server name/host not matching the SAN, which SDK did you use? Some SDKs implement the client side as a socket handler, and others by hooking/intercepting the DNS lookup, so I'm wondering if your implementation might be inserting Ziti in such a way that it disrupts the SAN check.

How is your application using the OpenZiti Swift SDK? and can you identity how it is failing?

Tunnelers are applications that use their own tcp/ip stack to capture network packets and proxy them to OpenZiti overlay connections. The only TLS handling that the tunneler does is between itself and the OpenZiti components (edge routers, controllers). Connections for tunneled applications are opaque to the tunneler, and are passed through bit-for-bit (including any TLS handshake that the underlying application requires).

The OpenZiti SDKs are available for developers who want to write their own "OpenZiti native" applications, so the application would likely be coded to dial an OpenZiti service by name instead connecting a socket to an IP:port.

The Swift SDK Reference has some examples that might be helpful.

Hi @qrkourier,

I've captured detailed logs for this issue. Here's what I found:

What Works

  • SDK successfully intercepts https://www.example.co.id/
  • Connection to service-example established successfully
  • Edge router selected properly (354ms latency)
  • Data exchange works normally (346 bytes, then 363 bytes)

The Problem

After connection suddenly closes:

connection status[ED71] seq[2] err[close called]
ZitiError Code=-53 "unexpected error"

or

connection status[ED71] seq[2] err[close called]
ZitiError Code=-4095 "unexpected error"

Questions

  1. Is there a timeout setting on the service/edge router causing this?
  2. Why does the tunnel work but SDK doesn't? Any difference in connection management?
  3. Are there specific behavior differences between OpenZiti tunnel APK and OpenZiti SDK that could cause this?

Environment: iOS SDK (ZitiUrlProtocol)

Any insights on this unexpected connection closure would be appreciated. Thanks!

Hi @Dicky019,

I think your problem comes down to how your app is connecting to the remote server. Shawn asks how you're using the SDK. Can you provide a small sample application that demonstrates your problem? What I suspect is however your app is constructing the TLS connection, it is either missing a full set of CAs that things like curl or a browser would get from the OS (which is why the tunneler would work) or something along these lines is the issue. Can you show us how you're setting up the Swift connection over ziti?


As to your questoins:

In my experience, this is almost always the remote side disconnecting the connection for "whatever" reason or your platform (swift) disconnecting for some reason (such as malformed TLS).

Almost certainly not, in my experience. OpenZiti won't ever close a connection unless the remote side closes the connection.

The tunneler will take whatever the client application requests and send the bytes, byte for byte, through the wire as Shawn said. There is no difference in connection management. Where the differences will be is in how your app connects to the remote machine and negotiates TLS. This is where I think your problem manifests (see above).

It's possible, sure (see above)

In OpenZiti, is the certificate used for mutual TLS authentication with the Edge Router the same as the certificate (or private key) used by the actual destination service (e.g., an HTTPS server)?

No* (* nuance explained below), that's an understandable confusion, but that wouldn't be possible unless you configure the server to use the same certificates.

OpenZiti will create a connection that sends whatever bytes you put into it to the other end. If you send http, it'll tunnel http to the other side (as shown below) and http will offload from the remote identity towards the final traffic destination. However, that http connection will tunnel over an end to end encrypted connection, and between all identities in the circuit, there will be mutual TLS connections.

IF you use application embedded zero trust on both ends, the protocol doesn't matter as much, you'll still have secure connectivity without using https. In this scenario, you're creating an end-to-end encrypted tunnel from client to server. HTTPS really isn't "needed" in that sort of deployment.

That help any?

1 Like

Thank You @TheLumberjack @qrkourier @scareything - HTTPS Issue Resolved! :tada:

Appreciation Post

I wanted to take a moment to express my sincere gratitude to everyone who helped me resolve the issue: "Why does HTTPS work through the OpenZiti Tunnel but fail when using the SDK?"

The Journey

What started as a frustrating problem where:

  • :white_check_mark: HTTPS requests worked perfectly through OpenZiti Tunnel
  • :cross_mark: HTTPS requests consistently failed when using the OpenZiti SDK
  • :thinking: Same endpoints, same network, completely different results

The Root Cause Discovery

Thanks to the incredible OpenZiti community, we were able to identify that the issue wasn't actually with the SDK implementation, but with the server's SSL certificate chain being problematic!

The Solution

Root Cause: Server SSL certificate chain issues Resolution: Fix Server SSL certificate chain issues or implemented a reverse proxy to handle the SSL termination properly

1 Like