Ziti DNS and TLS still showing self-signed cert despite correct DNS resolution (Node B → Node A via Ziti)

I have two VPS nodes:

  • Node A (runs Vault-like service + ziti-edge-tunnel host)
  • Node B (runs ziti-edge-tunnel client and should connect to Node A securely through Ziti)

Node A’s public address is vault.example.app:8200, but it should be accessed internally through Ziti with a proper certificate chain issued by Root CA.
However, when testing from Node B, I still see the old self-signed HashiCorp-style certificate even though DNS resolution points to Ziti.

What’s working

Node A side:
sudo openssl x509 -in /opt/vault/tls/vault.crt -noout -subject -issuer -enddate

subject=CN = vault.example.app

issuer=CN = Root CA

notAfter=Jan 16 10:10:31 2028 GMT

Node A ziti-edge-tunnel status:
sudo ziti-edge-tunnel tunnel_status | jq '.Data.Identities[0].Services | {Name, IsAccessible}'

vault-service: true

vault.example.app: true

Node B DNS resolution:
getent ahostsv4 vault.example.app

100.64.0.1 vault.example.app

dig @100.64.0.2 vault.example.app +short

100.64.0.3

cat /etc/hosts

100.64.0.3 vault.example.app

resolvectl:
DNS=100.64.0.2
Domains=~internal


:cross_mark: The problem

From Node B:
echo | openssl s_client -4 -connect vault.example.app:8200 -servername vault.example.app -showcerts 2>/dev/null | openssl x509 -noout -subject -issuer

subject=O = HashiCorp, CN = Vault

issuer=O = HashiCorp, CN = Vault

So, even though DNS resolves correctly to 100.64.x.x, the TLS handshake still hits the public listener instead of the Ziti-hosted one.


Observations

  • Ziti DNS resolution (via 100.64.0.2) is working fine.
  • But s_client connections still reach the public certificate.
  • Restarting ziti-edge-tunnel on Node A drops SSH (expected).
  • After reconnecting, tunnel shows services as active, but traffic still isn’t being intercepted for port 8200.

Suspected root cause

Either:

  1. The Ziti tunnel on Node A is not actually binding the Vault service (port 8200) locally; or
  2. The Ziti edge-tunnel on Node B is not intercepting correctly for vault.example.app; or
  3. The DNS configuration on Node B intermittently bypasses the Ziti resolver.

What’s been tried

  • Verified DNS through getent, dig, and /etc/hosts.
  • Restarted both tunnels (ziti-edge-tunnel service).
  • Confirmed both services show IsAccessible: true.
  • Still getting the public certificate when testing TLS.

Looking for guidance

What’s the correct way to ensure that:

  • Ziti intercepts all traffic for vault.example.app over the fabric,
  • Node A actually hosts/binds tcp:127.0.0.1:8200 through Ziti, and
  • TLS requests from Node B never touch the public network?

Any suggestions to verify or enforce the binding/intercept mapping would be appreciated.

Hi @relias,

Thanks for providing so much information. Sometimes it can hide what the problem actually is. Also, the formatting of the message makes it a bit hard to parse what you're trying to highlight vs what is a command result etc...

Looking through the post, it seems like you're saying this is the issue:

My guess here, is that your offloading traffic at the far side - after it's traversed ziti to the public endpoint. My guess is your offload is targetting "vault.example.app". People will routinely obfuscate DNS entries. that can make it harder for us to help too fwiw. I assume "vault.example.app" IS an actual public FQDN?

If this were me, i would remove any overlapping DNS entries entirely (which may not be possible if you're using tls). Anyway, i'd like to see what your host.v1 offload looks like. I assume the router/zet on the far side is colocated with vault? If that is the case the offload of vault should be to 127.0.0.1 not to the "vault.example.app" FQDN. That would explain why you're seeing what you're seeing but to be totally honest with what you've written, it's just not 100% clear to me... Hope that helps