Caspar's netcat approach is awesome for its simplicity, but there may be situations where you want don't want to send unencrypted files over the network.
To really get this right, you should probably use a mature solution like
scp, SFTP, samba, or magic-wormhole (a really cool one, but as of the time of writing unfortunately not great for sending huge folders).
But considering you are in this situation:
- you don't want to setup a user account for the other party, or don't know how to configure it so the other person can't execute shell commands on your PC (so SCP/SFTP is out of the picture)
- the configuration overhead of FTPS/samba is too much as well for a one-off transfer
- your folders are too large for magic-wormhole
- and you don't expect serious attackers
The following solution may be interesting:
gpg -c for encryption
serve (host): tar -cz . | gpg -c --cipher-algo AES256 | ncat -lp 8000
fetch (client): ncat HOST 8000 --recv-only | gpg -d | tar -xz
(here, using nmap's
ncat implementation. For others, see below..)
In case the receiver is easier to connect to than the sender, you can easily invert their roles by changing the netcat commands in the pipeline:
send (client): tar -cz . | gpg -c --cipher-algo AES256 | ncat HOST 8000
recv (host): ncat -lp 8000 --recv-only | gpg -d | tar -xz
The host command always has to be executed first.
Password via command line:
If you want, the password can be provided on both ends using
gpg [...] --batch --passphrase-fd 3 3<<<'PASSWORD', or
gpg [...] --batch --passphrase-file <(cat <<<'PASSWORD'), or simply
gpg [...] --batch --passphrase PASSWORD. However, this form should mostly be avoided, especially on multi-user systems.
As far as I understand, GPG does authenticate the ciphertext against the password, but this happens very late, so that the
tar extraction process may already be impossible to roll back and could have overwritten files in your local directory if some part of the ciphertext was replaced or incorrectly transmitted. For this reason, always cd to a new empty directory before doing this.
Note that I'm no expert on GPG/crypto and can't promise this is not immensively unsafe in other ways as well.
Things you could also try
I think it works, but no guarantees:
serve (host): ENCRYPT | nc -lNp 8000
fetch (client): nc -d HOST 8000 | DECRYPT
send (client): ENCRYPT | nc -N HOST 8000
receive (host): nc -ldp 8000 | DECRYPT
In theory, this could work:
serve (host): ENCRYPT | nc -clp 8000
fetch (client): nc HOST 8000 | DECRYPT
send (client): ENCRYPT | nc -c HOST 8000
receive (host): nc -lp 8000 | DECRYPT
However, in my trials it often failed due to closing the connection before all bytes were sent/received.
This can be mitigated by either not specifying the
-c option (in which case you have to close the connection manually using Ctrl+C, when you think it's done), or by building in some delay on the sender side:
(ENCRYPT; sleep 10s) | nc -clp 8000
Different netcat implementations on client/server
Encrypt the stream using
tar -cz . | openssl enc -e -aes-256-ctr -pbkdf2 | ncat -lp 8000
ncat HOST 8000 --recv-only | openssl enc -d -aes-256-ctr -pbkdf2 | tar -xz
openssl will ask you for the password. Alternatively, you can provide the password using the
-k PASSWORD command-line option on both ends, or on multi-user systems, using
Beware that this does not provide authenticated encryption - which means that there is no guarantee that the stream is unaltered. So, someone could really mess up your filesystem if they change a few bytes. Although, you get basic redundancy checks in the gzip archive enabled by the
-z option, this will not reliably protect you. This is probably fine to protect a love letter against your friends, but don't use it if there may be someone even more nefarious in the network!
enc doesn't support any authenticated encryption modes.
zip for encryption
tar -cz . | zip -e -Ppassword | ncat -lp 8000
ncat HOST 8000 --recv-only | funzip -password | tar -xz
Seems to work, but prints the following error:
funzip error: invalid compressed data--length error
(not due to network errors, I get the same error when calling
funzip in a local pipe, like
echo text | zip | funzip.)