Documentation SSH Access with OpenZiti

I’m currently using OpenVPN to access SSH and am planning to transition to OpenZiti for this purpose. I’ve been exploring the OpenZiti documentation and came across two relevant guides:

  1. Set up tunneled SSH connection
  2. Create ssh Service

From these two guides, which one provides the proper steps for setting up SSH access via OpenZiti? And what is differences between these two approaches?

They are functionally equivalent from my quick review. The first link is better and more generic as it offloads traffic to 127.0.0.1. the second link uses another IP, but they both appear to be doing the same thing to me.

If you find you need to ssh to many, many machines there are other techniques you might want to use. If you have only a few machines to ssh into, either guide seems fine to me.

1 Like

I'm setting up a tunneled SSH connection following this documentation. I've reached the final step, where I verify the policy advisor output. However, I'm encountering an issue.

Expected Output

# ziti edge policy-advisor services |grep t2tssh  
OKAY : egress-tunnel (2) -> t2tssh (2) Common Routers: (2/2) Dial: N Bind: Y  
OKAY : ingress-tunnel (2) -> t2tssh (2) Common Routers: (2/2) Dial: Y Bind: N  

Actual Output

[root@almalinuxztna-174 ztna]# ziti edge policy-advisor services |grep mySSHservice  
ERROR: ingress-tunnel (0) -> mySSHservice (0) Common Routers: (0/0) Dial: Y Bind: N  
ERROR: egress-tunnel (0) -> mySSHservice (0) Common Routers: (0/0) Dial: N Bind: Y  

Current Setup

I have only one router configured. Here is my router's config.yml:

v: 3

identity:
  cert:             "router.cert"
  server_cert:      "/var/lib/private/ziti-router/router.server.chain.cert"
  key:              "/var/lib/private/ziti-router/router.key"
  ca:               "/var/lib/private/ziti-router/router.cas"

ctrl:
  endpoint:             tls:ziti-internal-pki.telkomuniversity.ac.id:1280

link:
  dialers:
    - binding: transport
  listeners:
    - binding:          transport
      bind:             tls:0.0.0.0:3022
      advertise:        tls:ziti-router:3022
      options:
        outQueueSize:   4

listeners:
  - binding: edge
    address: tls:0.0.0.0:3022
    options:
      advertise: ziti-router:3022
      connectTimeoutMs: 5000
      getSessionTimeout: 60
  - binding: tunnel
    options:
      mode: host #tproxy|host

edge:
  csr:
    country: US
    province: NC
    locality: Charlotte
    organization: NetFoundry
    organizationalUnit: Ziti
    sans:
      dns:
        - localhost
        - ziti-router
        - almalinuxztna-174
      ip:
        - "127.0.0.1"
        - "::1"

forwarder:
  latencyProbeInterval: 0
  xgressDialQueueLength: 1000
  xgressDialWorkerCount: 128
  linkDialQueueLength: 1000
  linkDialWorkerCount: 32

The documentation mentions that a "pub-er" (public edge router) is required. Does this mean I need to create a new public router, or can I modify the existing router's configuration to act as public?

Link Listener indicates that this is a router that can accept link connections from other routers as long as this can reached ziti-router:3022 from those routers.

Also for clients/sdks, the edge section indicates that it listens for connections from clients/sdks as long as clients can reach ziti-router:3022

  - binding: edge
    address: tls:0.0.0.0:3022
    options:
      advertise: ziti-router:3022

Ok, I understand that the link listener in my current router configuration allows it to accept connections from other routers at ziti-router:3022, and the edge listener enables client/SDK connections at the same address.

But the error i get is the same, I've reconfigured everything and followed all this documentation, but there are still no common routers connecting my service (t2tssh). When I checked the policy advisor, the result was as follows:

[root@almalinuxztna-174 identities]# ziti edge policy-advisor services |grep t2tssh
ERROR: client1 (1) -> t2tssh (0) Common Routers: (0/0) Dial: Y Bind: N
ERROR: client2 (1) -> t2tssh (0) Common Routers: (0/0) Dial: Y Bind: N
ERROR: almalinux (1) -> t2tssh (0) Common Routers: (0/0) Dial: N Bind: Y

Current Configuration: Here's my current setup

  1. Edge Router Status:
╭────────────┬─────────────┬────────┬───────────────┬──────┬────────────╮
│ ID         │ NAME        │ ONLINE │ ALLOW TRANSIT │ COST │ ATTRIBUTES │
├────────────┼─────────────┼────────┼───────────────┼──────┼────────────┤
│ yfxV6h9nKG │ ziti-router │ true   │ true          │    0 │ public     │
╰────────────┴─────────────┴────────┴───────────────┴──────┴────────────╯
  1. Service Configuration:
╭────────────────────────┬────────┬────────────┬─────────────────────┬────────────╮
│ ID                     │ NAME   │ ENCRYPTION │ TERMINATOR STRATEGY │ ATTRIBUTES │
├────────────────────────┼────────┼────────────┼─────────────────────┼────────────┤
│ 6hCD3uf0s79zGRE0CHVHAy │ t2tssh │ true       │ smartrouting        │            │
╰────────────────────────┴────────┴────────────┴─────────────────────┴────────────╯
  1. Service Policies:
╭────────────────────────┬────────────────────┬──────────┬───────────────┬───────────────────┬─────────────────────╮
│ ID                     │ NAME               │ SEMANTIC │ SERVICE ROLES │ IDENTITY ROLES    │ POSTURE CHECK ROLES │
├────────────────────────┼────────────────────┼──────────┼───────────────┼───────────────────┼─────────────────────┤
│ 5sinP7RfWnKWk7604lIm82 │ t2tssh-dial-policy │ AllOf    │ @t2tssh       │ @client1 @client2 │                     │
│ 7bcX0EcvQAYepJZNoPufJk │ t2tssh-bind-policy │ AllOf    │ @t2tssh       │ @almalinux        │                     │
╰────────────────────────┴────────────────────┴──────────┴───────────────┴───────────────────┴─────────────────────╯

Issue: While running the tunneler egress (in my case, almalinux), the following error appears:

WARN ziti-sdk:bind.c:226 session_cb() server[0.0] failed to get session for service[t2tssh]: -17/NO_EDGE_ROUTERS_AVAILABLE

The tunnel initially connects to the controller and recognizes the edge router, but then fails with the NO_EDGE_ROUTERS_AVAILABLE error repeatedly.

Questions:

  1. Is there a misconfiguration in my setup?
  2. What could be causing the NO_EDGE_ROUTERS_AVAILABLE error despite the edge router showing as online?

The problem seems to me to be a missing edge router policy. When you see "Common Routers: (0/0)" that means the identity has edge routers online that it's allowed to connect to. That's the 0/0. == online routers the can connect to/total routers the identity is allowed to connect to

You should:

  • list your identities, find your edge router identity, and client identities and inspect the attributes it has assigned to them
  • list your edge-router-policies and ensure there's a policy granting access those identities to at least one router the identity can connect to

Hopeflly that makes sense? :slight_smile:

Thank you for your guidance! Based on your suggestion, I reviewed my configurations and found the following details:

  1. Identities:
╭────────────┬───────────────┬─────────┬────────────┬─────────────╮
│ ID         │ NAME          │ TYPE    │ ATTRIBUTES │ AUTH-POLICY │
├────────────┼───────────────┼─────────┼────────────┼─────────────┤
│ 4R4tI4KEkl │ client1       │ Default │            │ Default     │
│ 7YDtI4KxIl │ client2       │ Default │            │ Default     │
│ 9yyutS.N8  │ Default Admin │ Default │            │ Default     │
│ F1cUIX8EIl │ almalinux     │ Default │            │ Default     │
│ yfxV6h9nKG │ ziti-router   │ Router  │            │ Default     │
╰────────────┴───────────────┴─────────┴────────────┴─────────────╯
  1. Edge Routers:
╭────────────┬─────────────┬────────┬───────────────┬──────┬────────────╮
│ ID         │ NAME        │ ONLINE │ ALLOW TRANSIT │ COST │ ATTRIBUTES │
├────────────┼─────────────┼────────┼───────────────┼──────┼────────────┤
│ yfxV6h9nKG │ ziti-router │ true   │ true          │    0 │ public     │
╰────────────┴─────────────┴────────┴───────────────┴──────┴────────────╯
  1. Edge Router Policies:
╭────────────────────────┬───────────────────────────────┬───────────────────┬────────────────╮
│ ID                     │ NAME                          │ EDGE ROUTER ROLES │ IDENTITY ROLES │
├────────────────────────┼───────────────────────────────┼───────────────────┼────────────────┤
│ 5gnb2ftjidEnN7SwbN2Cvq │ allEdgeRouters                │ #public           │ #all           │
│ yfxV6h9nKG             │ edge-router-yfxV6h9nKG-system │ @ziti-router      │ @ziti-router   │
╰────────────────────────┴───────────────────────────────┴───────────────────┴────────────────╯

From what I can see, the allEdgeRouters policy uses #public for the edge router roles and #all for identity roles. My assumption was that this should work for my setup, as the ziti-router has the attribute public. However, client1 and client2 do not have any attributes defined, and this might be the cause of the issue.

Could you confirm if my assumption is correct? If so, would adding the #public attribute to client1 and client2 resolve the issue? Alternatively, should I create a new edge router policy that explicitly links these clients to the ziti-router?

No. The #all attribute is special. It matches any entity. The policy will match your two identities, adding #public will not affect any change.

No, you shouldn't need to do this either.

Can you list your service edge router policies too, please?

Everything you showed me seems right to me, let's verify your SERPs too.

here is the output:

[root@almalinuxztna-174 ztna]# ziti edge list service-edge-router-policies
╭────┬──────┬───────────────┬───────────────────╮
│ ID │ NAME │ SERVICE ROLES │ EDGE ROUTER ROLES │
├────┼──────┼───────────────┼───────────────────┤
╰────┴──────┴───────────────┴───────────────────╯
results: none

As you can see, the output is empty because I did not configure any Service Edge Router Policies (SERPs). The documentation I followed did not include any steps or guidance for setting up SERPs, so I assumed they were not required.

Do you think the absence of a Service Edge Router Policy could be causing the issue? If so, could you suggest how to configure one properly for this scenario?

Yes it definitely does. I would recommend you create an #all/#all service policy.

ziti edge create service-edge-router-policy serp-all-all --service-roles '#all' --edge-router-roles '#all'

I tried the command you provided, and it worked perfectly! Here's the output:

[root@almalinuxztna-174 identities]# ziti edge create service-edge-router-policy serp-all-all --service-roles '#all' --edge-router-roles '#all'  
New service edge router policy serp-all-all created with id: 7mwH5HYjAhuetxy4qqjjYo  

[root@almalinuxztna-174 identities]# ziti edge policy-advisor services | grep t2tssh  
OKAY : almalinux (1) -> t2tssh (1) Common Routers: (1/1) Dial: N Bind: Y  
OKAY : client3 (1) -> t2tssh (1) Common Routers: (1/1) Dial: Y Bind: N  
OKAY : client1 (1) -> t2tssh (1) Common Routers: (1/1) Dial: Y Bind: N  
OKAY : client2 (1) -> t2tssh (1) Common Routers: (1/1) Dial: Y Bind: N  

However, when I tested the connection, I encountered a connection refused error. You can see the result in the attached image. I suspect the problem might be related to my router.

What makes you think that? Would you log into the ziti CLI, and after logging in, run

ziti ops verify-traffic

If it returns no errors, your network should be established correctly.

Also look at the logs from the ziti desktop edge and see if there's anything in there. In general our logs do a good job of pointing out issues

I tried running the ziti ops verify-traffic command, but it doesn't seem to work on my setup. Here's the output I got:

[root@almalinuxztna-174 ztna]# ziti ops verify-traffic
Various utilities useful when operating a Ziti network

Usage:
  ziti ops [command]

Available Commands:
  db          Interact with Ziti database files
  log-format  Transform pfxlog output into a human readable format
  unwrap      Unwrap a Ziti Identity file into its separate pieces (supports PEM only)

Flags:
  -h, --help   help for ops

Use "ziti ops [command] --help" for more information about a command.

It seems that my current Ziti CLI doesn't support this command. For reference, I'm using version v1.1.7. Could this issue be because I'm running an outdated version of Ziti?

As for why I think the problem might be related to my router, it comes from the statement in the documentation I was following:
"On the IDENTITIES screen, you will see an identity match local-er router name. If you perform the provisioning correctly, you should not see an identity name pub-er."

In my case, the ziti-router does appear in the list of identities, and I suspect this might be because tunneling is enabled on my router. Could it be that this is causing the problem?

The ziti CLI command can be run from anywhere. If you have another computer, you can run a newer version from there (the command is backward compatible). Or you could run a ziti-cli interactively with something like:

docker run -it --rm --entrypoint "" openziti/ziti-cli:1.2.1 bash

Once inside the docker bash shell, ziti login and run ziti ops there.

I suspect one or more advertised addresses is incorrect.

No, you want tunneling enabled

Enter username: admin
Enter password:
Token: 9bdcee66-7c36-4d29-a0e5-1b241054b8d5
Saving identity 'default' to /home/ziggy/.config/ziti/ziti-cli.json
INFO    generating P-384 EC key
INFO    generating P-384 EC key
INFO    waiting 10s for terminator for service: 2024-11-26-1319.verify-traffic
INFO    successfully bound service: 2024-11-26-1319.verify-traffic.
INFO    Server is listening for a connection and will exit when one is received.
INFO    new service session                           session token=a7120708-fc2e-4e6b-9e16-62df5c7baa08
FATAL   terminator not found for service: 2024-11-26-1319.verify-traffic

This is the output I received when running ziti ops verify-traffic. It seems that the terminator for the service 2024-11-26-1319.verify-traffic could not be found.

Could this indicate that either the router or the controller has an incorrect advertised address? If so, I will look into verifying their configurations.

Make sure the identity hosting the service is online.
Make sure the identity can access to a Edge router via edge's advertised address.
Make sure there is a public link listener. (you can check this by checking the ziti fabric links, there should be a link between the link listener to the edge router)

It might, yes.

There is another command to run, I should have mentioned it that should check the config files. Try running a router check and controller check.

Router example:

ziti ops verify-network --router-config-file $PATH_TO_ROUTER_CONFIG

Controller example:

ziti ops verify-network --controller-config-file $PATH_TO_CONTROLLER_CONFIG

I ran the commands to verify the configurations for both the controller and router, as you suggested. Below are the outputs:

Controller Check Output

[root@d5bd6af94def ziti-controller]# ziti ops verify-network --controller-config-file /mnt/configs/ziti-controller/config.yml
INFO    Verifying controller config: /mnt/configs/ziti-controller/config.yml
INFO    controller advertise address at ziti-internal-pki.telkomuniversity.ac.id:1280 is available.
INFO    verifying 1 web entries
INFO    verifying 1 web bindPoints
INFO    web entry[client-management], bindPoint[0] address at ziti-internal-pki.telkomuniversity.ac.id:1280 is available.
INFO    web entry[client-management], bindPoint[0] is valid

INFO    All requested checks passed.

Router Check Output

[root@d5bd6af94def ziti-controller]# ziti ops verify-network --router-config-file /mnt/configs/ziti-router/config.yml
INFO    Verifying router config: /mnt/configs/ziti-router/config.yml
INFO    ctrl endpoint at ziti-internal-pki.telkomuniversity.ac.id:1280 is available.
INFO    verifying 1 web link listeners
INFO    link listener[0] at ziti-router.telkomuniversity.ac.id:3022 is available.
INFO    link listener[0] is valid
INFO    verifying 2 web edge listeners
INFO    listener binding[0] at ziti-router.telkomuniversity.ac.id:3022 is available.
INFO    listener binding[0] is valid
INFO    listener binding[1] has binding tunnel and doesn't need to be verified
INFO    listener binding[1] is valid

INFO    All requested checks passed.

Both checks passed without any errors or issues. It seems the advertised addresses and bindings are correctly configured. Please let me know if there’s anything else I should verify or if these results suggest the configuration is functioning as expected.

1. Ensure the identity hosting the service is online.
The identity hosting my service is running on an AlmaLinux server located in the data center. This server is always online and operational.

2. Ensure the identity can access an Edge Router via the router's advertised address.
The client identity (client2) can successfully reach the Edge Router (ziti-router.telkomuniversity.ac.id) via its advertised address. I verified this with the following ping test:

~ ❯ ping ziti-router.telkomuniversity.ac.id

Pinging ziti-router.telkomuniversity.ac.id [10.252.252.174] with 32 bytes of data:
Reply from 10.252.252.174: bytes=32 time=5ms TTL=60
Reply from 10.252.252.174: bytes=32 time=7ms TTL=60
Reply from 10.252.252.174: bytes=32 time=4ms TTL=60
Reply from 10.252.252.174: bytes=32 time=5ms TTL=60

Ping statistics for 10.252.252.174:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 4ms, Maximum = 7ms, Average = 5ms

This confirms the client can reach the Edge Router without issues.

3. Ensure there is a public link listener (check the Ziti fabric links).
I checked the public link listener using the ziti fabric list routers command. The output is as follows:

[root@almalinuxztna-174 ~]# ziti fabric list routers
╭───────────┬─────────────┬────────┬──────┬──────────────┬──────────┬───────────────────────┬────────────────────────────────────────────────╮
│ ID        │ NAME        │ ONLINE │ COST │ NO TRAVERSAL │ DISABLED │ VERSION               │ LISTENERS                                     │
├───────────┼─────────────┼────────┼──────┼──────────────┼──────────┼───────────────────────┼────────────────────────────────────────────────┤
│ jtGKEhO5R │ ziti-router │ true   │    0 │ false        │ false    │ v1.1.7 on linux/amd64 │ 1: tls:ziti-router.telkomuniversity.ac.id:3022 │
╰───────────┴─────────────┴────────┴──────┴──────────────┴──────────┴───────────────────────┴────────────────────────────────────────────────╯

Is this the expected configuration?

Your config seems ok it's unexpected to me that verify traffic would fail with a terminator related problem. You shouldn't move on to testing ssh before that is ready imo.

Could you add debug output to the verify traffic command please? Also, would you look in the logs if the controller and router looking for errors when the verify traffic command runs?

Sorry you're having this much trouble. :face_with_diagonal_mouth: