How to transfer data between hosts securely.

like a bossFrom time to time i faced with task how to transfer important data between servers securely (ie over ssl or something similar). I do not use passwords for remote access and do not have private keys on remote systems, so i can not use ssh for this purposes.

First i wanted to write about solution that i used few days ago (based on socat), but this solution is to complicated (later you will see why). I remembered that openssl can encrypt files with password and send result to STDOUT. While i was reading manual for openssl, i found that openssl can be used like netcat (s_server and s_client commands), unfortunately i did not found way how to use openssl for data transfer, because in session that you can establish openssl interprets some chars as commands (R for renegotiation for example), so if you want to use openssl client/server for data transfer, you need something like base64 encoding, but without control characters.

Solution with netcat and openssl:
First i created file for test (you can use data from STDIN, tar output for example, or transfer existing file):

client$ dd if=/dev/urandom of=/tmp/rand bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 1.36697 seconds, 7.7 MB/s
client$ md5sum /tmp/rand
10fe36edbbd48cde844ad1a2a29a8e0f  /tmp/rand

Next, prepare server side:

server$ read pass
PasSwOrD
server$ nc -l -p 6667|openssl aes-256-cbc -d -k $pass > /tmp/rand

I used “read” to prevent save key into history file.
There “PasSwOrD” is your key, i use ssh to organize data transfer, so i did not worried that the traffic with key can be captured.
Next initiate transfer from client side:

client$ read pass
PasSwOrD
client$ cat /tmp/rand |openssl  aes-256-cbc -salt -k $pass|nc -w1 server.remote 6667

Check sum:

server$ md5sum /tmp/rand
10fe36edbbd48cde844ad1a2a29a8e0f  /tmp/rand

Yeah! Your see? I transfered mah file.
UPDATE: [2019-05-26] Nowaday openssl has broken backward compatibility, so when you try to decrypt file you cold get error message like `digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:crypto/evp/evp_enc.c:535`, if so you need to add -md md5 or -md sha256 on both sides to openssl’s options.

Ok, next we will do it with socat.
First you need to generate client side and server side key and certificates, let’s do it on server:

server$ openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
........+++
......................................+++
e is 65537 (0x10001)

Create certificate:

server$  openssl req -new -key server.key -x509 -days 108 -batch -out server.crt

Create pem file:

server$ cat server.* > ./server.pem

After that you will need to execute same commands on client side, but you will need to change filenames from “server” to “client”.
Next step is to exchange certificates between client and server (do it on both sides), they could be copy pasted:

server$ cat > ./client.crt << EOF
-----BEGIN CERTIFICATE-----
.... a lot of garbage ....
-----END CERTIFICATE-----
EOF

Now we ready to transfer file, prepare server:

server$ socat openssl-listen:4433,reuseaddr,cert=./server.pem,cafile=./client.crt STDIO > /tmp/rand

Client:

client$ socat STDIO openssl-connect:server.remote:4433,cert=./client.pem,cafile=./server.crt < /tmp/rand
client$ md5sum /tmp/rand
10fe36edbbd48cde844ad1a2a29a8e0f  /tmp/rand

Gotcha!

As you can see, socat with TLS not a easy solution if you need just a transfer file, so i will recommend to use first solution. Also, in debian, you can use snakeoil key and cert, but it is your homework.

UPDATE:
I found how to use openssl for data transfer, only one problem, they did not close socket after EOF, so you need to stop it by hands:
Prepare server (this time i used snakeoil cert):

server% sudo openssl s_server -quiet -accept 4343 -cert /etc/ssl/certs/ssl-cert-snakeoil.pem -key /etc/ssl/private/ssl-cert-snakeoil.key < /tmp/test

Run client:

client% md5sum /tmp/rnd
86246865b3932804979fdac48a99cebf  /tmp/rnd
client% openssl s_client -connect localhost:4343 -quiet > /tmp/rnd

After data transfered, hit ^C on server side and check:

^C
server% md5sum /tmp/test
86246865b3932804979fdac48a99cebf  /tmp/test

6 comments on “How to transfer data between hosts securely.

  • Ivan says:

    I wrote before, openssl does not close connection after file will transfered. You need to press Ctrl-C, manualy.

    Reply
  • MacLing says:

    With socat and nc ==> running OK

    client% openssl s_client -connect server_IP:4343 -quiet > /tmp/rnd

    depth=0 C = XX, L = Default City, O = Default Company Ltd
    verify error:num=18:self signed certificate
    verify return:1
    depth=0 C = XX, L = Default City, O = Default Company Ltd
    verify return:1

    please advice ==> where is the server key,cert etc …. to send the file to server ?

    Reply
    • Ivan says:

      If you use debian or ubuntu, you can use pregenerated certificate and key. Check /etc/ssl/certs/ssl-cert-snakeoil.pem and /etc/ssl/private/ssl-cert-snakeoil.key.

      Reply
      • MacLing says:

        I use centos and there is no CA in that server. is it mandatory to setup the CA first or not ?

        Reply
        • Ivan says:

          You can generate certificate and key, like i wrote above:
          spirit@mfi:/tmp% openssl genrsa -out server.key 2048
          Generating RSA private key, 2048 bit long modulus
          ……….+++
          ……………………………………………..+++
          e is 65537 (0x10001)
          spirit@mfi:/tmp% openssl req -new -key server.key -x509 -days 108 -batch -out server.crt
          spirit@mfi:/tmp% echo ivanbayan.com > ./test
          spirit@mfi:/tmp% openssl s_server -quiet -accept 4343 -cert /tmp/server.crt -key /tmp/server.key < /tmp/test spirit@mfi:/tmp% openssl s_client -connect localhost:4343 -quiet 2>/dev/null
          ivanbayan.com

          Quest completed. =)

          Reply
          • MacLing says:

            still same ==> run from client :
            # openssl s_client -connect SERVER_IP:4343 -quiet > test
            depth=0 C = XX, L = Default City, O = Default Company Ltd
            verify error:num=18:self signed certificate
            verify return:1
            depth=0 C = XX, L = Default City, O = Default Company Ltd
            verify return:1
            read:errno=0

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>