Simple, secure SOCKS proxies using spiped。
Recently, I've been getting more concerned with security. As an American living in a Middle Eastern monarchy, multiple government agencies are likely monitoring my internet traffic—not to mention that I frequently connect to servers from sketchy internet cafes while traveling in the developing world. To mitigate these risks, I proxy all my traffic through a secure server—but with the recent heartbleed bug, I decided to step my security up a notch.
Now, all traffic is routed through spiped, a simple and secure utility. Using Docker, I've automated most of the setup for this system, so you can easily route your traffic securely as well.
Server Setup
Setting up the server for this is quite simple, assuming you have Docker installed.
- Clone my Dockerfile, which handles setting up a Socks proxy (with SSH) and the spiped server.
git clone https://github.com/morgante/spiped-docker /home/spiped
- Enter the spiped directory, where the magic happens:
cd /home/spiped
- Generate a secure key for the spiped socket to use for communication across the internet.
dd if=/dev/urandom bs=32 count=1 of=spiped.key
- Build the Docker image (it will automatically load the key you just generated)
docker build -t spiped .
- Start the spiped server with Docker:
docker run -d -p 49168:8089 -t spiped
You now have a fully functional SOCKS proxy listening on port 49168 and secured using a private key.
Client Setup
On the client, all you need to do is installed spiped and connect to the server. These instructions are for OS X, but the process should be similar for other operating systems.
- Install spiped (with Homebrew).
brew install spiped
- Copy the private key from your server.
scp username@server.name:/home/spiped/spiped.key ~/spiped.key
- Start the spiped client:
spiped -e -s '[0.0.0.0]:8089' -t '[107.170.94.89]:49168' -k ~/spiped.key
- In System Preferences, configure your network to connect to a SOCKS proxy at localhost:8089.
Now all your internet activity is securely routed through your server. If you want to automate this slightly more, I have written a very simple start script.
In my experience, the spiped tunnel is highly reliable and recovers more gracefully than a standard SSH tunnel.
Leave any questions in the comments and I'll do my best to answer.
from https://github.com/morgante/spiped-docker
---------------------------------------------------------
---------------------------------------------------------
spiped is a utility for creating symmetrically encrypted and authenticated pipes between socket addresses, so that one may connect to one address (e.g., a UNIX socket on localhost) and transparently have a connection established to another address (e.g., a UNIX socket on a different system). This is similar to 'ssh -L' functionality, but does not use SSH and requires a pre-shared symmetric key. spipe (pronounced "ess-pipe") is a utility which acts as an spiped protocol client (i.e., connects to an spiped daemon), taking input from the standard input and writing data read back to the standard output. Note that spiped: 1. Requires a strong key file: The file specified via the -k option should have at least 256 bits of entropy. ('dd if=/dev/urandom bs=32 count=1' is your friend.) 2. Requires strong entropy from /dev/urandom. (Make sure your kernel's random number generator is seeded at boot time!) 3. Does not provide any protection against information leakage via packet timing: Running telnet over spiped will protect a password from being directly read from the network, but will not obscure the typing rhythm. 4. Can significantly increase bandwidth usage for interactive sessions: It sends data in packets of 1024 bytes, and pads smaller messages up to this length, so a 1 byte write could be expanded to 1024 bytes if it cannot be coalesced with adjacent bytes. 5. Uses a symmetric key -- so anyone who can connect to an spiped "server" is also able to impersonate it. Example usage. To set up an encrypted and authenticated pipe for sending email between two systems (in the author's case, from many systems around the internet to his central SMTP server, which then relays email to the rest of the world), one might run # dd if=/dev/urandom bs=32 count=1 of=keyfile # spiped -d -s '[0.0.0.0]:8025' -t '[127.0.0.1]:25' -k keyfile on a server and after copying keyfile to the local system, run # spiped -e -s '[127.0.0.1]:25' -t $SERVERNAME:8025 -k keyfile at which point mail delivered via localhost:25 on the local system will be securely transmitted to port 25 on the server. You can also use spiped to protect SSH servers from attackers: Since data is authenticated before being forwarded to the target, this can allow you to SSH to a host while protecting you in the event that someone finds an exploitable bug in the SSH daemon -- this serves the same purpose as port knocking or a firewall which restricts source IP addresses which can connect to SSH. On the SSH server, run # dd if=/dev/urandom bs=32 count=1 of=/etc/ssh/spiped.key # spiped -d -s '[0.0.0.0]:8022' -t '[127.0.0.1]:22' -k /etc/ssh/spiped.key then copy the server's /etc/ssh/spiped.key to ~/.ssh/spiped_HOSTNAME_key on your local system and add the lines Host HOSTNAME ProxyCommand spipe -t %h:8022 -k ~/.ssh/spiped_%h_key to the ~/.ssh/config file. This will cause "ssh HOSTNAME" to automatically connect using the spipe client via the spiped daemon; you can then firewall off all incoming traffic on port tcp/22. For a detailed list of the command-line options to spiped and spipe, see the README files in the respective subdirectories. Security requirements. The user is responsible for ensuring that: 1. The key file contains 256 or more bits of entropy. 2. The same key file is not used for more than 2^64 connections. 3. Any individual connection does not transmit more than 2^64 bytes. Encrypted protocol. The client and server share a key file with 256 or more bits of entropy. On launch, they read the key file and compute K = SHA256(key file). When a connection is established: C1. The client generates a 256-bit random value nonce_C and sends it. S1. The server generates a 256-bit random value nonce_S and sends it. C2. The client receives a 256-bit value nonce_S. S2. The server receives a 256-bit value nonce_C. C3/S3. Both parties now compute the 512-bit value dk_1 = PBKDF2-SHA256(K, nonce_C || nonce_S, 1) and parse it as a pair of 256-bit values dhmac_C || dhmac_S = dk_1. C4. The client picks* a value x_C and computes** y_C = 2^x_C mod p, where p is the Diffie-Hellman "group #14" modulus, and h_C = HMAC-SHA256(dhmac_C, y_C). The client sends y_C || h_C to the server. S4. The server receives a 2304-bit value which it parses as y_C || h_C, where y_C is 2048 bits and h_C is 256 bits; and drops the connection if h_C is not equal to HMAC-SHA256(dhmac_C, y_C) or y_C >= p. S5. The server picks* a value x_S and computes** y_S = 2^x_S mod p and h_S = HMAC-SHA256(dhmac_S, y_S). The server sends y_S || h_S to the client. C5. The client receives a 2304-bit value which it parses as y_S || h_S, where y_S is 2048 bits and h_S is 256 bits; and drops the connection if h_S is not equal to HMAC-SHA256(dhmac_S, y_S) or y_S >= p. C6. The client computes** y_SC = y_S^x_C mod p. S6. The server computes** y_SC = y_C^x_S mod p. (Note that these two compute values are identical.) C7/S7. Both parties now compute the 1024-bit value dk_2 = PBKDF2-SHA256(K, nonce_C || nonce_S || y_SC, 1) and parse it as a 4-tuple of 256-bit values E_C || H_C || E_S || H_S. Thereafter, the client and server exchange 1060-byte packets P generated from plaintext messages M of 1--1024 bytes msg_padded = M || ( 0x00 x (1024 - length(M))) || bigendian32(length(M)) msg_encrypted = AES256-CTR(E, msg_padded, packet#) P = msg_encrypted || HMAC-SHA256(H, msg_encrypted || bigendian64(packet#)) where E and H are E_C and H_C or E_S and H_S depending on whether the packet is being sent by the client or the server, and AES256-CTR is computed with nonce equal to the packet #, which starts at zero and increments for each packet sent in the same direction. * The values x_C, x_S picked must either be 0 (if forward perfect secrecy is not desired) or have 256 bits of entropy (if forward perfect secrecy is desired). ** The values y_C, y_S, and y_SC are 2048 bits and big-endian. Security proof 1. Under the random oracle model, K has at least 255 bits of entropy (it's a 256-bit hash computed from a value with at least 256 bits of entropy). 2. Provided that at least one party is following the protocol and the key file has been used for fewer than 2^64 connections, the probability of the tuple (K, nonce_C, nonce_S) being non-unique is less than 2^(-192). 3. Under the random oracle model, the probability of an attacker without access to K guessing either of dhmac_C and dhmac_S is less than P(attacker guesses K) + P(the tuple has been input to the oracle before) + P(the attacker directly guesses), which is less than 2^(-255) + 2^(-192) + 2^(-255) = 2^(-192) + 2^(-254). 4. Consequently, in order for an attacker to convince a protocol-obeying party that a tuple (y, h) is legitimate, the attacker must do at least 2^190 expected work (which we consider to be computationally infeasible and do not consider any further). 5. If one of the parties opts to not have perfect forward secrecy, then the value y_SC will be equal to 1 and dk_2 will have the same security properties as dk_1, i.e., it will be computationally infeasible for an attacker without access to K to compute dk_2. 6. If both parties opt for perfect forward secrecy, an attacker who can compute y_SC has solved a Diffie-Hellman problem over the 2048-bit group #14, which is (under the CDH assumption) computationally infeasible. 7. Consequently, if both parties opt for perfect forward secrecy, an attacker who obtains access to K after the handshake has completed will continue to be unable to compute dk_2 from information exchanged during the handshake. 8. Under the random oracle model, the packets P are indistinguishable from random 1060-byte packets; thus no information about the keys used or the plaintext being transmitted is revealed by post-key-exchange communications. 9. Because the values (msg_encrypted || bigendian(packet#)) are distinct for each packet, under the random oracle model it is infeasible for an attacker without access to the value H to generate a packet which will be accepted as valid.
from https://github.com/morgante/spiped-docker/tree/master/spiped-1.3.1
or: https://github.com/gyepisam/spiped
-------------
spiped's dependency: https://opensource.apple.com/tarballs/bsdmake/bsdmake-24.tar.gz
在linux vps 上的编译:
wget https://www.tarsnap.com/spiped/spiped-1.5.0.tgz
tar zxvf spiped-1.5.0.tgz
cd spiped-1.5.0
make
make install
root@AR:~/spiped-1.5.0# which spiped
/usr/local/bin/spiped
(说明spiped安装成功。)
(说明spiped安装成功。)
root@AR:~/spiped-1.5.0# spiped
usage: spiped {-e | -d} -s <source socket> -t <target socket> -k <key file>
[-DFj] [-f | -g] [-n <max # connections>] [-o <connection timeout>]
root@AR:~/spiped-1.5.0#