From 9095b99f6bc8dcbff48a02002812a1f3961bfe26 Mon Sep 17 00:00:00 2001 From: Milos Gajdos Date: Mon, 25 Nov 2019 18:56:00 +0000 Subject: [PATCH] Token has been stripped; Headers are encrypted --- tunnel/crypto.go | 16 +++++++------- tunnel/default.go | 42 ++++++++++++++--------------------- tunnel/listener.go | 4 ++++ tunnel/session.go | 55 ++++++++++++++++++++++++++++++---------------- 4 files changed, 65 insertions(+), 52 deletions(-) diff --git a/tunnel/crypto.go b/tunnel/crypto.go index f34f9c15..ba0d5057 100644 --- a/tunnel/crypto.go +++ b/tunnel/crypto.go @@ -8,6 +8,14 @@ import ( "io" ) +// hash hahes the data into 32 bytes key and returns it +// hash uses sha256 underneath to hash the supplied key +func hash(key string) []byte { + hasher := sha256.New() + hasher.Write([]byte(key)) + return hasher.Sum(nil) +} + // Encrypt encrypts data and returns the encrypted data func Encrypt(data []byte, key string) ([]byte, error) { // generate a new AES cipher using our 32 byte key @@ -62,11 +70,3 @@ func Decrypt(data []byte, key string) ([]byte, error) { return plaintext, nil } - -// hash hahes the data into 32 bytes key and returns it -// hash uses sha256 underneath to hash the supplied key -func hash(key string) []byte { - hasher := sha256.New() - hasher.Write([]byte(key)) - return hasher.Sum(nil) -} diff --git a/tunnel/default.go b/tunnel/default.go index adf4bb6d..72963f0c 100644 --- a/tunnel/default.go +++ b/tunnel/default.go @@ -30,7 +30,7 @@ type tun struct { // the unique id for this tunnel id string - // tunnel token for authentication + // tunnel token for session encryption token string // to indicate if we're connected or not @@ -119,6 +119,7 @@ func (t *tun) newSession(channel, sessionId string) (*session, bool) { tunnel: t.id, channel: channel, session: sessionId, + token: t.token, closed: make(chan bool), recv: make(chan *message, 128), send: t.send, @@ -159,7 +160,6 @@ func (t *tun) announce(channel, session string, link *link) { "Micro-Tunnel-Channel": channel, "Micro-Tunnel-Session": session, "Micro-Tunnel-Link": link.id, - "Micro-Tunnel-Token": t.token, }, } @@ -292,9 +292,6 @@ func (t *tun) process() { // set the session id newMsg.Header["Micro-Tunnel-Session"] = msg.session - // set the tunnel token - newMsg.Header["Micro-Tunnel-Token"] = t.token - // send the message via the interface t.RLock() @@ -447,14 +444,11 @@ func (t *tun) listen(link *link) { return } - // always ensure we have the correct auth token - // TODO: segment the tunnel based on token - // e.g use it as the basis - token := msg.Header["Micro-Tunnel-Token"] - if token != t.token { - log.Debugf("Tunnel link %s received invalid token %s", token) - return - } + // TODO: figure out network authentication + // for now we use tunnel token to encrypt/decrypt + // session communication, but we will probably need + // some sort of network authentication (token) to avoid + // having rogue actors spamming the network // message type mtype := msg.Header["Micro-Tunnel"] @@ -702,9 +696,8 @@ func (t *tun) discover(link *link) { // send a discovery message to all links if err := link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "discover", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "discover", + "Micro-Tunnel-Id": t.id, }, }); err != nil { log.Debugf("Tunnel failed to send discover to link %s: %v", link.id, err) @@ -733,9 +726,8 @@ func (t *tun) keepalive(link *link) { log.Debugf("Tunnel sending keepalive to link: %v", link.Remote()) if err := link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "keepalive", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "keepalive", + "Micro-Tunnel-Id": t.id, }, }); err != nil { log.Debugf("Error sending keepalive to link %v: %v", link.Remote(), err) @@ -765,9 +757,8 @@ func (t *tun) setupLink(node string) (*link, error) { // send the first connect message if err := link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "connect", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "connect", + "Micro-Tunnel-Id": t.id, }, }); err != nil { return nil, err @@ -901,9 +892,8 @@ func (t *tun) close() error { for node, link := range t.links { link.Send(&transport.Message{ Header: map[string]string{ - "Micro-Tunnel": "close", - "Micro-Tunnel-Id": t.id, - "Micro-Tunnel-Token": t.token, + "Micro-Tunnel": "close", + "Micro-Tunnel-Id": t.id, }, }) link.Close() @@ -1157,6 +1147,8 @@ func (t *tun) Listen(channel string, opts ...ListenOption) (Listener, error) { tl := &tunListener{ channel: channel, + // tunnel token + token: t.token, // the accept channel accept: make(chan *session, 128), // the channel to close diff --git a/tunnel/listener.go b/tunnel/listener.go index c893297d..cc207d70 100644 --- a/tunnel/listener.go +++ b/tunnel/listener.go @@ -10,6 +10,8 @@ import ( type tunListener struct { // address of the listener channel string + // token is the tunnel token + token string // the accept channel accept chan *session // the channel to close @@ -78,6 +80,8 @@ func (t *tunListener) process() { channel: m.channel, // the session id session: m.session, + // tunnel token + token: t.token, // is loopback conn loopback: m.loopback, // the link the message was received on diff --git a/tunnel/session.go b/tunnel/session.go index 09042fd1..4b8721aa 100644 --- a/tunnel/session.go +++ b/tunnel/session.go @@ -1,6 +1,7 @@ package tunnel import ( + "encoding/hex" "errors" "io" "time" @@ -17,6 +18,8 @@ type session struct { channel string // the session id based on Micro.Tunnel-Session session string + // token is the session token + token string // closed closed chan bool // remote addr @@ -301,16 +304,10 @@ func (s *session) Send(m *transport.Message) error { // no op } - // get the token - token, ok := m.Header["Micro-Tunnel-Token"] - if !ok { - // TODO: should we continue or return error - log.Debugf("no token found, insecure channel") - } - // encrypt the transport message payload - body, err := Encrypt(m.Body, token+s.channel+s.session) + body, err := Encrypt(m.Body, s.token+s.channel+s.session) if err != nil { + log.Debugf("failed to encrypt message body: %v", err) return err } @@ -320,9 +317,16 @@ func (s *session) Send(m *transport.Message) error { Body: body, } + // encrypt all the headers for k, v := range m.Header { - // TODO: should we also encrypt headers? - data.Header[k] = v + // encrypt the transport message payload + val, err := Encrypt([]byte(v), s.token+s.channel+s.session) + if err != nil { + log.Debugf("failed to encrypt message header %s: %v", k, err) + return err + } + // hex encode the encrypted header value + data.Header[k] = hex.EncodeToString(val) } // create a new message @@ -366,22 +370,35 @@ func (s *session) Recv(m *transport.Message) error { default: } - // TODO: if we encrypt headers we will have to decrypt them here - token, ok := msg.data.Header["Micro-Tunnel-Token"] - if !ok { - // TODO: should we continue or return error - log.Debugf("no token found, insecure channel") - } - - log.Tracef("Received %+v from recv backlog", msg) + //log.Tracef("Received %+v from recv backlog", msg) + log.Debugf("Received %+v from recv backlog", msg) // decrypt the received payload using the token - body, err := Decrypt(msg.data.Body, token+s.channel+s.session) + body, err := Decrypt(msg.data.Body, s.token+s.channel+s.session) if err != nil { + log.Debugf("failed to decrypt message body: %v", err) return err } msg.data.Body = body + // encrypt all the headers + for k, v := range msg.data.Header { + // hex decode the header values + h, err := hex.DecodeString(v) + if err != nil { + log.Debugf("failed to decode message header %s: %v", k, err) + return err + } + // encrypt the transport message payload + val, err := Decrypt([]byte(h), s.token+s.channel+s.session) + if err != nil { + log.Debugf("failed to decrypt message header %s: %v", k, err) + return err + } + // hex encode the encrypted header value + msg.data.Header[k] = string(val) + } + // set message *m = *msg.data // return nil