SAGIRI controller reference implementation
1 Racket bindings
sagiri-connect
sagiri-start-forward
sagiri-stop-forward
2 SAGIRI IPC specification
2.1 Overview
2.2 Daemon greeting format
2.3 Application request format
2.4 Daemon response format
6.3.90.900

SAGIRI controller reference implementation

1 Racket bindings

 (require sagiri-comm) package: sagiri-comm

sagiri-comm provides a convenient Racket interface to SAGIRI. It works by talking with a running SAGIRI instance on the local machine, so make sure that SAGIRI is running before calling the procedures exported by this module.

One thing to note is the URL format: URLs that are passed to "sagiri-connect" and returned from the other two functions are of the following format:

[   IP address   ] [               EdDSA Public key (32 bytes)                    ]

(###-###-###-###--)aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.edge.sagiri

When returning a hostname, this library will always include the IP address. It’s up to the application to strip the IP portion out if it wishes to before handing out the address to anybody.

Note: In practice, until SAGIRI’s onion-routing and DHT functionality is completed, the IP address will always be needed.

procedure

(sagiri-connect host port)  
input-port? output-port?
  host : string?
  port : exact-integer?
Connects to the SAGIRI address at host and on port port.

procedure

(sagiri-start-forward #:private-key priv-key 
  #:internal-port int-port 
  #:external-port ext-port) 
  
string? exact-integer?
  priv-key : bytes?
  int-port : exact-integer?
  ext-port : exact-integer?
Instructs SAGIRI to forward incoming requests on ext-port to int-port. The globally addressable hostname (including the IP!) will be returned.

procedure

(sagiri-stop-forward #:private-key priv-key    
  #:external-port ext-port)  boolean?
  priv-key : bytes?
  ext-port : exact-integer?
Instructs SAGIRI to stop forward incoming requests on ext-port.

2 SAGIRI IPC specification

2.1 Overview

This document details the binary inter-process communication protocol used to talk with the SAGIRI daemon. All numbers are encoded as big-endian, and all strings are assumed to be in UTF-8 format.

The protocol itself is similar in spirit to HTTP/1.0: it’s stateless, and is based on a single request/response on a TCP connection which is not kept alive. The process goes like this:

This document does not cover SOCKS5, which is used to connect to the actual remote hosts. The daemon will tell the application where to find the SOCKS5 server set up by SAGIRI; the application then connects to remote SAGIRI/Kiricom hosts by using the pseudo-hostname and port extracted from the sort of URL described at the beginning of the document. The SAGIRI SOCKS5 server, for obvious reasons, only supports TCP proxying, not port forwarding or UDP proxying.

(The reason why SOCKS5 is used to handle the forwarding part is to reduce complexity of the IPC protocol, and also to more easily enable SAGIRI client functionality in third-party applications which support SOCKS5, who can simply be passed the correct SOCKS5 address by a shim program that implements this protocol to discover the SOCKS5 address.)

2.2 Daemon greeting format

The daemon sends a greeting of the following format:

1 byte:  major version

1 byte:  minor version

1 byte:  patch

2 bytes: SOCKS5 port

For example, SAGIRI 0.1.1 with SOCKS5 listening on port localhost:20480 would send (bytes 0 1 1 80 0) (in Racket syntax) as the greeting.

2.3 Application request format

The application request goes like this:

1 byte:   request code

32 bytes: private key (Ed25519 format from libsodium)

2 bytes:  internal port

2 bytes:  external port

The request codes are 0xFF for NOOP, 0x00 for HOST, and 0x01 for STOP.

The no-op request means the client does not want a response. The connection is immediately closed after sending a request with the NOOP code. The other fields are ignored by the daemon.

The HOST code indicates that the application intends to host a service over SAGIRI. For example, if the application is a Web server listening on port 8080 and intends to offer SAGIRI access from the outside Internet on port 80, it would set the internal port to 80, the external port to 8080, and the private key to a value that should be unique for each service.

Note: Currently, SAGIRI’s onion-routing is not done, so this essentially acts only as a Kiricom provider.

The STOP code indicates that the application wants to stop hosting a service. The external port and private key identify the service that is to be stopped. The internal port field is actually ignored by the daemon.

2.4 Daemon response format

The daemon’s response goes like this:

1 byte:   response code

2 bytes:  length of message

variable: message string

The codes are 0xF0 for OKAY, and 0xF1 for NOPE.

The OKAY code denotes that the request has been fulfilled. If the request was a hosting request, then the message contains the globally routable pseudo-hostname:port URL (see beginning of this document).

The NOPE code denotes that the request cannot be fulfilled. A human-readable message denoting the nature of the error is put in message.