Hi all,
I would like to know if there is a way for OpenZiti to listen on a UDP port on a machine and automatically forward traffic to a predetermined service.
Right now for testing I use a bent-pipe program on a machine with a ziti tunneller to resolve the DNS and forward the traffic on, but I am searching for something more production-friendly.
Is there a way to have openziti listen on a bare UDP port and send the data into a service?
I have seen a solution in this forum thread: TCP-Proxying services into Openziti without DNS Intercept?, however, this appears firstly to be TCP only, and secondly, despite my best efforts I cannot get the router to listen on the specified port. I suspect this may be due to having only 1 router in my testing network.
Many thanks for your consideration.
Hello,
All of the OpenZiti tunnelers are able to intercept udp packets and associate the packet payload with an OpenZiti service. The exact intercept mechanism depends on which tunneler you are using, but they are all configured with an intercept.v1 document and the effect is the same as having a server socket listening on a specific port (although intercepts also let you accept connections from port ranges and/or entire subnets).
So my first question to you is do you really need a listening socket, or do you just want to get data from a udp client and send it somewhere else and aren't concerned with how that happens?
I'm also curious about the app that you're trying to tunnel. It's obviously UDP... Is it a client/server app where one side connects to the other (possibly bidirectional data flow once the connection is esablished), or do both sides of the connection initiate their own outbound connection?
Thanks
Our company makes custom devices for receiving telemetry data from race cars over mobile networks. There's lots of magic involved, but the upshot is that I have 2-4 intermittent UDP streams coming out of the device that all point at the same IP/port. As a proof-of-concept / immediate solution I just need to get OpenZiti to tunnel this data to a PC running our application, where the data is then deduplicated and sorted. This will hopefully replace a nasty and clunky VPN based solution some of our customers have to use.
It is currently just independent initiated UDP connections with not much real logic behind them at the moment. We do have normal, basic back and forth TCP with regular old servers for configuration data, licensing etc., which I'm leaving off the Ziti network. However the telemetry data stream is the unusual part - It's just a UDP firehose that arrives at the PC whether anything is ready or not. Our app listens out for it, and if it receives anything it tidies it up and sends it onwards for analysis. Similarly for return traffic, we don't always have it but when we do it is just UDP sent out to an IP address/port regardless of the state of the other end.
We do have a much more elegant client/server solution, where I think OpenZiti would integrate perfectly out of the box, but for various annoying reasons, we can't use it for everyone. I've been asked to get it working this way first before I can get the buy in to integrate it properly elsewhere.
Alright, I'm not sure how you plan to run your OpenZiti tunnelers. I see that you've set up your own controller and routers in another thread, so I'll assume those components are up and running.
You mention a PC, so I'll assume you'll be using Ziti Desktop Edge for Windows as your tunneler. You'll need a tunneler on each end of the connection btw. If you need to support a different OS we probably have a tunneler for it. The concepts are the same regardless of the OS though - basically you'll create an identity for each tunneler that you need and enroll it using the tunneler. The first step on the application hosts is to install the tunnelers and m are sure they are running. They won't do anything until we enroll the identities.
You set up the service and which identities can access it with your OpenZiti controller interface of choice. We have the ziti CLI and/or a web-based admin console which you may already be hosting from your controller. I'll assume the CLI for now because it's easier to describe in a post.
On your controller host
-
Log into the controller
ziti edge login
-
Create two identities - one to represent the car and another for the PC:
ziti edge create identity ferrari-f175 -o ferrari-f175.jwt -a telemetry-dialers
ziti edge create identity joes-pc -o joes-pc.jwt -a telemetry-binders
The -a
option specifies a "role" that we'll use to assign service permissions to the identities. We'll create the policies that refer to these roles shortly. I'm assuming from your overview that the car will initiate connections and the PC will accept them.
-
Create the service configurations - one to describe which connections are intercepted and another to specify how to complete the connection:
ziti edge create config telemetry-intercept intercept.v1 '{
"protocols": ["udp"],
"addresses": ["telemetry.ziti", "4.4.4.4"],
"portRanges":[{"low":2171,"high":2171}]
}'
ziti edge create config telemetry-host host.v1 '{
"protocol": "udp",
"address":"127.0.0.1",
"port":8080
}'
These configurations will let you intercept connections that are destined for port 8080 on hostname "telemetry.ziti" and/or ip "4.4.4.4". You probably want a different intercept address, I'm just pointing out that you can intercept connections to hostnames or IPs of your choice.
-
Create the service, using the configurations and attributes from the previous steps:
ziti edge create service telemetry -c telemetry-intercept,telemetry-host -a telemetry-dialers,telemetry-binders
-
Create service policies that control which identities can use the service:
ziti edge create service-policy telemetry-dial Dial --identity-roles telemetry-dialers --service-roles '@telemetry'`
ziti edge create service-policy telemetry-bind Bind --identity-roles telemetry-binders --service-roles '@telemetry'`
So identities with the "telemetry-dialers" role can initiate connections to the service, and those with the "telemetry-binders" role can accept (bind) connections.
On your edge hosts
Transfer the jwt files for the respective identities to the appropriate PC, and enroll the identies
Shortly after enrolling you should see the "telemetry" service in the Ziti Desktop Edge UI, and then you'll be off to the races!
1 Like
Alright, thanks for the great answer! Actually, this is really good to see everything I need at once.
I've got it working flawlessly with both IP addresses and ziti service names, but only when I am sending a dummy datastream outwards from from inside my test machine. When I test with a real device, all I can get is a UDP stream arriving on an external interface - so I think I will need a listening port after all. The device is a bit of a black box, so I can't put openziti at the point the stream is actually generated, which I imagine would be the ideal scenario.
I have tried setting the intercept IP to the IP of the interface that the data is arriving on, but that doesn't appear to work. Honestly, I think I've massively misunderstood the functionality of a tunneller somewhere along the line - it seems much more designed to get traffic from inside one machine to inside another, and not to listen to the outside like this.
For now, I have a method using ncat to just crudely turn the data around into the ziti network - which will let me continue my testing.
I'm not exactly sure what you mean by "udp stream arriving on an external interface". Can you elaborate?
The tunnelers can intercept connections from other hosts, but those other hosts will need to have a route (in the operating system's routing tables) to send the packets to the host that's running the tunneler.
I can set an IP Address / Port pair on the telemetry device for the UDP traffic to be sent to. If I program this to the IP of my test machine, then the packets will arrive there - but I can't get openziti to listen to this, even if I set it's IP address in my intercept config.
Thanks for the explanation. I have an idea about why it isn't working for you when you use the tunneler.
One difference between packets being picked up by a listening socket and packets being picked up by the tunneler is that the tunneler is using its own network interface (a so-called "tun" device) to read packets. When packets are being intercepted from local processes, the routes that are set up by the tunneler direct the packets to the tun interface.
When packets are coming from another host, the packet enters the tunneler host on the LAN interface. When the host has a listening socket for the packet's dst address:port, the operating system delivers the packet to that port. But when the packet is handled by a different network interface (as dictated by the routing tables), the operating system needs to forward the packet to the target network interface.
It's very common for the target interface to be connected to another network (such as an ISP or another switch, etc). The tunneler's tun device isn't connected to another IP network though - the tunneler is connected to the OpenZiti overlay network. So the tunneler "reads" packets from the tun device and uses it's own tcp/ip stack to extract the payloads which are written to ("forwarded") to their associated OpenZiti connections (as determined by the packet dst ip:port).
All of that is probably more than you wanted or needed to know. The important thing (I think) is that you'll need to enable packet forwarding to get the tunneler to intercept connections from remote hosts.
There are lots of articles out there that talk about enabling packet forwarding on Windows. this one seemed pretty succinct and complete to me (especially the second answer) since it pointed out how to enable forwarding only for selected interfaces vs all interfaces.