Problem Description
We're using OpenZiti SDK (embedded in our client application) to intercept traffic to a SaaS provider (Atlassian) that has multiple unknown subdomains (*.atlassian.net).
We configured a wildcard intercept to catch all Atlassian subdomains since we can't enumerate them all upfront:
{
"addresses": ["*.atlassian.net"],
"protocols": ["tcp"],
"portRanges": [{"low": 443, "high": 443}]
}
What's Happening
-
DNS interception works fine - When the client requests media.atlassian.net, the OpenZiti DNS resolver intercepts and returns a synthetic IP
-
Connection routing fails - When the traffic reaches the router/terminator, it tries to dial *.atlassian.net (the pattern) instead of the actual hostname (media.atlassian.net)
Error Logs
ERROR: dial tcp: lookup *.atlassian.net: no such host
From the terminator logs:
error creating route for [c/4CxylnaQD2zxJ2yXrJfeqY]: dial tcp: lookup *.atlassian.net: no such host
Current Workaround
If we create explicit services for each known subdomain (without wildcards), it works perfectly:
json
{
"addresses": ["media.atlassian.net"],
"protocols": ["tcp"],
"portRanges": [{"low": 443, "high": 443}]
}
But this doesn't scale - we can't enumerate all possible Atlassian subdomains upfront.
Questions
-
Is this a known limitation of OpenZiti wildcards? Can wildcards only work at the DNS level and not for actual connection routing?
-
Is there a way to extract the actual hostname (from SNI or DNS query) and pass it to the terminator instead of the wildcard pattern?
-
What's the recommended approach for routing traffic to SaaS providers with unknown/dynamic subdomains through OpenZiti?
-
Would implementing an intermediate HTTPS proxy (HAProxy/NGINX) that extracts SNI and forwards to the real backend be the correct solution?
Hello and welcome to the OpenZiti discourse!
Wildcard DNS should work as I think you're expecting. First can you tell me which OpenZiti SDK you're using in your application?
Secondly, I'm assuming your host configuration specifies address forwarding. This is what you want - it tells the receiving tunneler that the actual dial address should be obtained from metadata that was provided when the Ziti service was dialed.
Without knowing more about which SDK you're using and more details about how the application sets up Ziti service dials, I'm guessing that your app is putting the address from the service configuration into the dial metadata. When the address is a DNS wildcard (or an IP CIDR block), it's on the app to supply the specific hostname or IP of the destination when calling the Ziti SDK's dial function.
For example, the openziti tunneler sdk gets hostnames for dialing by doing a reverse lookup on the intercepted IP address to get the dial destination (ziti-tunnel-sdk-c/lib/ziti-tunnel-cbs/ziti_tunnel_cbs.c at main · openziti/ziti-tunnel-sdk-c · GitHub). This works because the internal DNS server adds host/ip mappings hostnames in wildcard domains looked up.
If the above doesn't help then please let me know which SDK you're using, and maybe provide an example of the code that's doing the dial.
Thanks!
@scareything
Hi Shawn, thanks for the detailed explanation.
I think there is a misunderstanding in our setup: we are not using host hosting/address-forwarding at all today (no tunneler / host SDK app in the private network). Our architecture is:
-
We deploy OpenZiti routers inside private networks and use them as the gateway/egress point.
-
For onboarding SaaS apps (e.g. Atlassian), we create:
-
an intercept.v1 config to intercept client traffic (e.g. foo.atlassian.net:443)
-
a terminator on one of the routers with a fixed dial address, and we whitelist that router’s egress IP in the SaaS admin panel.
-
So the “dial” is performed by the router using the terminator address; we are not supplying dial metadata from an SDK host app.
When we tried to expand coverage from a single domain to all subdomains (because Atlassian uses many subdomains like media-cdn.atlassian.com), we changed intercept to wildcard and also tried wildcard in the terminator.
Here the intercept is working as expected, but looks like terminator DNS lookup is failing.
Terminator Config:
{
"id": "5fQ8kPyGKoIqKUgYBoUiGY",
"address": "tcp:*.atlassian.net:443",
"binding": "edge_transport",
"routerId": "lWa0W2tbn2",
"serviceId": "7DnN9vtDym046LJfx1i3yV",
"precedence": "default",
"cost": 0
}
Controller Log:
error creating route for [s/49HPBWSNEJmDd17YgDfHru] on [r/lWa0W2tbn2] (error creating route for [c/49HPBWSNEJmDd17YgDfHru]: dial tcp: lookup *.atlassian.net: no such host)
Question:
Given that we are not using host + forwardAddress/forwardPort and we don’t have a tunneler/host app supplying specific dial metadata, is there any way to support wildcard subdomains with router-managed static terminators only?
Or is the intended solution in OpenZiti to use host.v1 address forwarding (and therefore some hosting component like a tunneler / SDK host) so the concrete destination host (e.g. media-cdn.atlassian.com) is supplied per connection?
If needed, I can share more detail on how the client is dialing.
Thanks again.
Thanks for the updates.
intercept.v1 addresses can be projected on the overlay either through address forwarding as we've hinted at here or with or addressable terminators, where the dialing tunneler uses the intercepted ip/hostname to select the terminator by specifying $dst_ip/$dst_hostname in intercept.v1 dialOptions.identity.
It sounds like you're trying to take the addressable terminator route, but as you've discovered terminators can only bind with a specific name. If you don't know the full set of destination addresses up front then you need to use a tunneler at the hosting side of the connection with address forwarding enabled in the host.v1 configuration.
That said, if you already have a router running at your required locations then you can enable a tunneler within it if it isn't already enabled. This would let your router behave as an edge identity that processes a host.v1 service configuration.
Let me know if this is a decent direction for you, and if you need more details to make it happen.