Skip to content

Commit 50fdeea

Browse files
committed
add a udp-offload example
1 parent 80fc872 commit 50fdeea

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ to be aware of.
5252
from OIDC/oAuth/etc.) to authenticate with OpenZIti
5353
- [`reflect`](example/reflect) - a low level network "echo" client and server example
5454
- [`simple-server`](example/simple-server) - a bare-bones HTTP server side only example
55+
- [`udp-offload`](example/udp-offload) - an example demonstrating how to work with an OpenZiti client and a UDP server
5556
- [`zcat`](example/zcat) - wrapping existing network tooling (netcat) to work over OpenZiti
5657
- [`zping`](example/zping) - wrapping existing network tooling (ping) to work over OpenZiti
5758

example/udp-offload/README.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Overview
2+
This example illustrates how to send data to, and receive data from a UDP server via OpenZiti.
3+
You will configure an OpenZiti overlay network and run a UDP server that will respond with whatever text it was sent.
4+
The response from the server will be read written to the console.
5+
6+
This example demonstrates a hybrid approach ZTAA --> ZTHA:
7+
* Dialing a service
8+
* Binding a service using a tunneler
9+
10+
## Requirements
11+
* OpenZiti CLI to create services and identities on the OpenZiti Network
12+
* an OpenZiti network. If you have one you'd like to use, great. The guide is written using the
13+
`ziti edge quickstart` command.
14+
* All commands are executed relative to the `example` folder
15+
16+
## Build the examples
17+
Refer to the [example README](../README.md) to build the SDK examples
18+
19+
## Run and Configure OpenZiti
20+
The README assumes the `ziti` CLI on your path. If not, supply the full path to the `ziti` executable. This command
21+
will start a ziti overlay network on ports 1280/3022 for use with the rest of the README. The default values will
22+
also be used for username and password. The router from the quickstart is the identity which will offload the OpenZiti
23+
traffic toward the UDP server
24+
25+
In a new terminal run the following command:
26+
```
27+
ziti edge quickstart
28+
```
29+
30+
To configure the overlay, you will need another terminal with `ziti` on the path. Now, add a service for the UDP
31+
server to be offloaded from the OpenZiti overlay as well as create the identity this example will use:
32+
```
33+
svc_name="udp.relay.example"
34+
edge_router_name="quickstart-router"
35+
ziti edge login localhost:1280 -u admin -p admin -y
36+
ziti edge create config ${svc_name}.hostv1 host.v1 '{"protocol":"udp", "address":"127.0.0.1","port":10001}'
37+
ziti edge create service ${svc_name} --configs "${svc_name}.hostv1"
38+
ziti edge create service-policy ${svc_name}.dial Dial --identity-roles "#${svc_name}.dialers" --service-roles "@${svc_name}"
39+
ziti edge create service-policy ${svc_name}.bind Bind --identity-roles "#${svc_name}.binders" --service-roles "@${svc_name}"
40+
41+
ziti edge create identity ${svc_name}.client -a ${svc_name}.dialers -o ${svc_name}.client.jwt
42+
ziti edge enroll --jwt ${svc_name}.client.jwt
43+
44+
ziti edge update identity ${edge_router_name} -a "${svc_name}.binders"
45+
ziti edge policy-advisor services -q
46+
```
47+
48+
## Run the UDP Server
49+
In the terminal from where you configured the OpenZiti overlay start the UDP server. Make sure you're in the
50+
`example` folder and run:
51+
```
52+
./build/udp-server
53+
```
54+
55+
You should now have a UDP server that is listening on port 10001 and will respond to UDP messages sent to it.
56+
```
57+
$ ./build/udp-server
58+
Listening on :10001
59+
```
60+
61+
## Run the Example
62+
Make sure the router (or identity) hosting the service establishes a terminator. Issue the following command and verify
63+
a terminator is listed as shown:
64+
```
65+
ziti edge list terminators 'service.name="udp.relay.example"'
66+
```
67+
68+
example output:
69+
```
70+
$ ziti edge list terminators 'service.name="udp.relay.example"'
71+
╭───────────────────────┬───────────────────┬───────────────────┬─────────┬───────────────────────┬──────────┬──────┬────────────┬──────────────╮
72+
│ ID │ SERVICE │ ROUTER │ BINDING │ ADDRESS │ IDENTITY │ COST │ PRECEDENCE │ DYNAMIC COST │
73+
├───────────────────────┼───────────────────┼───────────────────┼─────────┼───────────────────────┼──────────┼──────┼────────────┼──────────────┤
74+
│ sNVBPDKuI6q5I0f2PrEc6 │ udp.relay.example │ quickstart-router │ tunnel │ sNVBPDKuI6q5I0f2PrEc6 │ │ 0 │ default │ 0 │
75+
╰───────────────────────┴───────────────────┴───────────────────┴─────────┴───────────────────────┴──────────┴──────┴────────────┴──────────────╯
76+
results: 1-1 of 1
77+
```
78+
79+
With the terminator in place, run the sample
80+
```
81+
./build/udp-offload-client ./udp.relay.example.client.json
82+
```
83+
84+
example output:
85+
```
86+
$ ./build/udp-offload-client ./udp.relay.example.client.json
87+
INFO[0000] found service named: udp.relay.example
88+
INFO[0000] Connected to udp.relay.example successfully.
89+
INFO[0000] You may now type a line to be sent to the server (press enter to send)
90+
INFO[0000] The line will be sent to the reflect server and returned
91+
this is the udp example
92+
wrote 24 bytes
93+
Sent :this is the udp example
94+
Received: udp server echo: this is the udp example
95+
```
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"github.com/michaelquigley/pfxlog"
7+
"github.com/openziti/sdk-golang/ziti"
8+
"io"
9+
"os"
10+
)
11+
12+
var log = pfxlog.Logger()
13+
14+
func main() {
15+
serviceName := "udp.relay.example"
16+
17+
zitiCfg, err := ziti.NewConfigFromFile(os.Args[1])
18+
if err != nil {
19+
log.Fatalf("failed to load ziti configuration file: %v", err)
20+
}
21+
zitiCfg.ConfigTypes = []string{
22+
"ziti-tunneler-client.v1",
23+
}
24+
25+
ctx, err := ziti.NewContext(zitiCfg)
26+
if err != nil {
27+
fmt.Println(err)
28+
os.Exit(1)
29+
}
30+
31+
foundSvc, ok := ctx.GetService(serviceName)
32+
if !ok {
33+
fmt.Println("error when retrieving all the services for the provided config")
34+
os.Exit(1)
35+
}
36+
log.Infof("found service named: %s", *foundSvc.Name)
37+
38+
svc, err := ctx.Dial(serviceName) //dial the service using the given name
39+
if err != nil {
40+
fmt.Println(fmt.Sprintf("error when dialing service name %s. %v", serviceName, err))
41+
os.Exit(1)
42+
}
43+
44+
go ReadFromZiti(svc)
45+
log.Infof("Connected to %s successfully.", serviceName)
46+
log.Info("You may now type a line to be sent to the server (press enter to send)")
47+
log.Info("The line will be sent to the reflect server and returned")
48+
ReadFromConsole(svc)
49+
}
50+
51+
func ReadFromConsole(writer io.Writer) {
52+
conWrite := bufio.NewWriter(writer)
53+
reader := bufio.NewReader(os.Stdin)
54+
for {
55+
text, err := reader.ReadString('\n') //read a line from input
56+
if err != nil {
57+
fmt.Println(err)
58+
os.Exit(1)
59+
}
60+
bytesRead, err := conWrite.WriteString(text)
61+
_ = conWrite.Flush()
62+
if err != nil {
63+
fmt.Println(err)
64+
os.Exit(1)
65+
} else {
66+
fmt.Println("wrote", bytesRead, "bytes")
67+
}
68+
fmt.Print("Sent :", text)
69+
}
70+
}
71+
72+
func ReadFromZiti(reader io.Reader) {
73+
conRead := bufio.NewReader(reader)
74+
for {
75+
read, err := conRead.ReadString('\n')
76+
if err != nil {
77+
fmt.Println(err)
78+
os.Exit(1)
79+
} else {
80+
fmt.Print("Received: ", read)
81+
}
82+
}
83+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net"
6+
"os"
7+
)
8+
9+
func main() {
10+
addr := ":10001"
11+
conn, err := net.ListenPacket("udp", addr)
12+
if err != nil {
13+
fmt.Println(err)
14+
os.Exit(1)
15+
}
16+
defer conn.Close()
17+
fmt.Printf("Listening on %s\n", addr)
18+
19+
buf := make([]byte, 1024)
20+
for {
21+
n, remoteAddr, err := conn.ReadFrom(buf)
22+
if err != nil {
23+
fmt.Println("Error reading:", err)
24+
continue
25+
}
26+
27+
fmt.Printf("%s sent: %s\n", remoteAddr, string(buf[:n-1]))
28+
29+
_, err = conn.WriteTo([]byte("udp server echo: "), remoteAddr)
30+
if err != nil {
31+
fmt.Println("Error writing:", err)
32+
}
33+
_, err = conn.WriteTo(buf[:n], remoteAddr)
34+
if err != nil {
35+
fmt.Println("Error writing:", err)
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)