mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 11:15:07 +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
					
				
					 6 changed files with 45 additions and 7 deletions
				
			
		| 
						 | 
					@ -5,6 +5,7 @@ type NodeConfig struct {
 | 
				
			||||||
	Listen      string
 | 
						Listen      string
 | 
				
			||||||
	AdminListen string
 | 
						AdminListen string
 | 
				
			||||||
	Peers       []string
 | 
						Peers       []string
 | 
				
			||||||
 | 
						PeerBoxPubs []string
 | 
				
			||||||
	BoxPub      string
 | 
						BoxPub      string
 | 
				
			||||||
	BoxPriv     string
 | 
						BoxPriv     string
 | 
				
			||||||
	SigPub      string
 | 
						SigPub      string
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -397,6 +397,12 @@ func (c *Core) DEBUG_setIfceExpr(expr *regexp.Regexp) {
 | 
				
			||||||
	c.ifceExpr = expr
 | 
						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) {
 | 
					func DEBUG_simLinkPeers(p, q *peer) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ import "math"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type peers struct {
 | 
					type peers struct {
 | 
				
			||||||
	core        *Core
 | 
						core        *Core
 | 
				
			||||||
 | 
						authBoxPubs map[boxPubKey]struct{}
 | 
				
			||||||
	mutex       sync.Mutex   // Synchronize writes to atomic
 | 
						mutex       sync.Mutex   // Synchronize writes to atomic
 | 
				
			||||||
	ports       atomic.Value //map[Port]*peer, use CoW semantics
 | 
						ports       atomic.Value //map[Port]*peer, use CoW semantics
 | 
				
			||||||
	//ports map[Port]*peer
 | 
						//ports map[Port]*peer
 | 
				
			||||||
| 
						 | 
					@ -41,6 +42,12 @@ func (ps *peers) init(c *Core) {
 | 
				
			||||||
	defer ps.mutex.Unlock()
 | 
						defer ps.mutex.Unlock()
 | 
				
			||||||
	ps.putPorts(make(map[switchPort]*peer))
 | 
						ps.putPorts(make(map[switchPort]*peer))
 | 
				
			||||||
	ps.core = c
 | 
						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 {
 | 
					func (ps *peers) getPorts() map[switchPort]*peer {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ func (iface *tcpInterface) listener() {
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			panic(err)
 | 
								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)
 | 
									delete(iface.calls, raddr)
 | 
				
			||||||
				iface.mutex.Unlock()
 | 
									iface.mutex.Unlock()
 | 
				
			||||||
			}()
 | 
								}()
 | 
				
			||||||
			iface.handler(conn)
 | 
								iface.handler(conn, false)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -106,12 +106,12 @@ func (iface *tcpInterface) call(saddr string) {
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return
 | 
									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()
 | 
						defer sock.Close()
 | 
				
			||||||
	// Get our keys
 | 
						// Get our keys
 | 
				
			||||||
	keys := []byte{}
 | 
						keys := []byte{}
 | 
				
			||||||
| 
						 | 
					@ -150,6 +150,15 @@ func (iface *tcpInterface) handler(sock net.Conn) {
 | 
				
			||||||
	if equiv(info.sig[:], iface.core.sigPub[:]) {
 | 
						if equiv(info.sig[:], iface.core.sigPub[:]) {
 | 
				
			||||||
		return
 | 
							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
 | 
						// Check if we already have a connection to this node, close and block if yes
 | 
				
			||||||
	info.localAddr, _, _ = net.SplitHostPort(sock.LocalAddr().String())
 | 
						info.localAddr, _, _ = net.SplitHostPort(sock.LocalAddr().String())
 | 
				
			||||||
	info.remoteAddr, _, _ = net.SplitHostPort(sock.RemoteAddr().String())
 | 
						info.remoteAddr, _, _ = net.SplitHostPort(sock.RemoteAddr().String())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -204,6 +204,14 @@ func (iface *udpInterface) handleKeys(msg []byte, addr connAddr) {
 | 
				
			||||||
	iface.mutex.RUnlock()
 | 
						iface.mutex.RUnlock()
 | 
				
			||||||
	if !isIn {
 | 
						if !isIn {
 | 
				
			||||||
		udpAddr := addr.toUDPAddr()
 | 
							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)
 | 
							themNodeID := getNodeID(&ks.box)
 | 
				
			||||||
		themAddr := address_addrForNodeID(themNodeID)
 | 
							themAddr := address_addrForNodeID(themNodeID)
 | 
				
			||||||
		themAddrString := net.IP(themAddr[:]).String()
 | 
							themAddrString := net.IP(themAddr[:]).String()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,6 +58,13 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
 | 
				
			||||||
		panic(err)
 | 
							panic(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	n.core.DEBUG_setIfceExpr(ifceExpr)
 | 
						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...")
 | 
						logger.Println("Starting interface...")
 | 
				
			||||||
	n.core.DEBUG_setupAndStartGlobalTCPInterface(cfg.Listen) // Listen for peers on TCP
 | 
						n.core.DEBUG_setupAndStartGlobalTCPInterface(cfg.Listen) // Listen for peers on TCP
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue