CLI tool
Tarsnap/spiped avatar
Tarsnap/spiped

spiped: an encrypted pipe between two sockets, without SSH

Spiped is a utility for creating symmetrically encrypted and authenticated pipes between socket addresses.

887 stars63 forksCNOASSERTION

At a glance

What is it?
spiped is a small C utility from the Tarsnap project that creates a symmetrically encrypted and authenticated connection between two socket addresses, so a local client can talk to a remote service over a protected link. It exists because SSH local forwarding was the wrong shape for the job, and the documentation is unusually blunt about the ways it can be misused.
Who is it for?
spiped fits an engineer who needs to protect a single local socket connection with a pre-shared key and does not want to run an SSH daemon, particularly for forwarding a database or mail service to a client on the same host. It is the wrong choice if you need host key verification or per-user identity, because the key is symmetric and shared, and it is the wrong choice if traffic is interactive, because of the documented 1024 byte padding.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 32 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A local socket forwarding to a remote socket, encrypted

The utility is described as creating symmetrically encrypted and authenticated pipes between socket addresses, so that one may connect to one address, a UNIX socket on localhost, and transparently have a connection established to another address, a UNIX socket on a different system.

That is the whole function, and the comparison the documentation draws is the useful one. This is similar to ssh -L functionality, but it does not use SSH and requires a pre-shared symmetric key.

Both halves of that sentence matter. Dropping SSH removes the need for a daemon, for host keys, for public key authentication and for the whole user and channel machinery that comes with them. In exchange, you get a key that both ends must already hold, and no way to authenticate the peer individually.

The second program, spipe, is the client side. It acts as an spiped protocol client, connecting to an spiped daemon, taking input from standard input and writing data read back to standard output. The naming convention is stated in the README, spiped is the daemon and spipe is the client, and both are pronounced for humans rather than spelled out.

So the deployment shape is: run spiped on the machine with the service, run spipe on the machine with the client, and the two are joined by the key. The documentation points to examples of spiped protecting SMTP and SSH on the project website, and for the command line options in detail it points to the man pages.

The project comes from Tarsnap, the backup service, and the same project hosts the official signed releases at tarsnap.com/spiped.html, which is a distinction worth noting. The repository carries the source; the signed binaries are distributed from the vendor's own site.

The five numbered caveats are the real documentation

The README lists five notes about spiped, and they read less like a feature list and more like a safety briefing. They are the most useful part of the documentation and any evaluation should start with them.

First, it requires a strong key file. The file specified via the -k option should have at least 256 bits of entropy, and the README helpfully gives the command:

bash
dd if=/dev/urandom bs=32 count=1

Second, it requires strong entropy from /dev/urandom, with a parenthetical reminder to make sure the kernel's random number generator is seeded at boot time.

Third, spiped does not provide any protection against information leakage via packet timing. The example given is running telnet over spiped, which will protect a password from being directly read from the network but will not obscure the typing rhythm. That is an honest statement of what a transport encryption layer does and does not do.

Fourth, and this is the one that bites in practice, spiped can significantly increase bandwidth usage for interactive sessions. It sends data in packets of 1024 bytes and pads smaller messages up to that length, so a 1 byte write could be expanded to 1024 bytes if it cannot be coalesced with adjacent bytes. For a batch transfer this is irrelevant. For a terminal session it is a real cost, and it is the reason SSH would be a better choice for interactive traffic.

Fifth, spiped uses a symmetric key, so anyone who can connect to an spiped server is also able to impersonate it. There is no identity in the protocol. That is the fundamental trade of the whole design, and the documentation states it in one line rather than leaving you to discover it.

The security requirements are numbers you have to respect

Below the caveats there is a separate section that states the user's responsibilities, and it is worth quoting because it is unusual for a tool to put usage limits on its own key.

The user is responsible for ensuring that the key file contains 256 or more bits of entropy, that the same key file is not used for more than 2^64 connections, and that any individual connection does not transmit more than 2^64 bytes.

Those two bounds on usage are the interesting part, because they are the key's lifetime limits rather than the tool's. A symmetric key that protects an unbounded number of sessions is a key whose compromise compromises everything ever done with it, so the tool asks you to rotate. The bounds are enormous, 2^64 connections and 2^64 bytes, which in practice means a key file is good for a very long time, but the requirement is stated because the design does not enforce it and nobody else will.

The two programs split the responsibilities between them. The daemon side handles the connection lifecycle, the handshake, and the data shuttling, and the client side reads from standard input and writes to standard output, which is what lets spipe sit in a pipeline. The protocol implementation is broken into separate files for the connection lifecycle, the handshaking, the data shuttling, and the cryptography shared by the handshake and the pipe, so the security-relevant code is in one place rather than spread across the two utilities.

The protocol is authenticated as well as encrypted, which the description makes explicit with the words symmetrically encrypted and authenticated. That matters more than it might sound. Encryption without authentication is a well known way to build a protocol that leaks, because an attacker can tamper with the ciphertext and observe what the receiver does. The handshake is where the key is exchanged and the peer is checked, and the authentication is what makes the encryption trustworthy.

Building and testing it with the included Makefiles

The build is a plain POSIX make build, and the documentation says the official releases should build and install on almost any POSIX-compliant operating system using the included Makefiles. The install target takes the destination directory as a variable:

bash
make BINDIR=/path/to/target/directory install

For more detail, including how to install the man pages, there is a BUILDING file in the repository.

The test suite is run with:

bash
make test

and memory testing with valgrind, which the documentation notes takes approximately twice as long as without valgrind, is enabled with:

bash
make test USE_VALGRIND=1

The Makefile itself shows how thorough the project is about portability. It starts with a .POSIX declaration, sets the default bindir to /usr/local/bin and the default CFLAGS to -O2, and the all target sources several generated configuration scripts, posix-flags.sh, cpusupport-config.h, cflags-filter.sh and apisupport-config.h, before descending into each program and test directory. In other words, the build probes what the host actually supports and filters the compiler flags accordingly, rather than assuming a fixed environment.

The test list in the Makefile is also revealing. Alongside the obvious client and server tests there are perftests with recv-zeros and send-zeros, a standalone-enc test, a dnsthread-resolve test, a pushbits test and a valgrind test, and a pthread_create_blocking_np test. The perftests are there because the padding behaviour documented in the caveats is exactly the sort of thing that needs measuring, and the standalone-enc test is there because the encryption path is worth exercising on its own.

The repository also carries a Makefile.BSD alongside the POSIX one, a lib directory, a liball directory with optional_mutex_normal and optional_mutex_pthread variants, the libcperciva directory of shared library code from the author's other projects, a perftests directory, a release-tools directory, and a tests directory whose test command is tests/test_spiped.sh.

The source layout tells you where the risk lives

The code layout section of the README is a map, and it is worth reading as a risk assessment rather than as a directory listing.

The spiped directory holds the code specific to the daemon utility, with main.c doing command-line parsing, initialization and the event loop, and dispatch.c accepting connections and handing them off to the protocol code. The spipe directory holds the client, again with main.c for parsing, initialization and the event loop, and pushbits.c copying data between standard input and output.

The proto directory implements the spiped protocol itself, and this is the part that matters for a security assessment. _conn.c manages the lifecycle of a connection, _handshake.c performs the handshaking portion, _pipe.c performs the data-shuttling portion, and _crypt.c does the cryptographic bits needed by the handshake and the pipe. The separation of the handshake from the pipe is what lets the same crypto code serve both, since the handshake has to agree on keys before the pipe can use them.

The lib directory contains dnsthread, which spawns a thread for background DNS resolution. That is worth noting because it is a place where the two utilities could disagree: the daemon resolves a hostname and the client resolves a hostname, and if they resolve to different addresses you get a connection that appears to fail for reasons that have nothing to do with the encryption. A separate thread for resolution keeps the event loop from blocking on a name lookup.

The libcperciva directory is library code from libcperciva, the author's shared library collection, and the repository listing also shows a perftests directory, a release-tools directory and a tests directory. For further detail the documentation points at DESIGN.md in the repository, and the top level also carries a CHANGELOG, a COPYRIGHT file, a STYLE file, an AGENTS.md and a Makefile.inc.

The primary language is C, and the licence field on the project record is a custom one that GitHub cannot classify, with the LICENSE file in the repository as the reference. That combination, hand written protocol code in C with a bespoke licence, is the shape you would expect from a security tool maintained by the author of a commercial backup service, where the code is published for inspection and the terms are their own.

Where spiped is the wrong tool

Three situations rule it out, and the first two are the tool telling you so.

The first is interactive traffic. The documentation says spiped can significantly increase bandwidth usage for interactive sessions, because of the 1024 byte packets and the padding of smaller messages. A terminal session over this pipe is wasteful, and SSH exists and is better at that job. Use spiped for a protocol that sends data in blocks, and use SSH for a person typing.

The second is anything that needs identity rather than a shared secret. The symmetric key means anyone who can connect to the server can impersonate it. If you need to know that the far end is a specific host run by a specific person, with a specific key, spiped cannot do that, because the key authenticates the channel, not the peer. That is a different problem from the one it solves, and SSH solves it with host keys and public key authentication.

The third is a workflow where you need to audit what happened, or where the connection has to survive a change of endpoint. spiped gives you an encrypted pipe, and that is the extent of it. There is no session accounting, no reconnection, no negotiation of cipher suites that the documentation describes, and no mechanism for using different keys for different destinations, since the key file is per invocation. For a service that has to be operated, observed and occasionally rotated without downtime, that is a lot of missing surface.

The licensing point deserves one more note, because it is unusual. The project is published under a custom licence that GitHub cannot classify, and the terms live in the LICENSE file rather than in the README. The official signed releases are hosted separately on tarsnap.com, which tells you the distribution and the terms are the vendor's own rather than a standard open source grant. Before you put spiped in a product, read that file and check it against your own obligations, because the README does not summarise the terms and this page is not going to guess at them.

Editorial conclusion

spiped fits an engineer who needs to protect a single local socket connection with a pre-shared key and does not want to run an SSH daemon, particularly for forwarding a database or mail service to a client on the same host. It is the wrong choice if you need host key verification or per-user identity, because the key is symmetric and shared, and it is the wrong choice if traffic is interactive, because of the documented 1024 byte padding. Before deploying it, generate the key file with at least 256 bits of entropy from /dev/urandom, and read the security requirements section, which caps how many connections and how many bytes a single key may protect.

Frequently asked questions

What is spiped and how does it differ from ssh -L?

spiped creates symmetrically encrypted and authenticated pipes between socket addresses, so a connection to one address is transparently established to another. The documentation compares it to ssh -L functionality but notes that it does not use SSH and instead requires a pre-shared symmetric key.

How do I generate a key file for spiped?

The README says the file specified via the -k option should have at least 256 bits of entropy, and gives dd if=/dev/urandom bs=32 count=1 as the way to produce it. It also warns that strong entropy from /dev/urandom requires the kernel random number generator to be seeded at boot time.

What are the security requirements for using spiped?

The user is responsible for ensuring the key file contains 256 or more bits of entropy, that the same key file is not used for more than 2^64 connections, and that any individual connection does not transmit more than 2^64 bytes. The documentation also notes that spiped does not protect against information leakage via packet timing.

How do I build and test spiped?

The official releases should build on almost any POSIX-compliant operating system using the included Makefiles, with make BINDIR=/path/to/target/directory install. The test suite runs with make test, and memory testing under valgrind, which takes about twice as long, is enabled with make test USE_VALGRIND=1.

Where do I get signed releases of spiped?

Official signed releases are published at the project page at tarsnap.com/spiped.html, and the repository carries the source. The project is licensed under a custom licence that GitHub cannot classify, with the terms in the LICENSE file in the repository.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Tarsnap/spiped on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/tarsnap-spiped.svg)](https://hysenlabs.com/projects/tarsnap-spiped)

Was this useful?