mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 13:00:47 +00:00
add inner crypto to linkProtoTraffic, using ephemeral keys, to prevent replay attacks from spoofing peer connections
This commit is contained in:
parent
1dcc60f054
commit
e5eb6de1f6
@ -54,10 +54,12 @@ func linkNodes(m, n *Node) {
|
|||||||
// Create peers
|
// Create peers
|
||||||
// Buffering reduces packet loss in the sim
|
// Buffering reduces packet loss in the sim
|
||||||
// This slightly speeds up testing (fewer delays before retrying a ping)
|
// This slightly speeds up testing (fewer delays before retrying a ping)
|
||||||
|
pLinkPub, pLinkPriv := m.core.DEBUG_newBoxKeys()
|
||||||
|
qLinkPub, qLinkPriv := m.core.DEBUG_newBoxKeys()
|
||||||
p := m.core.DEBUG_getPeers().DEBUG_newPeer(n.core.DEBUG_getEncryptionPublicKey(),
|
p := m.core.DEBUG_getPeers().DEBUG_newPeer(n.core.DEBUG_getEncryptionPublicKey(),
|
||||||
n.core.DEBUG_getSigningPublicKey())
|
n.core.DEBUG_getSigningPublicKey(), *m.core.DEBUG_getSharedKey(pLinkPriv, qLinkPub))
|
||||||
q := n.core.DEBUG_getPeers().DEBUG_newPeer(m.core.DEBUG_getEncryptionPublicKey(),
|
q := n.core.DEBUG_getPeers().DEBUG_newPeer(m.core.DEBUG_getEncryptionPublicKey(),
|
||||||
m.core.DEBUG_getSigningPublicKey())
|
m.core.DEBUG_getSigningPublicKey(), *n.core.DEBUG_getSharedKey(qLinkPriv, pLinkPub))
|
||||||
DEBUG_simLinkPeers(p, q)
|
DEBUG_simLinkPeers(p, q)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,10 @@ func (c *Core) DEBUG_getPeers() *peers {
|
|||||||
return &c.peers
|
return &c.peers
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *peers) DEBUG_newPeer(box boxPubKey,
|
func (ps *peers) DEBUG_newPeer(box boxPubKey, sig sigPubKey, link boxSharedKey) *peer {
|
||||||
sig sigPubKey) *peer {
|
|
||||||
//in <-chan []byte,
|
//in <-chan []byte,
|
||||||
//out chan<- []byte) *peer {
|
//out chan<- []byte) *peer {
|
||||||
return ps.newPeer(&box, &sig) //, in, out)
|
return ps.newPeer(&box, &sig, &link) //, in, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -275,6 +274,10 @@ func (c *Core) DEBUG_newBoxKeys() (*boxPubKey, *boxPrivKey) {
|
|||||||
return newBoxKeys()
|
return newBoxKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Core) DEBUG_getSharedKey(myPrivKey *boxPrivKey, othersPubKey *boxPubKey) *boxSharedKey {
|
||||||
|
return getSharedKey(myPrivKey, othersPubKey)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Core) DEBUG_newSigKeys() (*sigPubKey, *sigPrivKey) {
|
func (c *Core) DEBUG_newSigKeys() (*sigPubKey, *sigPrivKey) {
|
||||||
return newSigKeys()
|
return newSigKeys()
|
||||||
}
|
}
|
||||||
|
@ -76,17 +76,18 @@ type peer struct {
|
|||||||
bytesSent uint64 // To track bandwidth usage for getPeers
|
bytesSent uint64 // To track bandwidth usage for getPeers
|
||||||
bytesRecvd uint64 // To track bandwidth usage for getPeers
|
bytesRecvd uint64 // To track bandwidth usage for getPeers
|
||||||
// BUG: sync/atomic, 32 bit platforms need the above to be the first element
|
// BUG: sync/atomic, 32 bit platforms need the above to be the first element
|
||||||
core *Core
|
core *Core
|
||||||
port switchPort
|
port switchPort
|
||||||
box boxPubKey
|
box boxPubKey
|
||||||
sig sigPubKey
|
sig sigPubKey
|
||||||
shared boxSharedKey
|
shared boxSharedKey
|
||||||
firstSeen time.Time // To track uptime for getPeers
|
linkShared boxSharedKey
|
||||||
linkOut (chan []byte) // used for protocol traffic (to bypass queues)
|
firstSeen time.Time // To track uptime for getPeers
|
||||||
doSend (chan struct{}) // tell the linkLoop to send a switchMsg
|
linkOut (chan []byte) // used for protocol traffic (to bypass queues)
|
||||||
dinfo *dhtInfo // used to keep the DHT working
|
doSend (chan struct{}) // tell the linkLoop to send a switchMsg
|
||||||
out func([]byte) // Set up by whatever created the peers struct, used to send packets to other nodes
|
dinfo *dhtInfo // used to keep the DHT working
|
||||||
close func() // Called when a peer is removed, to close the underlying connection, or via admin api
|
out func([]byte) // Set up by whatever created the peers struct, used to send packets to other nodes
|
||||||
|
close func() // Called when a peer is removed, to close the underlying connection, or via admin api
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) getQueueSize() int64 {
|
func (p *peer) getQueueSize() int64 {
|
||||||
@ -97,14 +98,15 @@ func (p *peer) updateQueueSize(delta int64) {
|
|||||||
atomic.AddInt64(&p.queueSize, delta)
|
atomic.AddInt64(&p.queueSize, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *peers) newPeer(box *boxPubKey, sig *sigPubKey) *peer {
|
func (ps *peers) newPeer(box *boxPubKey, sig *sigPubKey, linkShared *boxSharedKey) *peer {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
p := peer{box: *box,
|
p := peer{box: *box,
|
||||||
sig: *sig,
|
sig: *sig,
|
||||||
shared: *getSharedKey(&ps.core.boxPriv, box),
|
shared: *getSharedKey(&ps.core.boxPriv, box),
|
||||||
firstSeen: now,
|
linkShared: *linkShared,
|
||||||
doSend: make(chan struct{}, 1),
|
firstSeen: now,
|
||||||
core: ps.core}
|
doSend: make(chan struct{}, 1),
|
||||||
|
core: ps.core}
|
||||||
ps.mutex.Lock()
|
ps.mutex.Lock()
|
||||||
defer ps.mutex.Unlock()
|
defer ps.mutex.Unlock()
|
||||||
oldPorts := ps.getPorts()
|
oldPorts := ps.getPorts()
|
||||||
@ -228,7 +230,13 @@ func (p *peer) sendPacket(packet []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *peer) sendLinkPacket(packet []byte) {
|
func (p *peer) sendLinkPacket(packet []byte) {
|
||||||
bs, nonce := boxSeal(&p.shared, packet, nil)
|
innerPayload, innerNonce := boxSeal(&p.linkShared, packet, nil)
|
||||||
|
innerLinkPacket := wire_linkProtoTrafficPacket{
|
||||||
|
Nonce: *innerNonce,
|
||||||
|
Payload: innerPayload,
|
||||||
|
}
|
||||||
|
outerPayload := innerLinkPacket.encode()
|
||||||
|
bs, nonce := boxSeal(&p.shared, outerPayload, nil)
|
||||||
linkPacket := wire_linkProtoTrafficPacket{
|
linkPacket := wire_linkProtoTrafficPacket{
|
||||||
Nonce: *nonce,
|
Nonce: *nonce,
|
||||||
Payload: bs,
|
Payload: bs,
|
||||||
@ -242,7 +250,15 @@ func (p *peer) handleLinkTraffic(bs []byte) {
|
|||||||
if !packet.decode(bs) {
|
if !packet.decode(bs) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
payload, isOK := boxOpen(&p.shared, packet.Payload, &packet.Nonce)
|
outerPayload, isOK := boxOpen(&p.shared, packet.Payload, &packet.Nonce)
|
||||||
|
if !isOK {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
innerPacket := wire_linkProtoTrafficPacket{}
|
||||||
|
if !innerPacket.decode(outerPayload) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
payload, isOK := boxOpen(&p.linkShared, innerPacket.Payload, &innerPacket.Nonce)
|
||||||
if !isOK {
|
if !isOK {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,8 @@ type router struct {
|
|||||||
func (r *router) init(core *Core) {
|
func (r *router) init(core *Core) {
|
||||||
r.core = core
|
r.core = core
|
||||||
r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
|
r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
|
||||||
in := make(chan []byte, 32) // TODO something better than this...
|
in := make(chan []byte, 32) // TODO something better than this...
|
||||||
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub) //, out, in)
|
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{})
|
||||||
p.out = func(packet []byte) {
|
p.out = func(packet []byte) {
|
||||||
// This is to make very sure it never blocks
|
// This is to make very sure it never blocks
|
||||||
select {
|
select {
|
||||||
|
@ -141,10 +141,12 @@ func (iface *tcpInterface) call(saddr string) {
|
|||||||
func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
||||||
defer sock.Close()
|
defer sock.Close()
|
||||||
// Get our keys
|
// Get our keys
|
||||||
|
myLinkPub, myLinkPriv := newBoxKeys() // ephemeral link keys
|
||||||
keys := []byte{}
|
keys := []byte{}
|
||||||
keys = append(keys, tcp_key[:]...)
|
keys = append(keys, tcp_key[:]...)
|
||||||
keys = append(keys, iface.core.boxPub[:]...)
|
keys = append(keys, iface.core.boxPub[:]...)
|
||||||
keys = append(keys, iface.core.sigPub[:]...)
|
keys = append(keys, iface.core.sigPub[:]...)
|
||||||
|
keys = append(keys, myLinkPub[:]...)
|
||||||
_, err := sock.Write(keys)
|
_, err := sock.Write(keys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -158,8 +160,9 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||||||
if n < len(keys) { /*panic("Partial key packet?") ;*/
|
if n < len(keys) { /*panic("Partial key packet?") ;*/
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
info := tcpInfo{}
|
info := tcpInfo{} // used as a map key, so don't include ephemeral link eys
|
||||||
if !tcp_chop_keys(&info.box, &info.sig, &keys) { /*panic("Invalid key packet?") ;*/
|
var theirLinkPub boxPubKey
|
||||||
|
if !tcp_chop_keys(&info.box, &info.sig, &theirLinkPub, &keys) { /*panic("Invalid key packet?") ;*/
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Quit the parent call if this is a connection to ourself
|
// Quit the parent call if this is a connection to ourself
|
||||||
@ -207,7 +210,7 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
|||||||
}()
|
}()
|
||||||
// Note that multiple connections to the same node are allowed
|
// Note that multiple connections to the same node are allowed
|
||||||
// E.g. over different interfaces
|
// E.g. over different interfaces
|
||||||
p := iface.core.peers.newPeer(&info.box, &info.sig)
|
p := iface.core.peers.newPeer(&info.box, &info.sig, getSharedKey(myLinkPriv, &theirLinkPub))
|
||||||
p.linkOut = make(chan []byte, 1)
|
p.linkOut = make(chan []byte, 1)
|
||||||
in := func(bs []byte) {
|
in := func(bs []byte) {
|
||||||
p.handlePacket(bs)
|
p.handlePacket(bs)
|
||||||
@ -336,10 +339,10 @@ func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) {
|
|||||||
var tcp_key = [...]byte{'k', 'e', 'y', 's'}
|
var tcp_key = [...]byte{'k', 'e', 'y', 's'}
|
||||||
var tcp_msg = [...]byte{0xde, 0xad, 0xb1, 0x75} // "dead bits"
|
var tcp_msg = [...]byte{0xde, 0xad, 0xb1, 0x75} // "dead bits"
|
||||||
|
|
||||||
func tcp_chop_keys(box *boxPubKey, sig *sigPubKey, bs *[]byte) bool {
|
func tcp_chop_keys(box *boxPubKey, sig *sigPubKey, link *boxPubKey, bs *[]byte) bool {
|
||||||
// This one is pretty simple: we know how long the message should be
|
// This one is pretty simple: we know how long the message should be
|
||||||
// So don't call this with a message that's too short
|
// So don't call this with a message that's too short
|
||||||
if len(*bs) < len(tcp_key)+len(*box)+len(*sig) {
|
if len(*bs) < len(tcp_key)+2*len(*box)+len(*sig) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for idx := range tcp_key {
|
for idx := range tcp_key {
|
||||||
@ -352,6 +355,8 @@ func tcp_chop_keys(box *boxPubKey, sig *sigPubKey, bs *[]byte) bool {
|
|||||||
(*bs) = (*bs)[len(box):]
|
(*bs) = (*bs)[len(box):]
|
||||||
copy(sig[:], *bs)
|
copy(sig[:], *bs)
|
||||||
(*bs) = (*bs)[len(sig):]
|
(*bs) = (*bs)[len(sig):]
|
||||||
|
copy(link[:], *bs)
|
||||||
|
(*bs) = (*bs)[len(sig):]
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user