mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-12-26 21:45:41 +00:00
move ckr checks into the tunConn code
This commit is contained in:
parent
b79829c43b
commit
4156aa3003
@ -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…
Reference in New Issue
Block a user