mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +03:00 
			
		
		
		
	move ckr checks into the tunConn code
This commit is contained in:
		
							parent
							
								
									b79829c43b
								
							
						
					
					
						commit
						4156aa3003
					
				
					 3 changed files with 123 additions and 118 deletions
				
			
		| 
						 | 
				
			
			@ -132,23 +132,9 @@ func (c *cryptokey) isEnabled() bool {
 | 
			
		|||
func (c *cryptokey) isValidLocalAddress(addr address.Address, addrlen int) bool {
 | 
			
		||||
	c.mutexlocals.RLock()
 | 
			
		||||
	defer c.mutexlocals.RUnlock()
 | 
			
		||||
 | 
			
		||||
	ip := net.IP(addr[:addrlen])
 | 
			
		||||
 | 
			
		||||
	if addrlen == net.IPv6len {
 | 
			
		||||
		// Does this match our node's address?
 | 
			
		||||
		if bytes.Equal(addr[:16], c.tun.addr[:16]) {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Does this match our node's subnet?
 | 
			
		||||
		if bytes.Equal(addr[:8], c.tun.subnet[:8]) {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Does it match a configured CKR source?
 | 
			
		||||
	if c.isEnabled() {
 | 
			
		||||
		ip := net.IP(addr[:addrlen])
 | 
			
		||||
		// Build our references to the routing sources
 | 
			
		||||
		var routingsources *[]net.IPNet
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import (
 | 
			
		|||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/address"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/crypto"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/util"
 | 
			
		||||
	"github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
 | 
			
		||||
	"golang.org/x/net/icmp"
 | 
			
		||||
| 
						 | 
				
			
			@ -71,16 +72,62 @@ func (s *tunConn) reader() (err error) {
 | 
			
		|||
				return e
 | 
			
		||||
			}
 | 
			
		||||
		} else if len(bs) > 0 {
 | 
			
		||||
			if bs[0]&0xf0 == 0x60 {
 | 
			
		||||
				switch {
 | 
			
		||||
				case bs[8] == 0x02 && !bytes.Equal(s.addr[:16], bs[8:24]): // source
 | 
			
		||||
				case bs[8] == 0x03 && !bytes.Equal(s.snet[:8], bs[8:16]): // source
 | 
			
		||||
				case bs[24] == 0x02 && !bytes.Equal(s.tun.addr[:16], bs[24:40]): // destination
 | 
			
		||||
				case bs[24] == 0x03 && !bytes.Equal(s.tun.subnet[:8], bs[24:32]): // destination
 | 
			
		||||
					util.PutBytes(bs)
 | 
			
		||||
					continue
 | 
			
		||||
				default:
 | 
			
		||||
			ipv4 := len(bs) > 20 && bs[0]&0xf0 == 0x40
 | 
			
		||||
			ipv6 := len(bs) > 40 && bs[0]&0xf0 == 0x60
 | 
			
		||||
			isCGA := true
 | 
			
		||||
			// Check source addresses
 | 
			
		||||
			switch {
 | 
			
		||||
			case ipv6 && bs[8] == 0x02 && bytes.Equal(s.addr[:16], bs[8:24]): // source
 | 
			
		||||
			case ipv6 && bs[8] == 0x03 && bytes.Equal(s.snet[:8], bs[8:16]): // source
 | 
			
		||||
			default:
 | 
			
		||||
				isCGA = false
 | 
			
		||||
			}
 | 
			
		||||
			// Check destiantion addresses
 | 
			
		||||
			switch {
 | 
			
		||||
			case ipv6 && bs[24] == 0x02 && bytes.Equal(s.tun.addr[:16], bs[24:40]): // destination
 | 
			
		||||
			case ipv6 && bs[24] == 0x03 && bytes.Equal(s.tun.subnet[:8], bs[24:32]): // destination
 | 
			
		||||
			default:
 | 
			
		||||
				isCGA = false
 | 
			
		||||
			}
 | 
			
		||||
			// Decide how to handle the packet
 | 
			
		||||
			var skip bool
 | 
			
		||||
			switch {
 | 
			
		||||
			case isCGA: // Allowed
 | 
			
		||||
			case s.tun.ckr.isEnabled() && (ipv4 || ipv6):
 | 
			
		||||
				var srcAddr address.Address
 | 
			
		||||
				var dstAddr address.Address
 | 
			
		||||
				var addrlen int
 | 
			
		||||
				if ipv4 {
 | 
			
		||||
					copy(srcAddr[:], bs[12:16])
 | 
			
		||||
					copy(dstAddr[:], bs[16:20])
 | 
			
		||||
					addrlen = 4
 | 
			
		||||
				}
 | 
			
		||||
				if ipv6 {
 | 
			
		||||
					copy(srcAddr[:], bs[8:24])
 | 
			
		||||
					copy(dstAddr[:], bs[24:40])
 | 
			
		||||
					addrlen = 16
 | 
			
		||||
				}
 | 
			
		||||
				if !s.tun.ckr.isValidLocalAddress(dstAddr, addrlen) {
 | 
			
		||||
					// The destination address isn't in our CKR allowed range
 | 
			
		||||
					skip = true
 | 
			
		||||
				} else if key, err := s.tun.ckr.getPublicKeyForAddress(srcAddr, addrlen); err == nil {
 | 
			
		||||
					srcNodeID := crypto.GetNodeID(&key)
 | 
			
		||||
					if s.conn.RemoteAddr() == *srcNodeID {
 | 
			
		||||
						// This is the one allowed CKR case, where source and destination addresses are both good
 | 
			
		||||
					} else {
 | 
			
		||||
						// The CKR key associated with this address doesn't match the sender's NodeID
 | 
			
		||||
						skip = true
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					// We have no CKR route for this source address
 | 
			
		||||
					skip = true
 | 
			
		||||
				}
 | 
			
		||||
			default:
 | 
			
		||||
				skip = true
 | 
			
		||||
			}
 | 
			
		||||
			if skip {
 | 
			
		||||
				util.PutBytes(bs)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			s.tun.send <- bs
 | 
			
		||||
			s.stillAlive()
 | 
			
		||||
| 
						 | 
				
			
			@ -108,15 +155,62 @@ func (s *tunConn) writer() error {
 | 
			
		|||
			if !ok {
 | 
			
		||||
				return errors.New("send closed")
 | 
			
		||||
			}
 | 
			
		||||
			if bs[0]&0xf0 == 0x60 {
 | 
			
		||||
				switch {
 | 
			
		||||
				case bs[8] == 0x02 && !bytes.Equal(s.tun.addr[:16], bs[8:24]): // source
 | 
			
		||||
				case bs[8] == 0x03 && !bytes.Equal(s.tun.subnet[:8], bs[8:16]): // source
 | 
			
		||||
				case bs[24] == 0x02 && !bytes.Equal(s.addr[:16], bs[24:40]): // destination
 | 
			
		||||
				case bs[24] == 0x03 && !bytes.Equal(s.snet[:8], bs[24:32]): // destination
 | 
			
		||||
					continue
 | 
			
		||||
				default:
 | 
			
		||||
			v4 := len(bs) > 20 && bs[0]&0xf0 == 0x40
 | 
			
		||||
			v6 := len(bs) > 40 && bs[0]&0xf0 == 0x60
 | 
			
		||||
			isCGA := true
 | 
			
		||||
			// Check source addresses
 | 
			
		||||
			switch {
 | 
			
		||||
			case v6 && bs[8] == 0x02 && bytes.Equal(s.tun.addr[:16], bs[8:24]): // source
 | 
			
		||||
			case v6 && bs[8] == 0x03 && bytes.Equal(s.tun.subnet[:8], bs[8:16]): // source
 | 
			
		||||
			default:
 | 
			
		||||
				isCGA = false
 | 
			
		||||
			}
 | 
			
		||||
			// Check destiantion addresses
 | 
			
		||||
			switch {
 | 
			
		||||
			case v6 && bs[24] == 0x02 && bytes.Equal(s.addr[:16], bs[24:40]): // destination
 | 
			
		||||
			case v6 && bs[24] == 0x03 && bytes.Equal(s.snet[:8], bs[24:32]): // destination
 | 
			
		||||
			default:
 | 
			
		||||
				isCGA = false
 | 
			
		||||
			}
 | 
			
		||||
			// Decide how to handle the packet
 | 
			
		||||
			var skip bool
 | 
			
		||||
			switch {
 | 
			
		||||
			case isCGA: // Allowed
 | 
			
		||||
			case s.tun.ckr.isEnabled() && (v4 || v6):
 | 
			
		||||
				var srcAddr address.Address
 | 
			
		||||
				var dstAddr address.Address
 | 
			
		||||
				var addrlen int
 | 
			
		||||
				if v4 {
 | 
			
		||||
					copy(srcAddr[:], bs[12:16])
 | 
			
		||||
					copy(dstAddr[:], bs[16:20])
 | 
			
		||||
					addrlen = 4
 | 
			
		||||
				}
 | 
			
		||||
				if v6 {
 | 
			
		||||
					copy(srcAddr[:], bs[8:24])
 | 
			
		||||
					copy(dstAddr[:], bs[24:40])
 | 
			
		||||
					addrlen = 16
 | 
			
		||||
				}
 | 
			
		||||
				if !s.tun.ckr.isValidLocalAddress(srcAddr, addrlen) {
 | 
			
		||||
					// The source address isn't in our CKR allowed range
 | 
			
		||||
					skip = true
 | 
			
		||||
				} else if key, err := s.tun.ckr.getPublicKeyForAddress(dstAddr, addrlen); err == nil {
 | 
			
		||||
					dstNodeID := crypto.GetNodeID(&key)
 | 
			
		||||
					if s.conn.RemoteAddr() == *dstNodeID {
 | 
			
		||||
						// This is the one allowed CKR case, where source and destination addresses are both good
 | 
			
		||||
					} else {
 | 
			
		||||
						// The CKR key associated with this address doesn't match the sender's NodeID
 | 
			
		||||
						skip = true
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					// We have no CKR route for this destination address... why do we have the packet in the first place?
 | 
			
		||||
					skip = true
 | 
			
		||||
				}
 | 
			
		||||
			default:
 | 
			
		||||
				skip = true
 | 
			
		||||
			}
 | 
			
		||||
			if skip {
 | 
			
		||||
				util.PutBytes(bs)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			msg := yggdrasil.FlowKeyMessage{
 | 
			
		||||
				FlowKey: util.GetFlowKey(bs),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@ package tuntap
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,62 +20,6 @@ func (tun *TunAdapter) writer() error {
 | 
			
		|||
		if n == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		var srcAddr address.Address
 | 
			
		||||
		var dstAddr address.Address
 | 
			
		||||
		var addrlen int
 | 
			
		||||
		// Check whether the packet is IPv4, IPv6 or neither
 | 
			
		||||
		if b[0]&0xf0 == 0x60 {
 | 
			
		||||
			// IPv6 packet found
 | 
			
		||||
			if len(b) < 40 {
 | 
			
		||||
				// Packet was too short
 | 
			
		||||
				util.PutBytes(b)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			// Extract the IPv6 addresses
 | 
			
		||||
			copy(srcAddr[:16], b[8:24])
 | 
			
		||||
			copy(dstAddr[:16], b[24:40])
 | 
			
		||||
			addrlen = 16
 | 
			
		||||
		} else if b[0]&0xf0 == 0x40 {
 | 
			
		||||
			// IPv4 packet found
 | 
			
		||||
			if len(b) < 20 {
 | 
			
		||||
				// Packet was too short
 | 
			
		||||
				util.PutBytes(b)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			// Extract the IPv4 addresses
 | 
			
		||||
			copy(srcAddr[:4], b[12:16])
 | 
			
		||||
			copy(dstAddr[:4], b[16:20])
 | 
			
		||||
			addrlen = 4
 | 
			
		||||
		} else {
 | 
			
		||||
			// Neither IPv4 nor IPv6
 | 
			
		||||
			return errors.New("Invalid address family")
 | 
			
		||||
		}
 | 
			
		||||
		// Check the crypto-key routing rules next
 | 
			
		||||
		if tun.ckr.isEnabled() {
 | 
			
		||||
			if !tun.ckr.isValidLocalAddress(dstAddr, addrlen) {
 | 
			
		||||
				util.PutBytes(b)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if srcAddr[0] != 0x02 && srcAddr[0] != 0x03 {
 | 
			
		||||
				// TODO: is this check useful? this doesn't actually guarantee that the
 | 
			
		||||
				// packet came from the configured public key for that remote, just that
 | 
			
		||||
				// it came from *a* configured remote. at this stage we have no ability
 | 
			
		||||
				// to know which Conn or public key was involved
 | 
			
		||||
				if _, err := tun.ckr.getPublicKeyForAddress(srcAddr, addrlen); err != nil {
 | 
			
		||||
					util.PutBytes(b)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if addrlen != 16 {
 | 
			
		||||
				util.PutBytes(b)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if !bytes.Equal(tun.addr[:16], dstAddr[:16]) && !bytes.Equal(tun.subnet[:8], dstAddr[:8]) {
 | 
			
		||||
				util.PutBytes(b)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if tun.iface.IsTAP() {
 | 
			
		||||
			sendndp := func(dstAddr address.Address) {
 | 
			
		||||
				neigh, known := tun.icmpv6.getNeighbor(dstAddr)
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +29,7 @@ func (tun *TunAdapter) writer() error {
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
			peermac := net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 | 
			
		||||
			var dstAddr address.Address
 | 
			
		||||
			var peerknown bool
 | 
			
		||||
			if b[0]&0xf0 == 0x40 {
 | 
			
		||||
				dstAddr = tun.addr
 | 
			
		||||
| 
						 | 
				
			
			@ -183,10 +127,7 @@ func (tun *TunAdapter) readerPacketHandler(ch chan []byte) {
 | 
			
		|||
		// From the IP header, work out what our source and destination addresses
 | 
			
		||||
		// and node IDs are. We will need these in order to work out where to send
 | 
			
		||||
		// the packet
 | 
			
		||||
		var srcAddr address.Address
 | 
			
		||||
		var dstAddr address.Address
 | 
			
		||||
		var dstNodeID *crypto.NodeID
 | 
			
		||||
		var dstNodeIDMask *crypto.NodeID
 | 
			
		||||
		var dstSnet address.Subnet
 | 
			
		||||
		var addrlen int
 | 
			
		||||
		n := len(bs)
 | 
			
		||||
| 
						 | 
				
			
			@ -203,7 +144,6 @@ func (tun *TunAdapter) readerPacketHandler(ch chan []byte) {
 | 
			
		|||
			}
 | 
			
		||||
			// IPv6 address
 | 
			
		||||
			addrlen = 16
 | 
			
		||||
			copy(srcAddr[:addrlen], bs[8:])
 | 
			
		||||
			copy(dstAddr[:addrlen], bs[24:])
 | 
			
		||||
			copy(dstSnet[:addrlen/2], bs[24:])
 | 
			
		||||
		} else if bs[0]&0xf0 == 0x40 {
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +157,6 @@ func (tun *TunAdapter) readerPacketHandler(ch chan []byte) {
 | 
			
		|||
			}
 | 
			
		||||
			// IPv4 address
 | 
			
		||||
			addrlen = 4
 | 
			
		||||
			copy(srcAddr[:addrlen], bs[12:])
 | 
			
		||||
			copy(dstAddr[:addrlen], bs[16:])
 | 
			
		||||
		} else {
 | 
			
		||||
			// Unknown address length or protocol, so drop the packet and ignore it
 | 
			
		||||
| 
						 | 
				
			
			@ -225,36 +164,22 @@ func (tun *TunAdapter) readerPacketHandler(ch chan []byte) {
 | 
			
		|||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if tun.ckr.isEnabled() {
 | 
			
		||||
			if !tun.ckr.isValidLocalAddress(srcAddr, addrlen) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if !dstAddr.IsValid() && !dstSnet.IsValid() {
 | 
			
		||||
			if addrlen != 16 || (!dstAddr.IsValid() && !dstSnet.IsValid()) {
 | 
			
		||||
				if key, err := tun.ckr.getPublicKeyForAddress(dstAddr, addrlen); err == nil {
 | 
			
		||||
					// A public key was found, get the node ID for the search
 | 
			
		||||
					dstNodeID = crypto.GetNodeID(&key)
 | 
			
		||||
					// Do a quick check to ensure that the node ID refers to a vaild
 | 
			
		||||
					// Yggdrasil address or subnet - this might be superfluous
 | 
			
		||||
					addr := *address.AddrForNodeID(dstNodeID)
 | 
			
		||||
					copy(dstAddr[:], addr[:])
 | 
			
		||||
					copy(dstSnet[:], addr[:])
 | 
			
		||||
					// Are we certain we looked up a valid node?
 | 
			
		||||
					if !dstAddr.IsValid() && !dstSnet.IsValid() {
 | 
			
		||||
						continue
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					// No public key was found in the CKR table so we've exhausted our options
 | 
			
		||||
					continue
 | 
			
		||||
					dstNodeID := crypto.GetNodeID(&key)
 | 
			
		||||
					dstAddr = *address.AddrForNodeID(dstNodeID)
 | 
			
		||||
					dstSnet = *address.SubnetForNodeID(dstNodeID)
 | 
			
		||||
					addrlen = 16
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if addrlen != 16 {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if !dstAddr.IsValid() && !dstSnet.IsValid() {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if addrlen != 16 || (!dstAddr.IsValid() && !dstSnet.IsValid()) {
 | 
			
		||||
			// Couldn't find this node's ygg IP
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		// Do we have an active connection for this node address?
 | 
			
		||||
		var dstNodeID, dstNodeIDMask *crypto.NodeID
 | 
			
		||||
		tun.mutex.RLock()
 | 
			
		||||
		session, isIn := tun.addrToConn[dstAddr]
 | 
			
		||||
		if !isIn || session == nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue