mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2024-11-21 15:05:21 +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
|
||||
// Buffering reduces packet loss in the sim
|
||||
// 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(),
|
||||
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(),
|
||||
m.core.DEBUG_getSigningPublicKey())
|
||||
m.core.DEBUG_getSigningPublicKey(), *n.core.DEBUG_getSharedKey(qLinkPriv, pLinkPub))
|
||||
DEBUG_simLinkPeers(p, q)
|
||||
return
|
||||
}
|
||||
|
@ -64,11 +64,10 @@ func (c *Core) DEBUG_getPeers() *peers {
|
||||
return &c.peers
|
||||
}
|
||||
|
||||
func (ps *peers) DEBUG_newPeer(box boxPubKey,
|
||||
sig sigPubKey) *peer {
|
||||
func (ps *peers) DEBUG_newPeer(box boxPubKey, sig sigPubKey, link boxSharedKey) *peer {
|
||||
//in <-chan []byte,
|
||||
//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()
|
||||
}
|
||||
|
||||
func (c *Core) DEBUG_getSharedKey(myPrivKey *boxPrivKey, othersPubKey *boxPubKey) *boxSharedKey {
|
||||
return getSharedKey(myPrivKey, othersPubKey)
|
||||
}
|
||||
|
||||
func (c *Core) DEBUG_newSigKeys() (*sigPubKey, *sigPrivKey) {
|
||||
return newSigKeys()
|
||||
}
|
||||
|
@ -76,17 +76,18 @@ type peer struct {
|
||||
bytesSent 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
|
||||
core *Core
|
||||
port switchPort
|
||||
box boxPubKey
|
||||
sig sigPubKey
|
||||
shared boxSharedKey
|
||||
firstSeen time.Time // To track uptime for getPeers
|
||||
linkOut (chan []byte) // used for protocol traffic (to bypass queues)
|
||||
doSend (chan struct{}) // tell the linkLoop to send a switchMsg
|
||||
dinfo *dhtInfo // used to keep the DHT working
|
||||
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
|
||||
core *Core
|
||||
port switchPort
|
||||
box boxPubKey
|
||||
sig sigPubKey
|
||||
shared boxSharedKey
|
||||
linkShared boxSharedKey
|
||||
firstSeen time.Time // To track uptime for getPeers
|
||||
linkOut (chan []byte) // used for protocol traffic (to bypass queues)
|
||||
doSend (chan struct{}) // tell the linkLoop to send a switchMsg
|
||||
dinfo *dhtInfo // used to keep the DHT working
|
||||
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 {
|
||||
@ -97,14 +98,15 @@ func (p *peer) updateQueueSize(delta int64) {
|
||||
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()
|
||||
p := peer{box: *box,
|
||||
sig: *sig,
|
||||
shared: *getSharedKey(&ps.core.boxPriv, box),
|
||||
firstSeen: now,
|
||||
doSend: make(chan struct{}, 1),
|
||||
core: ps.core}
|
||||
sig: *sig,
|
||||
shared: *getSharedKey(&ps.core.boxPriv, box),
|
||||
linkShared: *linkShared,
|
||||
firstSeen: now,
|
||||
doSend: make(chan struct{}, 1),
|
||||
core: ps.core}
|
||||
ps.mutex.Lock()
|
||||
defer ps.mutex.Unlock()
|
||||
oldPorts := ps.getPorts()
|
||||
@ -228,7 +230,13 @@ func (p *peer) sendPacket(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{
|
||||
Nonce: *nonce,
|
||||
Payload: bs,
|
||||
@ -242,7 +250,15 @@ func (p *peer) handleLinkTraffic(bs []byte) {
|
||||
if !packet.decode(bs) {
|
||||
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 {
|
||||
return
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ type router struct {
|
||||
func (r *router) init(core *Core) {
|
||||
r.core = core
|
||||
r.addr = *address_addrForNodeID(&r.core.dht.nodeID)
|
||||
in := make(chan []byte, 32) // TODO something better than this...
|
||||
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub) //, out, in)
|
||||
in := make(chan []byte, 32) // TODO something better than this...
|
||||
p := r.core.peers.newPeer(&r.core.boxPub, &r.core.sigPub, &boxSharedKey{})
|
||||
p.out = func(packet []byte) {
|
||||
// This is to make very sure it never blocks
|
||||
select {
|
||||
|
@ -141,10 +141,12 @@ func (iface *tcpInterface) call(saddr string) {
|
||||
func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
||||
defer sock.Close()
|
||||
// Get our keys
|
||||
myLinkPub, myLinkPriv := newBoxKeys() // ephemeral link keys
|
||||
keys := []byte{}
|
||||
keys = append(keys, tcp_key[:]...)
|
||||
keys = append(keys, iface.core.boxPub[:]...)
|
||||
keys = append(keys, iface.core.sigPub[:]...)
|
||||
keys = append(keys, myLinkPub[:]...)
|
||||
_, err := sock.Write(keys)
|
||||
if err != nil {
|
||||
return
|
||||
@ -158,8 +160,9 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
||||
if n < len(keys) { /*panic("Partial key packet?") ;*/
|
||||
return
|
||||
}
|
||||
info := tcpInfo{}
|
||||
if !tcp_chop_keys(&info.box, &info.sig, &keys) { /*panic("Invalid key packet?") ;*/
|
||||
info := tcpInfo{} // used as a map key, so don't include ephemeral link eys
|
||||
var theirLinkPub boxPubKey
|
||||
if !tcp_chop_keys(&info.box, &info.sig, &theirLinkPub, &keys) { /*panic("Invalid key packet?") ;*/
|
||||
return
|
||||
}
|
||||
// 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
|
||||
// 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)
|
||||
in := func(bs []byte) {
|
||||
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_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
|
||||
// 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
|
||||
}
|
||||
for idx := range tcp_key {
|
||||
@ -352,6 +355,8 @@ func tcp_chop_keys(box *boxPubKey, sig *sigPubKey, bs *[]byte) bool {
|
||||
(*bs) = (*bs)[len(box):]
|
||||
copy(sig[:], *bs)
|
||||
(*bs) = (*bs)[len(sig):]
|
||||
copy(link[:], *bs)
|
||||
(*bs) = (*bs)[len(sig):]
|
||||
return true
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user