natter

package module
v0.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 22, 2019 License: MIT Imports: 27 Imported by: 0

README

natter: A peer-to-peer TCP port forwarding library using NAT traversal with QUIC

natter is a peer-to-peer TCP port forwarding library and command line tool. It connects two clients across the Internet, even if they are behind a NAT via UDP hole punching (NAT traversal) as per RFC 5128. Connections are brokered (but not relayed!) via a rendevous server ("broker"), and tunneled via the QUIC protocol.

The command line utility natter implements the broker and the client. The library is natively written in Go, but provides a C library (and can be used in C/C++).

Project Status

While the functionality is very close to what I want the library to be, the project and library API is a work in progress, mostly because this is my first Go project.

Building

You'll need Go 1.12+ and a protobuf compiler. Pretty much everything can be compiled with make:

Build:
  make all   - Build all deliverables
  make cmd   - Build the natter CLI tool & Go library
  make lib   - Build the natter C/C++ library
  make clean - Clean build folder

Examples:
  example_echo_[_run]      - Build/run echo client/server example
  example_simple_go[_run]  - Build/run simple Go example
  example_simple_c[_run]   - Build/run simple C example
  example_simple_cpp[_run] - Build/run simple C++ example

Examples

We provide a few code examples for Go, C and C++ in the example directory. Please note that for obvious reasons, all examples operate on localhost, but they could work across multiple systems.

You can also run examples via make.

TCP port forwarding using the natter CLI

Let's assume we have 3 machines, an Internet facing broker and two clients behind different NATs alice and bob.

First, start the broker on port 10000 (let's assume it listens on IP 1.2.3.4):

broker> natter -broker :10000

Then start client Bob, and listen for incoming connections:

bob> natter -name bob -broker 1.2.3.4:10000 -listen

And finally start client Alice, and forward local TCP connections on 8022 to bob's TCP port 22 (SSH). After that, Alice can connect to Bob's SSH server by connecting to localhost:8022:

alice> natter -name alice -broker 1.2.3.4:10000 8022:bob:22
alice> ssh -p 8022 root@localhost

STDIN-to-remote-command forwarding using the natter CLI

This is a fun example. It forwards the output of a local command to the input of a remote command, again, assuming that your broker is listening on 1.2.3.4:10000 and your remote client is Bob, like above:

alice> cat /etc/natter/natter.conf
ClientId alice
BrokerAddr 1.2.3.4:10000

alice> cat /dev/zero | natter :bob: sh -c 'cat > zeros'
Using the Go library

Here's the same example on localhost:

package main

import (
    "heckel.io/natter"
)

func main() {
	broker, _ := natter.NewBroker(&natter.Config{BrokerAddr: ":10000"})
	go broker.ListenAndServe()

	bob, _ := natter.NewClient(&natter.Config{ClientId: "bob", BrokerAddr: "localhost:10000"})
	bob.Listen()

	alice, _ := natter.NewClient(&natter.Config{ClientId: "alice", BrokerAddr: "localhost:10000"})
	alice.Forward(":8022", "bob", ":22", nil)

	select {}
}

Contributing

There is lots TODO. Feel free to help out via PRs of by opening issues.

Author

Philipp C. Heckel

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Broker

type Broker interface {
	ListenAndServe() error
}

func NewBroker

func NewBroker(config *Config) (Broker, error)

type Client

type Client interface {
	// Listen listens on a UDP/QUIC connection for incoming peer connections.
	Listen() error

	// Forward requests a forward connection to another client.
	//
	// localAddr is the local TCP [address]:port that shall be forwarded, e.g. 10.0.10.1:9000
	// If the address is omitted, all local addressed will be bound to, e.g. :9000
	// If it is empty, STDIN is read.
	//
	// target is the client identifier (see ClientId below) of the target client.
	// It cannot be empty.
	//
	// targetForwardAddr is the target TCP [address]:port on the target client, e.g. 192.168.1.2:22
	// If the address is omitted, localhost is used, e.g. :22 is equivalent to 127.0.0.1:22
	// If the address is a non-local address, traffic is forwarded to another host via the target machine,
	// e.g. google.com:80 will forward to Google's web server
	//
	// targetCommand can be used to execute a command on the target host and forward its STDIN,
	// e.g. []string { "zfs", "recv" } or []string{ "sh", "-c", "cat > hello.txt" }.
	// If targetCommand is set, targetForwardAddr is ignored.
	Forward(localAddr string, target string, targetForwardAddr string, targetCommand []string) (Forward, error)
}

Client represents a natter client. It can be used to listen for incoming connections and/or to open forwards to other clients.

func NewClient

func NewClient(config *Config) (Client, error)

NewClient creates a new client struct. It checks the configuration passed and returns an error if it is invalid.

type Config

type Config struct {
	// Identifier used to uniquely identify individual clients. It is important
	// and required to be able to connect to other clients. Example: myclient123
	ClientId string

	// Hostname and port of the broker. The broker is only used to connect
	// the two peers. Example: heckel.io:2568
	BrokerAddr string

	// Configure TLS for all TLS clients
	TLSClientConfig *tls.Config

	// Configure TLS between client and server
	TLSServerConfig *tls.Config

	// Override the QUIC configuration. This should not be necessary and
	// can break the functionality, if not done correctly. Ideally, you should
	// not change any settings here.
	QuicConfig *quic.Config
}

Config defines the configuration for a natter client or broker.

func LoadConfig

func LoadConfig(filename string) (*Config, error)

type Forward

type Forward interface {
	PeerUdpAddr() *net.UDPAddr
}

Directories

Path Synopsis
cmd
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL