mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-26 07:11:40 +00:00
Merge branch 'develop' into ios
This commit is contained in:
commit
30df632eb2
@ -227,11 +227,6 @@ func main() {
|
|||||||
logger.Println("An error occurred during startup")
|
logger.Println("An error occurred during startup")
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
// Check to see if any allowed encryption keys were provided in the config.
|
|
||||||
// If they were then set them now.
|
|
||||||
for _, pBoxStr := range cfg.AllowedEncryptionPublicKeys {
|
|
||||||
n.core.AddAllowedEncryptionPublicKey(pBoxStr)
|
|
||||||
}
|
|
||||||
// The Stop function ensures that the TUN/TAP adapter is correctly shut down
|
// The Stop function ensures that the TUN/TAP adapter is correctly shut down
|
||||||
// before the program exits.
|
// before the program exits.
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -765,35 +765,20 @@ func (a *admin) getData_getSessions() []admin_nodeInfo {
|
|||||||
|
|
||||||
// getAllowedEncryptionPublicKeys returns the public keys permitted for incoming peer connections.
|
// getAllowedEncryptionPublicKeys returns the public keys permitted for incoming peer connections.
|
||||||
func (a *admin) getAllowedEncryptionPublicKeys() []string {
|
func (a *admin) getAllowedEncryptionPublicKeys() []string {
|
||||||
pubs := a.core.peers.getAllowedEncryptionPublicKeys()
|
return a.core.peers.getAllowedEncryptionPublicKeys()
|
||||||
var out []string
|
|
||||||
for _, pub := range pubs {
|
|
||||||
out = append(out, hex.EncodeToString(pub[:]))
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// addAllowedEncryptionPublicKey whitelists a key for incoming peer connections.
|
// addAllowedEncryptionPublicKey whitelists a key for incoming peer connections.
|
||||||
func (a *admin) addAllowedEncryptionPublicKey(bstr string) (err error) {
|
func (a *admin) addAllowedEncryptionPublicKey(bstr string) (err error) {
|
||||||
boxBytes, err := hex.DecodeString(bstr)
|
a.core.peers.addAllowedEncryptionPublicKey(bstr)
|
||||||
if err == nil {
|
return nil
|
||||||
var box crypto.BoxPubKey
|
|
||||||
copy(box[:], boxBytes)
|
|
||||||
a.core.peers.addAllowedEncryptionPublicKey(&box)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// removeAllowedEncryptionPublicKey removes a key from the whitelist for incoming peer connections.
|
// removeAllowedEncryptionPublicKey removes a key from the whitelist for incoming peer connections.
|
||||||
// If none are set, an empty list permits all incoming connections.
|
// If none are set, an empty list permits all incoming connections.
|
||||||
func (a *admin) removeAllowedEncryptionPublicKey(bstr string) (err error) {
|
func (a *admin) removeAllowedEncryptionPublicKey(bstr string) (err error) {
|
||||||
boxBytes, err := hex.DecodeString(bstr)
|
a.core.peers.removeAllowedEncryptionPublicKey(bstr)
|
||||||
if err == nil {
|
return nil
|
||||||
var box crypto.BoxPubKey
|
|
||||||
copy(box[:], boxBytes)
|
|
||||||
a.core.peers.removeAllowedEncryptionPublicKey(&box)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a DHT ping to the node with the provided key and coords, optionally looking up the specified target NodeID.
|
// Send a DHT ping to the node with the provided key and coords, optionally looking up the specified target NodeID.
|
||||||
|
@ -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
|
||||||
|
@ -5,6 +5,7 @@ package yggdrasil
|
|||||||
// Live code should be better commented
|
// Live code should be better commented
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@ -18,12 +19,10 @@ import (
|
|||||||
// In most cases, this involves passing the packet to the handler for outgoing traffic to another peer.
|
// In most cases, this involves passing the packet to the handler for outgoing traffic to another peer.
|
||||||
// In other cases, it's link protocol traffic used to build the spanning tree, in which case this checks signatures and passes the message along to the switch.
|
// In other cases, it's link protocol traffic used to build the spanning tree, in which case this checks signatures and passes the message along to the switch.
|
||||||
type peers struct {
|
type peers struct {
|
||||||
core *Core
|
core *Core
|
||||||
reconfigure chan chan error
|
reconfigure chan chan error
|
||||||
mutex sync.Mutex // Synchronize writes to atomic
|
mutex sync.Mutex // Synchronize writes to atomic
|
||||||
ports atomic.Value //map[switchPort]*peer, use CoW semantics
|
ports atomic.Value //map[switchPort]*peer, use CoW semantics
|
||||||
authMutex sync.RWMutex
|
|
||||||
allowedEncryptionPublicKeys map[crypto.BoxPubKey]struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the peers struct.
|
// Initializes the peers struct.
|
||||||
@ -39,40 +38,48 @@ func (ps *peers) init(c *Core) {
|
|||||||
e <- nil
|
e <- nil
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
ps.allowedEncryptionPublicKeys = make(map[crypto.BoxPubKey]struct{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if an incoming peer connection to a key is allowed, either because the key is in the whitelist or because the whitelist is empty.
|
// Returns true if an incoming peer connection to a key is allowed, either
|
||||||
|
// because the key is in the whitelist or because the whitelist is empty.
|
||||||
func (ps *peers) isAllowedEncryptionPublicKey(box *crypto.BoxPubKey) bool {
|
func (ps *peers) isAllowedEncryptionPublicKey(box *crypto.BoxPubKey) bool {
|
||||||
ps.authMutex.RLock()
|
boxstr := hex.EncodeToString(box[:])
|
||||||
defer ps.authMutex.RUnlock()
|
ps.core.configMutex.RLock()
|
||||||
_, isIn := ps.allowedEncryptionPublicKeys[*box]
|
defer ps.core.configMutex.RUnlock()
|
||||||
return isIn || len(ps.allowedEncryptionPublicKeys) == 0
|
for _, v := range ps.core.config.AllowedEncryptionPublicKeys {
|
||||||
|
if v == boxstr {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(ps.core.config.AllowedEncryptionPublicKeys) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a key to the whitelist.
|
// Adds a key to the whitelist.
|
||||||
func (ps *peers) addAllowedEncryptionPublicKey(box *crypto.BoxPubKey) {
|
func (ps *peers) addAllowedEncryptionPublicKey(box string) {
|
||||||
ps.authMutex.Lock()
|
ps.core.configMutex.RLock()
|
||||||
defer ps.authMutex.Unlock()
|
defer ps.core.configMutex.RUnlock()
|
||||||
ps.allowedEncryptionPublicKeys[*box] = struct{}{}
|
ps.core.config.AllowedEncryptionPublicKeys =
|
||||||
|
append(ps.core.config.AllowedEncryptionPublicKeys, box)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a key from the whitelist.
|
// Removes a key from the whitelist.
|
||||||
func (ps *peers) removeAllowedEncryptionPublicKey(box *crypto.BoxPubKey) {
|
func (ps *peers) removeAllowedEncryptionPublicKey(box string) {
|
||||||
ps.authMutex.Lock()
|
ps.core.configMutex.RLock()
|
||||||
defer ps.authMutex.Unlock()
|
defer ps.core.configMutex.RUnlock()
|
||||||
delete(ps.allowedEncryptionPublicKeys, *box)
|
for k, v := range ps.core.config.AllowedEncryptionPublicKeys {
|
||||||
|
if v == box {
|
||||||
|
ps.core.config.AllowedEncryptionPublicKeys =
|
||||||
|
append(ps.core.config.AllowedEncryptionPublicKeys[:k],
|
||||||
|
ps.core.config.AllowedEncryptionPublicKeys[k+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the whitelist of allowed keys for incoming connections.
|
// Gets the whitelist of allowed keys for incoming connections.
|
||||||
func (ps *peers) getAllowedEncryptionPublicKeys() []crypto.BoxPubKey {
|
func (ps *peers) getAllowedEncryptionPublicKeys() []string {
|
||||||
ps.authMutex.RLock()
|
ps.core.configMutex.RLock()
|
||||||
defer ps.authMutex.RUnlock()
|
defer ps.core.configMutex.RUnlock()
|
||||||
keys := make([]crypto.BoxPubKey, 0, len(ps.allowedEncryptionPublicKeys))
|
return ps.core.config.AllowedEncryptionPublicKeys
|
||||||
for key := range ps.allowedEncryptionPublicKeys {
|
|
||||||
keys = append(keys, key)
|
|
||||||
}
|
|
||||||
return keys
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atomically gets a map[switchPort]*peer of known peers.
|
// Atomically gets a map[switchPort]*peer of known peers.
|
||||||
|
@ -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()
|
||||||
|
@ -245,15 +245,27 @@ func (iface *tcpInterface) call(saddr string, socksaddr *string, sintf string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (src.To4() != nil) == (dst.IP.To4() != nil) {
|
if src.Equal(dst.IP) {
|
||||||
if addrindex == len(addrs)-1 || src.IsGlobalUnicast() {
|
continue
|
||||||
dialer.LocalAddr = &net.TCPAddr{
|
}
|
||||||
IP: src,
|
if !src.IsGlobalUnicast() && !src.IsLinkLocalUnicast() {
|
||||||
Port: 0,
|
continue
|
||||||
Zone: sintf,
|
}
|
||||||
}
|
bothglobal := src.IsGlobalUnicast() == dst.IP.IsGlobalUnicast()
|
||||||
break
|
bothlinklocal := src.IsLinkLocalUnicast() == dst.IP.IsLinkLocalUnicast()
|
||||||
|
if !bothglobal && !bothlinklocal {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (src.To4() != nil) != (dst.IP.To4() != nil) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if bothglobal || bothlinklocal || addrindex == len(addrs)-1 {
|
||||||
|
dialer.LocalAddr = &net.TCPAddr{
|
||||||
|
IP: src,
|
||||||
|
Port: 0,
|
||||||
|
Zone: sintf,
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dialer.LocalAddr == nil {
|
if dialer.LocalAddr == nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user