/ratnet

Ratnet is a prototype anonymity network for mesh routing and embedded scenarios.

Primary LanguageGoGNU General Public License v3.0GPL-3.0

What is Ratnet?

Ratnet is a library that allows applications to communicate using an onion-routed and flood-routed message bus. All communications are encrypted end-to-end by the library itself.

Ratnet is completely modular, meaning that the interactions of all significant components of the system are defined with interfaces, and are therefore interchangeable. Network transports, cryptosystems, connection policies, and the ratnet nodes themselves can all be customized and swapped around dynamically.

The Ratnet library provides two working implementations for each of these interfaces:

It's also easy to implement your own replacement for any or all of these components. Multiple transport modules can be used at once, and different cryptosystems can be used for the Onion-routing and for the content encryption, if desired.

Ratnet provides input and output channels for your application to send and receive binary messages in clear text, making it very easy to interact with.

What's a Connection Policy?

You caught me, I made that term up. In ratnet, Transports are responsible for physically making and receiving connections and that's it. Nodes are basically message queues with some key management and special knowledge about when to encrypt things (and the Cryptosystem is the method they would use to do that). But none of those things actually starts a connection and moves the data around. That is the responsibility of the Connection Policy. Think of it as a script that controls a Node and any number of different Transports.

We provide two very simple connection policies:

  1. Server - This just opens up a port and listens on it.
  2. Polling - After a delay, this will connect to every Peer and exchange messages.

In real-world usage, you're very likely to want to implement your own version of Polling (via the Policy interface). We will be doing a lot more development and experimentation with new policies (and transports!) in the future.

Examples

RatNet Shell Example

There is a standalone example application specifically designed to showcase the relationship between common use-cases and the Ratnet API available here.

Fully Working IRC-like Demo

Hushcom is a fully working demo app that implements IRC-like chat functionality with a client and a server.

The hushcom client application is a good reference for how to set up a client using the Poll connection policy.

The hushcomd server application is a good reference for how to set up a server using the Server connection policy.

Making a Node

Make a QL-Database-Backed Node, which saves states to disk:

	// QLDB Node Mode
	node := qldb.New(new(ecc.KeyPair), new(ecc.KeyPair))
	node.BootstrapDB(dbFile)

Or, make a RAM-Only Node, which won't write anything to the disk:

	// RamNode Mode:
	node := ram.New(new(ecc.KeyPair), new(ecc.KeyPair))

The KeyPairs passed in as arguments are just used to determine which cryptosystem should be used for the Onion-Routing (first argument) and for the Content Encryption (second argument). There is no requirement that the routing encryption be the same as the content encryption. It's easy to use RSA for content and ECC for routing, for example, just change the second argument above to rsa.KeyPair.

Setup Transports and Policies

	transportPublic := https.New("cert.pem", "key.pem", node, true)
	transportAdmin := https.New("cert.pem", "key.pem", node, true)
	node.SetPolicy(
		policy.NewServer(transportPublic, listenPublic, false),
		policy.NewServer(transportAdmin, listenAdmin, true))

	log.Println("Public Server starting: ", listenPublic)
	log.Println("Control Server starting: ", listenAdmin)

	node.Start()

Handle messages coming from the network

	go func() {
		for {
			msg := <-node.Out()
			if err := HandleMsg(msg); err != nil {
				log.Println(err.Error())
			}
		}
	}()

Send messages to the network

Blocking Send:

	message := api.Msg{Name: "destname1", IsChan: false}
	message.Content = bytes.NewBufferString(testMessage1)
	node.In() <- message

Non-Blocking Send:

        select {
		case node.In() <- message:
			//fmt.Println("sent message", msg)
		default:
			//fmt.Println("no message sent")
		}	

Additional Documentation

  • Overview Slide Deck from Toorcamp 2016 here.
  • API Docs are available here.

Related Projects

#Authors and Contributors