Zssh service hosting

Any number of Ziti identities can host the zssh service, correct? Then, the zssh client can login to a particular SSH server by specifying the name of the Ziti identity that is hosting the service on that particular device?


Any identity configured to ‘host’ a zssh service - can host it. Yes. zssh relies on a relatively new feature of ziti called an “addressable terminator”. An addressable terminator requires an identity be provided the ability to ‘bind’ the service.

Using the ziti cli that might be accomplished by something like:

ziti edge create config zssh-server host.v1 '{"protocol":"tcp", "address":"","port":22, "listenOptions": {"bindUsingEdgeIdentity":true} }'
ziti edge create service-policy bind-all Bind --service-roles '#zssh' --identity-roles '#zsshServerEndpoints'

now any endpoint with the zsshServerEndpoints attribute shoudl be able to ‘host’ ssh via zssh. Does that make sense?

It almost makes sense. Clarification: I see you’re creating a hosting config named “zssh-server” with listenOptions.bindUsingEdgeIdentity: true, and a bind SP named “bind-all” to select identities with #zsshServerEndpoints for binding services with #zssh. I’m not sure what the difference is if listenOptions.bindUsingEdgeIdentity is false, though. I think false is the default, but how is the service bound if not by Edge identity?

bindUsingEdgeIdentity flag is the basis of addressable terminators. if you set it to false - you will need to make a service for each identity you want to host an ssh service via zssh. You can opt instead to use the built-in variable of tunneler_id.name like this if you don’t want to use bindUsingEdgeIdentity (this is semantically equivalent to the previous example:

ziti edge controller create config zssh-server host.v1 '{"protocol":"tcp", "address":"","port":22, "listenOptions": {"identity":"$tunneler_id.name"} }'

Also - if you don’t use an addressable terminator - i would not expect zssh to ‘work’… I didn’t test it that way for sure

Now I think my question is really “How do addressable terminators work?”, using a zssh service as an example.

I think the goal of addressable terminators is to enable a client to access a particular server instance of a service hosted by any one of many Ziti identities that have permission to bind the same Ziti service. Put another way, to make it unnecessary to create many Ziti services for which the configuration is identical and are hosted by many identities in the same way.

With that goal in mind, what is the meaning of bindUsingEdgeIdentity: false? I think that’s the default, and I took your meaning that when false we’re no longer using addressable terminators, and so there’s no way for an edge client to override the load balancing algorithm that determines which hosting identity will fulfill a particular connection request.

Assuming all of that is accurate, I’m only stuck on the name of the property and understanding precisely what it means to “bind using edge identity”. Specifically, what’s the alternative to binding with an edge identity? Would that be binding by the intercept/packet destination?

Reference: Ziti Services | Ziti

When you bind, you can set bindUsingEdgeIdentity=true to use the edge identity as the terminator identity. However, if you set that to false you can use something else as the identity. For example, in a voip use case your identity may my-laptop, but you want your terminator identity to be 555-555-5555.

In the SSH use case maybe your edge identity is server1 but you want the terminator identity to be

As an aside, you can have multiple terminators with the same identity. For example, a hosting tunneler or sdk client may connect to multiple edge routers. In this case there would be one terminator for each router and they would all have the same terminator identity. Then when a client connected to the service and used that terminator identity, the controller would pick from the terminators with that identity.

Thanks @dovholuknf and @plorenz for explaining that. Now I see what assumptions zssh is making in order to map a Ziti identity name to an addressable terminator. Importantly, that there’s a hosting config with bindUsingEdgeIdentity: true which means the identifier of the terminator is the binding identity.

Do terminators really have identities in the same sense that Edge SDKs have identities i.e. user certificates backed by a private key? It sounds like terminators might rather be known by “identifiers”.

Terminators do not ‘have’ identities. Terminators are terminated ‘at’ or ‘by’ a given identity. All ‘terminator’ means is “send this traffic to this identity”. Once at that identity - the application using that identity decides ‘what’ to do with the traffic.

Take a tunneling app (mac, windows, whatever) with an identity called “identity-host”. If you have that identity ‘host’ a service - a terminator is created for that identity/service combo. Now some other identity named “identity-client” uses the service and writes data to the service. Ziti routes the traffic ‘somewhere’. That ‘somewhere’ is determined by terminators, so ziti routes the traffic to “identity-host”.

Once at the identity - the identity decides ‘what’ to do with the traffic… For a tunneler app - it’d send the traffic off the ziti network to the final destination… Make sense?

1 Like

No, terminators don’t have identities, it’s just an identifier in the sense of a lookup key. If you’ve got a suggestion for a less confusing name, I’ve been looking for something. Maybe dialIdentifier?

I’d disagree with @dovholuknf that terminators are terminated at or by an identity. They can be, if they happen to be terminated by an SDK client, but they don’t need to be. You could use transport binding terminators which have no relation to an edge identity and provide some arbitrary string as the dial identifier.

1 Like

Thanks again. This is still coming into focus and both responses make sense.

First, a clarification about bindUsingEdgeIdentity: do I understand correctly this functions as a shorthand way of expressing precisely the following in the hosting config?

Is that the only implication of bindUsingEdgeIdentity: true? If so, then I think the most interesting property here is listenOptions. I expect I would infer a wealth of understanding about this config property by reading a few examples, if those are available somewhere.

If I understand correctly I don’t need to use bindUsingEdgeIdentity: true to enable addressable terminators. Rather, I could have any string value for .listenOptions.identity and the sending edge identity may “address” that value to ensure the traffic is algorithmically load balanced (according to configured terminator costs, weights, etc…) across all bindings that have that value.

@plorenz Re: naming
“Yes” to something like “identifier”, “destination”, “target”, or just “terminator” or “terminatorListener” or “terminatorAddress”, since that appears to be how this value is actually used. “identifier” is a mite subtle difference from “identity” but would have been sufficient for me.

that is correct. they do the same thing

Today I learned that "bindUsingEdgeIdentity": true also means that the terminator’s identifier can only be claimed by a single concurrent Edge identity. Multiple instances of Ziti Edge SDK could be using the same Edge identity and therefore all have a shared terminator, and this distinguishes "identity":"$tunneler_id.name" (synonym for "bindUsingEdgeIdentity": true) from other values for "identity" in that it guarantees uniqueness of the terminator. All other values imply at least the possibility of load-balancing connections across all identical terminator identifiers.