Handle session firewall using central config

This commit is contained in:
Neil Alexander 2019-01-16 20:38:51 +00:00
parent fdf300a1ff
commit 9d5085492e
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
2 changed files with 14 additions and 58 deletions

View File

@ -212,15 +212,6 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
return err return err
} }
c.sessions.setSessionFirewallState(nc.SessionFirewall.Enable)
c.sessions.setSessionFirewallDefaults(
nc.SessionFirewall.AllowFromDirect,
nc.SessionFirewall.AllowFromRemote,
nc.SessionFirewall.AlwaysAllowOutbound,
)
c.sessions.setSessionFirewallWhitelist(nc.SessionFirewall.WhitelistEncryptionPublicKeys)
c.sessions.setSessionFirewallBlacklist(nc.SessionFirewall.BlacklistEncryptionPublicKeys)
if err := c.router.start(); err != nil { if err := c.router.start(); err != nil {
c.log.Println("Failed to start router") c.log.Println("Failed to start router")
return err return err

View File

@ -7,7 +7,6 @@ package yggdrasil
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"sync"
"time" "time"
"github.com/yggdrasil-network/yggdrasil-go/src/address" "github.com/yggdrasil-network/yggdrasil-go/src/address"
@ -115,14 +114,6 @@ type sessions struct {
byTheirPerm map[crypto.BoxPubKey]*crypto.Handle byTheirPerm map[crypto.BoxPubKey]*crypto.Handle
addrToPerm map[address.Address]*crypto.BoxPubKey addrToPerm map[address.Address]*crypto.BoxPubKey
subnetToPerm map[address.Subnet]*crypto.BoxPubKey subnetToPerm map[address.Subnet]*crypto.BoxPubKey
// Options from the session firewall
sessionFirewallMutex sync.RWMutex
sessionFirewallEnabled bool
sessionFirewallAllowsDirect bool
sessionFirewallAllowsRemote bool
sessionFirewallAlwaysAllowsOutbound bool
sessionFirewallWhitelist []string
sessionFirewallBlacklist []string
} }
// Initializes the session struct. // Initializes the session struct.
@ -155,51 +146,28 @@ func (ss *sessions) init(core *Core) {
ss.lastCleanup = time.Now() ss.lastCleanup = time.Now()
} }
// Enable or disable the session firewall // Determines whether the session firewall is enabled.
func (ss *sessions) setSessionFirewallState(enabled bool) { func (ss *sessions) isSessionFirewallEnabled() bool {
ss.sessionFirewallMutex.Lock() ss.core.configMutex.RLock()
defer ss.sessionFirewallMutex.Unlock() defer ss.core.configMutex.RUnlock()
ss.sessionFirewallEnabled = enabled
}
// Set the session firewall defaults (first parameter is whether to allow return ss.core.config.SessionFirewall.Enable
// sessions from direct peers, second is whether to allow from remote nodes).
func (ss *sessions) setSessionFirewallDefaults(allowsDirect bool, allowsRemote bool, alwaysAllowsOutbound bool) {
ss.sessionFirewallMutex.Lock()
defer ss.sessionFirewallMutex.Unlock()
ss.sessionFirewallAllowsDirect = allowsDirect
ss.sessionFirewallAllowsRemote = allowsRemote
ss.sessionFirewallAlwaysAllowsOutbound = alwaysAllowsOutbound
}
// Set the session firewall whitelist - nodes always allowed to open sessions.
func (ss *sessions) setSessionFirewallWhitelist(whitelist []string) {
ss.sessionFirewallMutex.Lock()
defer ss.sessionFirewallMutex.Unlock()
ss.sessionFirewallWhitelist = whitelist
}
// Set the session firewall blacklist - nodes never allowed to open sessions.
func (ss *sessions) setSessionFirewallBlacklist(blacklist []string) {
ss.sessionFirewallMutex.Lock()
defer ss.sessionFirewallMutex.Unlock()
ss.sessionFirewallBlacklist = blacklist
} }
// Determines whether the session with a given publickey is allowed based on // Determines whether the session with a given publickey is allowed based on
// session firewall rules. // session firewall rules.
func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) bool { func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) bool {
ss.sessionFirewallMutex.RLock() ss.core.configMutex.RLock()
defer ss.sessionFirewallMutex.RUnlock() defer ss.core.configMutex.RUnlock()
// Allow by default if the session firewall is disabled // Allow by default if the session firewall is disabled
if !ss.sessionFirewallEnabled { if !ss.isSessionFirewallEnabled() {
return true return true
} }
// Prepare for checking whitelist/blacklist // Prepare for checking whitelist/blacklist
var box crypto.BoxPubKey var box crypto.BoxPubKey
// Reject blacklisted nodes // Reject blacklisted nodes
for _, b := range ss.sessionFirewallBlacklist { for _, b := range ss.core.config.SessionFirewall.BlacklistEncryptionPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
copy(box[:crypto.BoxPubKeyLen], key) copy(box[:crypto.BoxPubKeyLen], key)
@ -209,7 +177,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
} }
} }
// Allow whitelisted nodes // Allow whitelisted nodes
for _, b := range ss.sessionFirewallWhitelist { for _, b := range ss.core.config.SessionFirewall.WhitelistEncryptionPublicKeys {
key, err := hex.DecodeString(b) key, err := hex.DecodeString(b)
if err == nil { if err == nil {
copy(box[:crypto.BoxPubKeyLen], key) copy(box[:crypto.BoxPubKeyLen], key)
@ -219,7 +187,7 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
} }
} }
// Allow outbound sessions if appropriate // Allow outbound sessions if appropriate
if ss.sessionFirewallAlwaysAllowsOutbound { if ss.core.config.SessionFirewall.AlwaysAllowOutbound {
if initiator { if initiator {
return true return true
} }
@ -233,11 +201,11 @@ func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) b
} }
} }
// Allow direct peers if appropriate // Allow direct peers if appropriate
if ss.sessionFirewallAllowsDirect && isDirectPeer { if ss.core.config.SessionFirewall.AllowFromDirect && isDirectPeer {
return true return true
} }
// Allow remote nodes if appropriate // Allow remote nodes if appropriate
if ss.sessionFirewallAllowsRemote && !isDirectPeer { if ss.core.config.SessionFirewall.AllowFromRemote && !isDirectPeer {
return true return true
} }
// Finally, default-deny if not matching any of the above rules // Finally, default-deny if not matching any of the above rules
@ -474,14 +442,11 @@ func (ss *sessions) handlePing(ping *sessionPing) {
// Get the corresponding session (or create a new session) // Get the corresponding session (or create a new session)
sinfo, isIn := ss.getByTheirPerm(&ping.SendPermPub) sinfo, isIn := ss.getByTheirPerm(&ping.SendPermPub)
// Check the session firewall // Check the session firewall
ss.sessionFirewallMutex.RLock() if !isIn && ss.isSessionFirewallEnabled() {
if !isIn && ss.sessionFirewallEnabled {
if !ss.isSessionAllowed(&ping.SendPermPub, false) { if !ss.isSessionAllowed(&ping.SendPermPub, false) {
ss.sessionFirewallMutex.RUnlock()
return return
} }
} }
ss.sessionFirewallMutex.RUnlock()
if !isIn || sinfo.timedout() { if !isIn || sinfo.timedout() {
if isIn { if isIn {
sinfo.close() sinfo.close()