diff --git a/cmd/yggdrasil/main.go b/cmd/yggdrasil/main.go index 0581e018..b43faeb2 100644 --- a/cmd/yggdrasil/main.go +++ b/cmd/yggdrasil/main.go @@ -210,6 +210,9 @@ func main() { for _, peer := range cfg.Peers { options = append(options, core.Peer{URI: peer}) } + if cfg.GroupPassword != "" { + options = append(options, core.GroupPassword(cfg.GroupPassword)) + } for intf, peers := range cfg.InterfacePeers { for _, peer := range peers { options = append(options, core.Peer{URI: peer, SourceInterface: intf}) diff --git a/go.mod b/go.mod index 28bcb09c..cb34cd14 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/yggdrasil-network/yggdrasil-go go 1.24.0 +replace github.com/Arceliar/ironwood => github.com/neilalexander/ironwood v0.0.0-20260512143124-5ffa69c5b2c5 + require ( github.com/Arceliar/ironwood v0.0.0-20260117132459-7017dbc41d8e github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d diff --git a/go.sum b/go.sum index 8aa02bb6..d0de1178 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/Arceliar/ironwood v0.0.0-20260117132459-7017dbc41d8e h1:s7MuhcZu2hNfVvYLT4cKnQt7pZ1+z6eL2E48YlaAqzY= -github.com/Arceliar/ironwood v0.0.0-20260117132459-7017dbc41d8e/go.mod h1:SrrElc3FFMpYCODSr11jWbLFeOM8WsY+DbDY/l2AXF0= github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d h1:UK9fsWbWqwIQkMCz1CP+v5pGbsGoWAw6g4AyvMpm1EM= github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d/go.mod h1:BCnxhRf47C/dy/e/D2pmB8NkB3dQVIrkD98b220rx5Q= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= @@ -39,6 +37,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ= github.com/mattn/go-runewidth v0.0.20/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/neilalexander/ironwood v0.0.0-20260512143124-5ffa69c5b2c5 h1:iInQaEVwPcUFf3DNfJvTP/jWSZMLRIMAUO/zEnPvcz0= +github.com/neilalexander/ironwood v0.0.0-20260512143124-5ffa69c5b2c5/go.mod h1:SrrElc3FFMpYCODSr11jWbLFeOM8WsY+DbDY/l2AXF0= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= github.com/olekukonko/errors v1.2.0 h1:10Zcn4GeV59t/EGqJc8fUjtFT/FuUh5bTMzZ1XwmCRo= diff --git a/src/config/config.go b/src/config/config.go index 5dd7b3d4..c20506c8 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -49,6 +49,7 @@ type NodeConfig struct { AdminListen string `json:",omitempty" comment:"Listen address for admin connections. Default is to listen for local\nconnections either on TCP/9001 or a UNIX socket depending on your\nplatform. Use this value for yggdrasilctl -endpoint=X. To disable\nthe admin socket, use the value \"none\" instead."` MulticastInterfaces []MulticastInterfaceConfig `comment:"Configuration for which interfaces multicast peer discovery should be\nenabled on. Regex is a regular expression which is matched against an\ninterface name, and interfaces use the first configuration that they\nmatch against. Beacon controls whether or not your node advertises its\npresence to others, whereas Listen controls whether or not your node\nlistens out for and tries to connect to other advertising nodes. See\nhttps://yggdrasil-network.github.io/configurationref.html#multicastinterfaces\nfor more supported options."` AllowedPublicKeys []string `comment:"List of peer public keys to allow incoming peering connections\nfrom. If left empty/undefined then all connections will be allowed\nby default. This does not affect outgoing peerings, nor does it\naffect link-local peers discovered via multicast.\nWARNING: THIS IS NOT A FIREWALL and DOES NOT limit who can reach\nopen ports or services running on your machine!"` + GroupPassword string `comment:"Traffic is only allowed to/from nodes with the same group password.\nIf you want to form a private sub-network or ensure that other public\nusers cannot connect to your machines, choose a strong group password\nand then share it only to other allowed nodes in your private group.\nIf left empty or not specified, public connectivity will be permitted.\nThis option DOES NOT affect peer connections."` IfName string `comment:"Local network interface name for TUN adapter, or \"auto\" to select\nan interface automatically, or \"none\" to run without TUN."` IfMTU uint64 `comment:"Maximum Transmission Unit (MTU) size for your local TUN interface.\nDefault is the largest supported size for your platform. The lowest\npossible value is 1280."` LogLookups bool `json:",omitempty"` diff --git a/src/core/core.go b/src/core/core.go index 26be28a2..83a270d0 100644 --- a/src/core/core.go +++ b/src/core/core.go @@ -42,6 +42,7 @@ type Core struct { nodeinfo NodeInfo // immutable after startup nodeinfoPrivacy NodeInfoPrivacy // immutable after startup _allowedPublicKeys map[[32]byte]struct{} // configurable after startup + groupPassword string // immutable after startup } pathNotify func(ed25519.PublicKey) } @@ -94,8 +95,9 @@ func New(cert *tls.Certificate, logger Logger, opts ...SetupOption) (*Core, erro keyXform := func(key ed25519.PublicKey) ed25519.PublicKey { return address.SubnetForKey(key).GetKey() } - if c.PacketConn, err = iwe.NewPacketConn( + if c.PacketConn, err = iwe.NewPacketConnWithPassword( c.secret, + c.config.groupPassword, iwn.WithBloomTransform(keyXform), iwn.WithPeerMaxMessageSize(65535*2), iwn.WithPathNotify(c.doPathNotify), diff --git a/src/core/options.go b/src/core/options.go index 7e67bfb4..455d13d2 100644 --- a/src/core/options.go +++ b/src/core/options.go @@ -35,6 +35,8 @@ func (c *Core) _applyOption(opt SetupOption) (err error) { pk := [32]byte{} copy(pk[:], v) c.config._allowedPublicKeys[pk] = struct{}{} + case GroupPassword: + c.config.groupPassword = string(v) } return } @@ -52,6 +54,7 @@ type NodeInfo map[string]interface{} type NodeInfoPrivacy bool type AllowedPublicKey ed25519.PublicKey type PeerFilter func(net.IP) bool +type GroupPassword string func (a ListenAddress) isSetupOption() {} func (a Peer) isSetupOption() {} @@ -59,3 +62,4 @@ func (a NodeInfo) isSetupOption() {} func (a NodeInfoPrivacy) isSetupOption() {} func (a AllowedPublicKey) isSetupOption() {} func (a PeerFilter) isSetupOption() {} +func (a GroupPassword) isSetupOption() {}