mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03: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
					
				
					 5 changed files with 57 additions and 31 deletions
				
			
		| 
						 | 
				
			
			@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue