mirror of
https://github.com/yggdrasil-network/yggdrasil-go
synced 2024-11-09 23:20:26 +03:00
Optional peer authentication, if non-empty then incoming TCP and all UDP peers must match one of these box keys
This commit is contained in:
parent
5962d009a5
commit
6026e0a014
@ -5,6 +5,7 @@ type NodeConfig struct {
|
||||
Listen string
|
||||
AdminListen string
|
||||
Peers []string
|
||||
PeerBoxPubs []string
|
||||
BoxPub string
|
||||
BoxPriv string
|
||||
SigPub string
|
||||
|
@ -397,6 +397,12 @@ func (c *Core) DEBUG_setIfceExpr(expr *regexp.Regexp) {
|
||||
c.ifceExpr = expr
|
||||
}
|
||||
|
||||
func (c *Core) DEBUG_addAuthBoxPub(boxBytes []byte) {
|
||||
var box boxPubKey
|
||||
copy(box[:], boxBytes)
|
||||
c.peers.authBoxPubs[box] = struct{}{}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func DEBUG_simLinkPeers(p, q *peer) {
|
||||
|
@ -31,6 +31,7 @@ import "math"
|
||||
|
||||
type peers struct {
|
||||
core *Core
|
||||
authBoxPubs map[boxPubKey]struct{}
|
||||
mutex sync.Mutex // Synchronize writes to atomic
|
||||
ports atomic.Value //map[Port]*peer, use CoW semantics
|
||||
//ports map[Port]*peer
|
||||
@ -41,6 +42,12 @@ func (ps *peers) init(c *Core) {
|
||||
defer ps.mutex.Unlock()
|
||||
ps.putPorts(make(map[switchPort]*peer))
|
||||
ps.core = c
|
||||
ps.authBoxPubs = make(map[boxPubKey]struct{})
|
||||
}
|
||||
|
||||
func (ps *peers) isAuthBoxPub(box *boxPubKey) bool {
|
||||
_, isIn := ps.authBoxPubs[*box]
|
||||
return isIn || len(ps.authBoxPubs) == 0
|
||||
}
|
||||
|
||||
func (ps *peers) getPorts() map[switchPort]*peer {
|
||||
|
@ -62,7 +62,7 @@ func (iface *tcpInterface) listener() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go iface.handler(sock)
|
||||
go iface.handler(sock, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ func (iface *tcpInterface) callWithConn(conn net.Conn) {
|
||||
delete(iface.calls, raddr)
|
||||
iface.mutex.Unlock()
|
||||
}()
|
||||
iface.handler(conn)
|
||||
iface.handler(conn, false)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@ -106,12 +106,12 @@ func (iface *tcpInterface) call(saddr string) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
iface.handler(conn)
|
||||
iface.handler(conn, false)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (iface *tcpInterface) handler(sock net.Conn) {
|
||||
func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
|
||||
defer sock.Close()
|
||||
// Get our keys
|
||||
keys := []byte{}
|
||||
@ -150,6 +150,15 @@ func (iface *tcpInterface) handler(sock net.Conn) {
|
||||
if equiv(info.sig[:], iface.core.sigPub[:]) {
|
||||
return
|
||||
}
|
||||
// Check if we're authorized to connect to this key / IP
|
||||
if incoming && !iface.core.peers.isAuthBoxPub(&info.box) {
|
||||
// Allow unauthorized peers if they're link-local
|
||||
raddrStr, _, _ := net.SplitHostPort(sock.RemoteAddr().String())
|
||||
raddr := net.ParseIP(raddrStr)
|
||||
if !raddr.IsLinkLocalUnicast() {
|
||||
return
|
||||
}
|
||||
}
|
||||
// Check if we already have a connection to this node, close and block if yes
|
||||
info.localAddr, _, _ = net.SplitHostPort(sock.LocalAddr().String())
|
||||
info.remoteAddr, _, _ = net.SplitHostPort(sock.RemoteAddr().String())
|
||||
|
@ -204,6 +204,14 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
|
||||
iface.mutex.RUnlock()
|
||||
if !isIn {
|
||||
udpAddr := addr.toUDPAddr()
|
||||
// Check if we're authorized to connect to this key / IP
|
||||
// TODO monitor and always allow outgoing connections
|
||||
if !iface.core.peers.isAuthBoxPub(&ks.box) {
|
||||
// Allow unauthorized peers if they're link-local
|
||||
if !udpAddr.IP.IsLinkLocalUnicast() {
|
||||
return
|
||||
}
|
||||
}
|
||||
themNodeID := getNodeID(&ks.box)
|
||||
themAddr := address_addrForNodeID(themNodeID)
|
||||
themAddrString := net.IP(themAddr[:]).String()
|
||||
|
@ -58,6 +58,13 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
|
||||
panic(err)
|
||||
}
|
||||
n.core.DEBUG_setIfceExpr(ifceExpr)
|
||||
for _, pBoxStr := range cfg.PeerBoxPubs {
|
||||
pbox, err := hex.DecodeString(pBoxStr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
n.core.DEBUG_addAuthBoxPub(pbox)
|
||||
}
|
||||
|
||||
logger.Println("Starting interface...")
|
||||
n.core.DEBUG_setupAndStartGlobalTCPInterface(cfg.Listen) // Listen for peers on TCP
|
||||
|
Loading…
Reference in New Issue
Block a user