saltunnel - a cryptographically secure TCP tunnel



saltunnel client [--version] [-t <timeout>] [-m <maxconns>] -k <keyfile> <fromip>:<fromport> <toip>:<toport>

saltunnel server [--version] [-t <timeout>] [-m <maxconns>] -k <keyfile> <fromip>:<fromport> <toip>:<toport>

saltunnel key generate <keyfile>

saltunnel key import <keyfile>

saltunnel key export <keyfile>



The saltunnel client and saltunnel server commands are used in conjunction to establish a cryptographically secure TCP tunnel using symmetric key cryptography. This allows one to augment a normally-insecure TCP session with state-of-the-art security, with minimal hassle and minimal impact on performance.

The saltunnel key generate command generates a new shared long-term key and places it into a file. This command is a simply convenience function; this step could be done many other ways. For example, it is equivalent to "cat /dev/urandom | head -c 32 > keyfile".

Another way to create a key is with saltunnel key import, which, instead of generating a random key, reads a 64-character hexadecimal string from standard input, and writes the 32-byte binary value of this string to <keyfile>.

The saltunnel key export command reads a 32-byte <keyfile> and outputs its value in hexadecimal.

The following options are available:


Display version information.

    -t <timeout

Set a connection timeout (in seconds) for all outgoing TCP connections. (Optional; defaults to system default.)

    -m <maxconns>

Set a limit on the maximum number of concurrent TCP connections. (Optional; defaults to 100.)

    -k <keyfile>

Specify the path to the shared long-term key file. This file must be 32-bytes, and should be derived from a cryptographically secure random number generator.


The ip:port pair identifying the source address to listen for incoming TCP connections. (For saltunnel client this is data arrives unencrypted; for saltunnel server it arrives encrypted.)


The ip:port pair identifying the destination address to connect to for outgoing (encrypted) TCP connections. (For saltunnel client this is data is sent encrypted; for saltunnel server it is sent unencrypted.)



Imagine that you have two computers on two different continents--ComputerA and ComputerB--and would like for some program on ComputerA to establish a TCP session with some port ComputerB, but the protocol which this program uses is too insecure to use comfortably over a network. You can use saltunnel to easily solve this problem. Going further, imagine both of the countries your computers are in have border firewalls which detect and block common encryption protocols: saltunnel would help here, too, as the saltunnel protocol is difficult to detect.

First, you will need to generate a shared long-term key and (somehow) copy it to both computers; saltunnel requires 32-byte keys, which should be generated from a cryptographically secure random number generator.

So, on ComputerA, generate a key:

mkdir ~/.saltunnel
saltunnel key generate ~/.saltunnel/k

You'll then need to securely copy this to ComputerB. Doing this step securely is critical, but saltunnel isn't designed to help with this, so we will hand-wave this step. If you're okay with manually reading and re-typing the hexadecimal value of the key, you may run saltunnel key export on one computer and saltunnel key import on the other.

Next, you can set up the client-side of a tunnel. On ComputerA, you run:

saltunnel client -k ~/.saltunnel/k computer-a:30000

(Where 'computer-a' is the hostname or IP address of ComputerA.)

After running this, any TCP connections made from ComputerA to IP address, port 8080, will be encrypted and forwarded to ComputerB's port 30000.

But, you'll still need to set up the server-side of the tunnel. On ComputerB, you run:

saltunnel server -k ~/.saltunnel/k

After running this, any TCP connections incoming to ComputerB on port 30000 will be decrypted and forwarded to IP address, port 8080.

Now that both ends of the tunnel are initialized, ComputerA can securely communicate with ComputerB. If ComputerA now makes a TCP connection to its own port 8080, the behavior should be as if it is connecting directly to ComputerB's local port 8080.



Normally, saltunnel client and saltunnel server do not exit. (They will both continue to listen for connections until terminated.) All other commands will exit with 0 on success.

If invalid arguments are given, saltunnel will exit with code 2.

If an error occurs, saltunnel will exit with code 1.  


The saltunnel programs and the protocol used by saltunnel provide the following features:

Confidentiality and Integrity

The saltunnel protocol uses salsa20+poly1305 as its primary symmetric cipher, which provides confidentiality and integrity.

Denial-of-Service Protection

saltunnel servers have denial-of-service protection; about as much as is possible for a TCP server. An attacker attempting to overload a saltunnel server instance will find that the most cost-effective attacks are (probably) reduced to exploiting the well-known shortcomings of TCP itself.

Forward Secrecy

Forward secrecy ensures that it is impossible to retroactively decrypt data from a past connection, even if, at some point in the future, the long-term shared symmetric key is compromised. Despite using a symmetric-key protocol for its initiating handshake, saltunnel performs a Diffie-Hellman exchange to obtain an ephemeral session key, which is then used for the remainder of the TCP connection. When a connection terminates, the ephemeral keys which were used to encrypt that connection are permanently erased.

Key/Data Safety

Both programs use mlock to pin all keys and plaintext to memory, so that they are never swapped to disk. Additionally, as soon as each connection is closed, that connection's keys and plaintext are immediately erased from memory (except when the program is terminated via interrupt, unfortunately). This (almost) provides forward secrecy even in the face of disk forensics (assuming your RLIMIT_MEMLOCK is not too low) or cold-boot attacks (assuming you don't terminate the program or enter sleep mode while a connection is active).

Message-Length Quantization

Data is sent over the network in chunks of 512 bytes. If one computer sends, for example, 7 bytes, it will arrive as a 512-byte chunk on the other computer. This greatly reduces the amount of information which can be inferred from network analysis.

Post-Quantum Security

The protocol is also immune to quantum computing attacks, because its security relies on 256-bit symmetric-key cryptography. (Of which, the best attack known to be possible by quantum computers is Grover's algorithm, which reduces the security level to 128 bits.) The catch, of course, is that as a prerequisite to using saltunnel, the key must be (somehow) shared securely between parties---a process which is famously difficult to do, especially in a post-quantum-secure way.

Uniform Random TCP Data

An attacker who eavesdrops on a saltunnel connection will only see a TCP connection with same-sized chunks of uniform random data. There are no protocol header magic bytes or patterns within any given chunk of data. This complicates an attacker's ability to track/fingerprint users, and makes it difficult to write analysis tools that detect/censor the saltunnel protocol. (Though, patterns may still be available through timing analysis.)


For more information, see <>.


Jay Sullivan <>