Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easy secure connection over unsafe network (both endpoints fully controlled)

I need to connect client & server over untrusted network. I've considered using TLS (crypto/tls), but from what I understand, I first need to create a create a crypto/x509.Certificate. But I feel overwhelmed by all the parameters I need to pass to the x509.CreateCertificate() function - it says it needs all of the following fields:

SerialNumber, Subject, NotBefore, NotAfter, KeyUsage, BasicConstraintsValid, IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical, PermittedDNSDomains.

I have full control over both endpoints, so I believe I don't need any expiration or invalidation support/parameters (I can change keys both on client and server at any time I want) - so I can probably skip NotBefore and NotAfter (? or do I have to set them anyway?). What should I put in all the other fields, and why, to avoid any vulnerabilities? Also, can I use the same private/public key pair for both ways authentication (client to server, and server to client), or do I have to use 2 pairs?

Or, is there something simpler than TLS that I could use? Note however, that I need to two way authentication.

EDIT:

I created a simple library based on suggestions from the accepted answer, plus key generation code from generate_cert.go - see:

github.com/akavel/tunnel

like image 753
akavel Avatar asked Sep 02 '12 20:09

akavel


1 Answers

Owlstead is partly correct. Your best bet is creating self signed certificates using OpenSSL. However, I would then use the Go TLS library for encryption. Below is some code that may help you.

Creating an x509 key pair

I normally follow the instructions here. Summary of commands (do for both client and server):

openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Using Go's TLS library

First, create a tls.Config. One TLS config will work on both client and server but some of the options only need to be set on one or the other:

cert, err := tls.LoadX509KeyPair(cert, key)
config := &tls.Config{
    Certificates: []Certificates{cert},
    ClientAuth: tls.RequireAnyClientCert, // Must be done on server
    InsecureSkipVerify: true, // Must be done on client
}

On the server, you need to setup a TLS listener. This sets it up on port 4443:

listener, err := tls.Listen("tcp", ":4443", config)
for {
    conn, err := listener.Accept()
    acceptConn(conn) // your code
}

On the client:

conn, err := tls.Dial("tcp", serverAddr, config)

This will create an encrypted connection, but it will not verify the other side is who they say they are. The easiest way to do that is to give each server the public key of the other server and compare it to the server that has just connected. To find the public key on the other server, you need to:

c := conn.(*tls.Conn) // convert net.Conn from listener to tls conn
err := c.Handshake() // ensure handshake is completed without error
state := c.ConnectionState()
pubKey, err := x509.MarshalPKIXPublicKey(state.PeerCertificates[0])
bytes.Equal(pubKey, knownKey) // compare to known value
like image 77
Stephen Weinberg Avatar answered Oct 03 '22 21:10

Stephen Weinberg