5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-14 03:20:28 +00: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:
Arceliar 2018-05-06 16:32:34 -05:00
parent 5962d009a5
commit 6026e0a014
6 changed files with 45 additions and 7 deletions

View File

@ -5,6 +5,7 @@ type NodeConfig struct {
Listen string
AdminListen string
Peers []string
PeerBoxPubs []string
BoxPub string
BoxPriv string
SigPub string

View File

@ -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) {

View File

@ -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 {

View File

@ -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())

View File

@ -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()

View File

@ -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