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

This commit is contained in:
Arceliar 2021-05-15 15:55:47 -05:00
parent 7e10025ef0
commit 5b00273dfc
4 changed files with 29 additions and 27 deletions

View File

@ -2,6 +2,7 @@ package main
import ( import (
"bytes" "bytes"
"crypto/ed25519"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"flag" "flag"
@ -277,11 +278,11 @@ func main() {
panic(err) panic(err)
} }
// Register the session firewall gatekeeper function // Register the session firewall gatekeeper function
// TODO n.core.SetSessionGatekeeper(n.sessionFirewall)
// Allocate our modules // Allocate our modules
n.admin = &admin.AdminSocket{} n.admin = &admin.AdminSocket{}
n.multicast = &multicast.Multicast{} n.multicast = &multicast.Multicast{}
n.tuntap = &tuntap.TunAdapter{} n.tuntap = &tuntap.TunAdapter{}
n.tuntap.(*tuntap.TunAdapter).SetSessionGatekeeper(n.sessionFirewall)
// Start the admin socket // Start the admin socket
n.admin.Init(&n.core, n.state, logger, nil) n.admin.Init(&n.core, n.state, logger, nil)
if err := n.admin.Start(); err != nil { if err := n.admin.Start(); err != nil {
@ -300,21 +301,6 @@ func main() {
logger.Errorln("An error occurred starting TUN/TAP:", err) logger.Errorln("An error occurred starting TUN/TAP:", err)
} }
n.tuntap.SetupAdminHandlers(n.admin.(*admin.AdminSocket)) 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. // Make some nice output that tells us what our IPv6 address and subnet are.
// This is just logged to stdout for the user. // This is just logged to stdout for the user.
address := n.core.Address() address := n.core.Address()
@ -337,7 +323,7 @@ func (n *node) shutdown() {
n.core.Stop() 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() n.state.Mutex.RLock()
defer n.state.Mutex.RUnlock() defer n.state.Mutex.RUnlock()
@ -346,14 +332,11 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
return true return true
} }
// Prepare for checking whitelist/blacklist
var box crypto.BoxPubKey
// Reject blacklisted nodes // Reject blacklisted nodes
for _, b := range n.state.Current.SessionFirewall.BlacklistPublicKeys { for _, b := range n.state.Current.SessionFirewall.BlacklistPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
copy(box[:crypto.BoxPubKeyLen], key) if bytes.Equal(key, pubkey) {
if box == *pubkey {
return false return false
} }
} }
@ -363,8 +346,7 @@ func (n *node) sessionFirewall(pubkey *crypto.BoxPubKey, initiator bool) bool {
for _, b := range n.state.Current.SessionFirewall.WhitelistPublicKeys { for _, b := range n.state.Current.SessionFirewall.WhitelistPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
copy(box[:crypto.BoxPubKeyLen], key) if bytes.Equal(key, pubkey) {
if box == *pubkey {
return true 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 // Look and see if the pubkey is that of a direct peer
var isDirectPeer bool var isDirectPeer bool
/* TODO
for _, peer := range n.core.GetPeers() { for _, peer := range n.core.GetPeers() {
if peer.PublicKey == *pubkey { if bytes.Equal(peer.Key[:], pubkey[:]) {
isDirectPeer = true isDirectPeer = true
break break
} }
} }
*/
// Allow direct peers if appropriate // Allow direct peers if appropriate
if n.state.Current.SessionFirewall.AllowFromDirect && isDirectPeer { if n.state.Current.SessionFirewall.AllowFromDirect && isDirectPeer {

View File

@ -93,6 +93,9 @@ func (tun *TunAdapter) write() {
continue // bad local address/subnet continue // bad local address/subnet
} }
info := tun.store.update(ed25519.PublicKey(from.(iwt.Addr))) info := tun.store.update(ed25519.PublicKey(from.(iwt.Addr)))
if info == nil {
continue // Blocked by the gatekeeper
}
if srcAddr != info.address && srcSubnet != info.subnet { if srcAddr != info.address && srcSubnet != info.subnet {
continue // bad remote address/subnet continue // bad remote address/subnet
} }

View File

@ -115,6 +115,18 @@ func (k *keyStore) update(key ed25519.PublicKey) *keyInfo {
info.address = *address.AddrForKey(ed25519.PublicKey(info.key[:])) info.address = *address.AddrForKey(ed25519.PublicKey(info.key[:]))
info.subnet = *address.SubnetForKey(ed25519.PublicKey(info.key[:])) info.subnet = *address.SubnetForKey(ed25519.PublicKey(info.key[:]))
info.mtu = MTU(^uint16(0)) // TODO 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.keyToInfo[info.key] = info
k.addrToInfo[info.address] = info k.addrToInfo[info.address] = info
k.subnetToInfo[info.subnet] = info k.subnetToInfo[info.subnet] = info

View File

@ -45,6 +45,13 @@ type TunAdapter struct {
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below 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 //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 // Gets the maximum supported MTU for the platform based on the defaults in