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:
Using gpg -c
for encryption
Pull mode:
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..)
Push mode:
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.
Caution:
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
OpenBSD netcat
I think it works, but no guarantees:
Pull mode:
serve (host): ENCRYPT | nc -lNp 8000
fetch (client): nc -d HOST 8000 | DECRYPT
Push mode:
send (client): ENCRYPT | nc -N HOST 8000
receive (host): nc -ldp 8000 | DECRYPT
GNU netcat
In theory, this could work:
Pull mode:
serve (host): ENCRYPT | nc -clp 8000
fetch (client): nc HOST 8000 | DECRYPT
Push mode:
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
Should work.
Encrypt the stream using openssl enc
Serve files:
tar -cz . | openssl enc -e -aes-256-ctr -pbkdf2 | ncat -lp 8000
Fetch files:
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 -pass file:<(cat<<<PASSWORD)
.
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!
Unfortunately, openssl's enc
doesn't support any authenticated encryption modes.
Using zip
for encryption
Server:
tar -cz . | zip -e -Ppassword | ncat -lp 8000
Client:
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
.)