From 5b00273dfcaed74160cc690b994cfe6d93f42a23 Mon Sep 17 00:00:00 2001 From: Arceliar Date: Sat, 15 May 2021 15:55:47 -0500 Subject: [PATCH] move sessionfirewall into the tuntap. this needs testing. the name is also slightly wrong, since a crypto session can still be set up, packets are just accepted/rejected at the tun/tap level instead --- cmd/yggdrasil/main.go | 32 ++++++-------------------------- src/tuntap/iface.go | 3 +++ src/tuntap/keystore.go | 12 ++++++++++++ src/tuntap/tun.go | 9 ++++++++- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go index f315825..11310f7 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/yggdrasil/main.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "crypto/ed25519" "encoding/hex" "encoding/json" "flag" @@ -277,11 +278,11 @@ func main() { panic(err) } // Register the session firewall gatekeeper function - // TODO n.core.SetSessionGatekeeper(n.sessionFirewall) // Allocate our modules n.admin = &admin.AdminSocket{} n.multicast = &multicast.Multicast{} n.tuntap = &tuntap.TunAdapter{} + n.tuntap.(*tuntap.TunAdapter).SetSessionGatekeeper(n.sessionFirewall) // Start the admin socket n.admin.Init(&n.core, n.state, logger, nil) if err := n.admin.Start(); err != nil { @@ -300,21 +301,6 @@ func main() { logger.Errorln("An error occurred starting TUN/TAP:", err) } n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) - /* - if listener, err := n.core.ConnListen(); err == nil { - if dialer, err := n.core.ConnDialer(); err == nil { - n.tuntap.Init(&n.core, n.state, logger, tuntap.TunOptions{Listener: listener, Dialer: dialer}) - if err := n.tuntap.Start(); err != nil { - logger.Errorln("An error occurred starting TUN/TAP:", err) - } - n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) - } else { - logger.Errorln("Unable to get Dialer:", err) - } - } else { - logger.Errorln("Unable to get Listener:", err) - } - */ // Make some nice output that tells us what our IPv6 address and subnet are. // This is just logged to stdout for the user. address := n.core.Address() @@ -337,7 +323,7 @@ func (n *node) shutdown() { n.core.Stop() } -func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool { +func (n *node) sessionFirewall(pubkey ed25519.PublicKey, initiator bool) bool { n.state.Mutex.RLock() defer n.state.Mutex.RUnlock() @@ -346,14 +332,11 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool { return true } - // Prepare for checking whitelist/blacklist - var box crypto.BoxPubKey // Reject blacklisted nodes for _, b := range n.state.Current.SessionFirewall.BlacklistPublicKeys { key, err := hex.DecodeString(b) if err == nil { - copy(box[:crypto.BoxPubKeyLen], key) - if box == *pubkey { + if bytes.Equal(key, pubkey) { return false } } @@ -363,8 +346,7 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool { for _, b := range n.state.Current.SessionFirewall.WhitelistPublicKeys { key, err := hex.DecodeString(b) if err == nil { - copy(box[:crypto.BoxPubKeyLen], key) - if box == *pubkey { + if bytes.Equal(key, pubkey) { return true } } @@ -379,14 +361,12 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool { // Look and see if the pubkey is that of a direct peer var isDirectPeer bool - /* TODO for _, peer := range n.core.GetPeers() { - if peer.PublicKey == *pubkey { + if bytes.Equal(peer.Key[:], pubkey[:]) { isDirectPeer = true break } } - */ // Allow direct peers if appropriate if n.state.Current.SessionFirewall.AllowFromDirect && isDirectPeer { diff --git a/src/tuntap/iface.go b/src/tuntap/iface.go index af76dac..d2680d0 100644 --- a/src/tuntap/iface.go +++ b/src/tuntap/iface.go @@ -93,6 +93,9 @@ func (tun *TunAdapter) write() { continue // bad local address/subnet } info := tun.store.update(ed25519.PublicKey(from.(iwt.Addr))) + if info == nil { + continue // Blocked by the gatekeeper + } if srcAddr != info.address && srcSubnet != info.subnet { continue // bad remote address/subnet } diff --git a/src/tuntap/keystore.go b/src/tuntap/keystore.go index ddcf50c..a930630 100644 --- a/src/tuntap/keystore.go +++ b/src/tuntap/keystore.go @@ -115,6 +115,18 @@ func (k *keyStore) update(key ed25519.PublicKey) *keyInfo { info.address = *address.AddrForKey(ed25519.PublicKey(info.key[:])) info.subnet = *address.SubnetForKey(ed25519.PublicKey(info.key[:])) info.mtu = MTU(^uint16(0)) // TODO + var isOutgoing bool + if k.addrBuffer[info.address] != nil { + isOutgoing = true + } + if k.subnetBuffer[info.subnet] != nil { + isOutgoing = true + } + if !k.tun.gatekeeper(key, isOutgoing) { + // Blocked by the gatekeeper, so don't create an entry for this + k.mutex.Unlock() + return nil + } k.keyToInfo[info.key] = info k.addrToInfo[info.address] = info k.subnetToInfo[info.subnet] = info diff --git a/src/tuntap/tun.go b/src/tuntap/tun.go index 1cc1fde..79736a0 100644 --- a/src/tuntap/tun.go +++ b/src/tuntap/tun.go @@ -44,7 +44,14 @@ type TunAdapter struct { iface tun.Device phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below //mutex sync.RWMutex // Protects the below - isOpen bool + isOpen bool + gatekeeper func(pubkey ed25519.PublicKey, initiator bool) bool +} + +func (tun *TunAdapter) SetSessionGatekeeper(gatekeeper func(pubkey ed25519.PublicKey, initiator bool) bool) { + phony.Block(tun, func() { + tun.gatekeeper = gatekeeper + }) } // Gets the maximum supported MTU for the platform based on the defaults in