-
Notifications
You must be signed in to change notification settings - Fork 84
Tutorial: TCP Forwarding
This tutorial shows you how to use Piko to forward TCP traffic to upstream listeners.
Piko supports proxying TCP traffic, though unlike HTTP it requires using either Piko forward or the Go SDK to map the desired local TCP port to the target endpoint (as there's no way to identify the target endpoint using raw TCP).
As an example, this runs an upstream Redis server then connects to it via Piko.
Start a Piko server node:
$ piko serverSee the server documentation for details.
Start the Redis server:
$ redis-serverThis will listen for connections on port 6379 by default.
Next run the Piko agent alongside the server to register a
Piko endpoint, my-redis-endpoint, and forward incoming TCP connections to
port 6379:
$ piko agent tcp my-redis-endpoint 6379To keep the tutorial simple, you can run the Redis server and Piko agent locally, though using Piko you could run them anywhere, as long as the agent can open an outbound connection to the Piko server. Such as they could be running behind a firewall or NAT blocking all incoming traffic.
Instead of using the Piko agent, you could also use the Go SDK:
upstream := &piko.Upstream{
// options...
}
forwarder, err := upstream.ListenAndForward(
context.Background(),
"my-redis-endpoint",
"localhost:6379",
); err != nil {
panic("listen: " + err.Error())
}
defer forwarder.Close()
if err := forwarder.Wait(); err != nil {
panic("forward: " + err.Error())
}Finally you can open a TCP connection to the endpoint my-redis-endpoint using
Piko forward.
piko forward listens on a local TCP port and forwards connections to the
configured endpoint. Run piko forward to listen on port 7000 and forward to
endpoint my-redis-endpoint:
$ piko forward tcp 7000 my-redis-endpointYou can then connect to port 7000 and your connection will be forwarded to
your registered upstream listener:
$ redis-cli -p 7000 PING
PONGAlternatively you can connect to Redis directly from your application using
the Go SDK. The Piko client has a
Dial(ctx context.Context, endpointID string) (net.Conn, error) method
that returns a net.Conn. Such as connecting with the
Redis Go client:
pikoDialer := &piko.Dialer{
// options...
}
// Use a custom dialer that connects to the upstream endpoint via Piko.
dialer := func(ctx context.Context, network, addr string) (net.Conn, error) {
return pikoDialer.Dial(ctx, addr)
}
// github.com/redis/go-redis/v9
rdb := redis.NewClient(&redis.Options{
Addr: "my-redis-endpoint",
Dialer: dialer,
})
if err := rdb.Ping(context.Background()).Err(); err != nil {
panic("ping: " + err.Error())
}