VPN Piercer Protocol
Goal
Protocol Goal
Equipment
Typically a pair of computers (initially Beaglebone Black boards in sturdy cases) will be given to the customer to put on their local network which has access to their VPN. They will then pick a pair of consecutive ports on a public IP address, and set up their firewall to forward these ports over to the computers. (This is used for failover in case one of the computers fails.) They then enter this information into Command Center and can then add units on their VPN to their command center account.
Protocol
This protocol is an encrypted protocol which multiplexes access to units behind a VPN over a single port. It runs over TCP/IP, or some other sequenced, reliable communications method which makes the guarantees of TCP.
Handshake / Authentication
The VPN piercer listens for incoming connections from SolarNet on port 1039. The protocol begins with a simple unencrypted handshake that sets up the encryption, after which all communications are encrypted.
Upon connection, SolarNet specifies the protocol version to be used as a simple ASCII string terminated by a newline "\n" character. Currently, the only version of this protocol is "solartech3".
The VPN Piercer then response with a 16 byte initialization vector. From this point on, all communications, in both directions, are encrypted using AES in the cipher mode corresponding to the Java cipher mode "AES/CFB8/NoPadding", with the specified initialization vector. The key is pre-shared.
The SolarNet then sends the string, "Friends, Romans, Countrymen: lend me your ears" (there is no newline or other terminating character). If the VPN Piercer is able to decrypt this string, it replies, "I come not to praise Caesar but to bury him" and proceeds to normal operation. If it is not able to properly decrypt this string, it sends the string, "ave atque vale" and then drops the connection.
Normal Operation
Normal operation is very simple, consisting only of six packets, three of which are IPv6 versions of the other packets. All packets have this initial structure:
[byte] packet type
[short] length
[length] ASCII address of unit on the VPN
Addresses are any valid ASCII string that can be passed to getaddrinfo(). Note that addresses must end with :port. All multi-byte types are big-endian encoded unless otherwise specified. the String type corresponds to an unsigned short followed by that many bytes of string data, roughly what you get from DataOutput.writeUTF(), except ASCII.
The packets are:
Connection Initiation Packet
Size |
Type |
Value |
Description |
1 |
unsigned byte |
0x01 |
Packet Type |
2-65535 |
JString |
|
address of the unit on the VPN |
Connection Close Packet
Size |
Type |
Value |
Description |
1 |
unsigned byte |
2 |
Packet Type |
2-65535 |
JString |
|
address of the unit on the VPN |
Data Payload Packet
Size |
Type |
Value |
Description |
1 |
unsigned byte |
3 |
Packet Type |
2-65535 |
JString |
|
address of the unit on the VPN |
4 |
u32 |
|
length the size of the data payload |
length |
bytes |
|
the data payload |
CYA packet
Size |
Type |
Value |
Description |
1 |
unsigned byte |
4 |
Packet Type |
4 |
unsigned int |
|
length |
length |
|
|
an ascii string which specifies the path of an executable to exec() with stdin and stdout dup'd from this network connection. |
A packet meant to enable us to recover in dire circumstances. Not for normal use.
|
Error Packet
Size |
Type |
Value |
Description |
1 |
unsigned byte |
5 |
Packet Type |
1 |
unsigned byte |
|
error code |
2-65535 |
JString |
|
address |
2-65535 |
JString |
|
description of the error |
Keep-Alive Packet
Size |
Type |
Value |
Description |
1 |
unsigned byte |
6 |
Packet Type |
No response is expected, this packet is just used to keep connections active so firewalls don't kill them.
|
Listen Request Packet
Size |
Type |
Value |
Description |
2-65,537 |
JString |
|
Address. |