mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-12-22 18:45:40 +00:00
Multicast passwords
This commit is contained in:
parent
45b773eade
commit
2a21241738
@ -230,6 +230,7 @@ func main() {
|
|||||||
Listen: intf.Listen,
|
Listen: intf.Listen,
|
||||||
Port: intf.Port,
|
Port: intf.Port,
|
||||||
Priority: uint8(intf.Priority),
|
Priority: uint8(intf.Priority),
|
||||||
|
Password: intf.Password,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if n.multicast, err = multicast.New(n.core, logger, options...); err != nil {
|
if n.multicast, err = multicast.New(n.core, logger, options...); err != nil {
|
||||||
|
@ -88,6 +88,7 @@ func (m *Yggdrasil) StartJSON(configjson []byte) error {
|
|||||||
Listen: intf.Listen,
|
Listen: intf.Listen,
|
||||||
Port: intf.Port,
|
Port: intf.Port,
|
||||||
Priority: uint8(intf.Priority),
|
Priority: uint8(intf.Priority),
|
||||||
|
Password: intf.Password,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
m.multicast, err = multicast.New(m.core, m.logger, options...)
|
m.multicast, err = multicast.New(m.core, m.logger, options...)
|
||||||
|
@ -61,6 +61,7 @@ type MulticastInterfaceConfig struct {
|
|||||||
Listen bool
|
Listen bool
|
||||||
Port uint16
|
Port uint16
|
||||||
Priority uint64 // really uint8, but gobind won't export it
|
Priority uint64 // really uint8, but gobind won't export it
|
||||||
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates default configuration and returns a pointer to the resulting
|
// Generates default configuration and returns a pointer to the resulting
|
||||||
|
@ -7,21 +7,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type multicastAdvertisement struct {
|
type multicastAdvertisement struct {
|
||||||
MajorVersion uint16
|
MajorVersion uint16
|
||||||
MinorVersion uint16
|
MinorVersion uint16
|
||||||
PublicKey ed25519.PublicKey
|
PublicKey ed25519.PublicKey
|
||||||
Port uint16
|
Port uint16
|
||||||
Discriminator []byte
|
Hash []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *multicastAdvertisement) MarshalBinary() ([]byte, error) {
|
func (m *multicastAdvertisement) MarshalBinary() ([]byte, error) {
|
||||||
b := make([]byte, 0, ed25519.PublicKeySize+8+len(m.Discriminator))
|
b := make([]byte, 0, ed25519.PublicKeySize+8+len(m.Hash))
|
||||||
b = binary.BigEndian.AppendUint16(b, m.MajorVersion)
|
b = binary.BigEndian.AppendUint16(b, m.MajorVersion)
|
||||||
b = binary.BigEndian.AppendUint16(b, m.MinorVersion)
|
b = binary.BigEndian.AppendUint16(b, m.MinorVersion)
|
||||||
b = append(b, m.PublicKey...)
|
b = append(b, m.PublicKey...)
|
||||||
b = binary.BigEndian.AppendUint16(b, m.Port)
|
b = binary.BigEndian.AppendUint16(b, m.Port)
|
||||||
b = binary.BigEndian.AppendUint16(b, uint16(len(m.Discriminator)))
|
b = binary.BigEndian.AppendUint16(b, uint16(len(m.Hash)))
|
||||||
b = append(b, m.Discriminator...)
|
b = append(b, m.Hash...)
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +34,6 @@ func (m *multicastAdvertisement) UnmarshalBinary(b []byte) error {
|
|||||||
m.PublicKey = append(m.PublicKey[:0], b[4:4+ed25519.PublicKeySize]...)
|
m.PublicKey = append(m.PublicKey[:0], b[4:4+ed25519.PublicKeySize]...)
|
||||||
m.Port = binary.BigEndian.Uint16(b[4+ed25519.PublicKeySize : 6+ed25519.PublicKeySize])
|
m.Port = binary.BigEndian.Uint16(b[4+ed25519.PublicKeySize : 6+ed25519.PublicKeySize])
|
||||||
dl := binary.BigEndian.Uint16(b[6+ed25519.PublicKeySize : 8+ed25519.PublicKeySize])
|
dl := binary.BigEndian.Uint16(b[6+ed25519.PublicKeySize : 8+ed25519.PublicKeySize])
|
||||||
m.Discriminator = append(m.Discriminator[:0], b[8+ed25519.PublicKeySize:8+ed25519.PublicKeySize+dl]...)
|
m.Hash = append(m.Hash[:0], b[8+ed25519.PublicKeySize:8+ed25519.PublicKeySize+dl]...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,11 @@ func TestMulticastAdvertisementRoundTrip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
orig := multicastAdvertisement{
|
orig := multicastAdvertisement{
|
||||||
MajorVersion: 1,
|
MajorVersion: 1,
|
||||||
MinorVersion: 2,
|
MinorVersion: 2,
|
||||||
PublicKey: pk,
|
PublicKey: pk,
|
||||||
Port: 3,
|
Port: 3,
|
||||||
Discriminator: sk, // any bytes will do
|
Hash: sk, // any bytes will do
|
||||||
}
|
}
|
||||||
|
|
||||||
ob, err := orig.MarshalBinary()
|
ob, err := orig.MarshalBinary()
|
||||||
|
@ -3,6 +3,7 @@ package multicast
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/ed25519"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@ -14,6 +15,7 @@ import (
|
|||||||
"github.com/gologme/log"
|
"github.com/gologme/log"
|
||||||
|
|
||||||
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
"github.com/yggdrasil-network/yggdrasil-go/src/core"
|
||||||
|
"golang.org/x/crypto/blake2b"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,10 +33,8 @@ type Multicast struct {
|
|||||||
_interfaces map[string]*interfaceInfo
|
_interfaces map[string]*interfaceInfo
|
||||||
_timer *time.Timer
|
_timer *time.Timer
|
||||||
config struct {
|
config struct {
|
||||||
_discriminator []byte
|
_groupAddr GroupAddress
|
||||||
_discriminatorMatch func([]byte) bool
|
_interfaces map[MulticastInterface]struct{}
|
||||||
_groupAddr GroupAddress
|
|
||||||
_interfaces map[MulticastInterface]struct{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +45,8 @@ type interfaceInfo struct {
|
|||||||
listen bool
|
listen bool
|
||||||
port uint16
|
port uint16
|
||||||
priority uint8
|
priority uint8
|
||||||
|
password []byte
|
||||||
|
hash []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type listenerInfo struct {
|
type listenerInfo struct {
|
||||||
@ -178,6 +180,7 @@ func (m *Multicast) _getAllowedInterfaces() map[string]*interfaceInfo {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Work out which interfaces to announce on
|
// Work out which interfaces to announce on
|
||||||
|
pk := m.core.PublicKey()
|
||||||
for _, iface := range allifaces {
|
for _, iface := range allifaces {
|
||||||
switch {
|
switch {
|
||||||
case iface.Flags&net.FlagUp == 0:
|
case iface.Flags&net.FlagUp == 0:
|
||||||
@ -196,12 +199,23 @@ func (m *Multicast) _getAllowedInterfaces() map[string]*interfaceInfo {
|
|||||||
if !ifcfg.Regex.MatchString(iface.Name) {
|
if !ifcfg.Regex.MatchString(iface.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
hasher, err := blake2b.New512([]byte(ifcfg.Password))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if n, err := hasher.Write(pk); err != nil {
|
||||||
|
continue
|
||||||
|
} else if n != ed25519.PublicKeySize {
|
||||||
|
continue
|
||||||
|
}
|
||||||
interfaces[iface.Name] = &interfaceInfo{
|
interfaces[iface.Name] = &interfaceInfo{
|
||||||
iface: iface,
|
iface: iface,
|
||||||
beacon: ifcfg.Beacon,
|
beacon: ifcfg.Beacon,
|
||||||
listen: ifcfg.Listen,
|
listen: ifcfg.Listen,
|
||||||
port: ifcfg.Port,
|
port: ifcfg.Port,
|
||||||
priority: ifcfg.Priority,
|
priority: ifcfg.Priority,
|
||||||
|
password: []byte(ifcfg.Password),
|
||||||
|
hash: hasher.Sum(nil),
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -298,10 +312,13 @@ func (m *Multicast) _announce() {
|
|||||||
var linfo *listenerInfo
|
var linfo *listenerInfo
|
||||||
if _, ok := m._listeners[iface.Name]; !ok {
|
if _, ok := m._listeners[iface.Name]; !ok {
|
||||||
// No listener was found - let's create one
|
// No listener was found - let's create one
|
||||||
urlString := fmt.Sprintf("tls://[%s]:%d", addrIP, info.port)
|
v := &url.Values{}
|
||||||
u, err := url.Parse(urlString)
|
v.Add("priority", fmt.Sprintf("%d", info.priority))
|
||||||
if err != nil {
|
v.Add("password", string(info.password))
|
||||||
panic(err)
|
u := &url.URL{
|
||||||
|
Scheme: "tls",
|
||||||
|
Host: net.JoinHostPort(addrIP.String(), fmt.Sprintf("%d", info.port)),
|
||||||
|
RawQuery: v.Encode(),
|
||||||
}
|
}
|
||||||
if li, err := m.core.Listen(u, iface.Name); err == nil {
|
if li, err := m.core.Listen(u, iface.Name); err == nil {
|
||||||
m.log.Debugln("Started multicasting on", iface.Name)
|
m.log.Debugln("Started multicasting on", iface.Name)
|
||||||
@ -324,11 +341,11 @@ func (m *Multicast) _announce() {
|
|||||||
}
|
}
|
||||||
addr := linfo.listener.Addr().(*net.TCPAddr)
|
addr := linfo.listener.Addr().(*net.TCPAddr)
|
||||||
adv := multicastAdvertisement{
|
adv := multicastAdvertisement{
|
||||||
MajorVersion: core.ProtocolVersionMajor,
|
MajorVersion: core.ProtocolVersionMajor,
|
||||||
MinorVersion: core.ProtocolVersionMinor,
|
MinorVersion: core.ProtocolVersionMinor,
|
||||||
PublicKey: m.core.PublicKey(),
|
PublicKey: m.core.PublicKey(),
|
||||||
Port: uint16(addr.Port),
|
Port: uint16(addr.Port),
|
||||||
Discriminator: m.config._discriminator,
|
Hash: info.hash,
|
||||||
}
|
}
|
||||||
msg, err := adv.MarshalBinary()
|
msg, err := adv.MarshalBinary()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -356,6 +373,7 @@ func (m *Multicast) listen() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
bs := make([]byte, 2048)
|
bs := make([]byte, 2048)
|
||||||
|
hb := make([]byte, 0, blake2b.Size) // Reused to reduce hash allocations
|
||||||
for {
|
for {
|
||||||
n, rcm, fromAddr, err := m.sock.ReadFrom(bs)
|
n, rcm, fromAddr, err := m.sock.ReadFrom(bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -386,10 +404,6 @@ func (m *Multicast) listen() {
|
|||||||
continue
|
continue
|
||||||
case adv.PublicKey.Equal(m.core.PublicKey()):
|
case adv.PublicKey.Equal(m.core.PublicKey()):
|
||||||
continue
|
continue
|
||||||
case m.config._discriminatorMatch == nil && !bytes.Equal(adv.Discriminator, m.config._discriminator):
|
|
||||||
continue
|
|
||||||
case m.config._discriminatorMatch != nil && !m.config._discriminatorMatch(adv.Discriminator):
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
from := fromAddr.(*net.UDPAddr)
|
from := fromAddr.(*net.UDPAddr)
|
||||||
from.Port = int(adv.Port)
|
from.Port = int(adv.Port)
|
||||||
@ -398,9 +412,22 @@ func (m *Multicast) listen() {
|
|||||||
interfaces = m._interfaces
|
interfaces = m._interfaces
|
||||||
})
|
})
|
||||||
if info, ok := interfaces[from.Zone]; ok && info.listen {
|
if info, ok := interfaces[from.Zone]; ok && info.listen {
|
||||||
|
hasher, err := blake2b.New512(info.password)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if n, err := hasher.Write(adv.PublicKey); err != nil {
|
||||||
|
continue
|
||||||
|
} else if n != ed25519.PublicKeySize {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !bytes.Equal(hasher.Sum(hb[:0]), adv.Hash) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
v := &url.Values{}
|
v := &url.Values{}
|
||||||
v.Add("key", hex.EncodeToString(adv.PublicKey))
|
v.Add("key", hex.EncodeToString(adv.PublicKey))
|
||||||
v.Add("priority", fmt.Sprintf("%d", info.priority))
|
v.Add("priority", fmt.Sprintf("%d", info.priority))
|
||||||
|
v.Add("password", string(info.password))
|
||||||
u := &url.URL{
|
u := &url.URL{
|
||||||
Scheme: "tls",
|
Scheme: "tls",
|
||||||
Host: from.String(),
|
Host: from.String(),
|
||||||
|
@ -8,10 +8,6 @@ func (m *Multicast) _applyOption(opt SetupOption) {
|
|||||||
m.config._interfaces[v] = struct{}{}
|
m.config._interfaces[v] = struct{}{}
|
||||||
case GroupAddress:
|
case GroupAddress:
|
||||||
m.config._groupAddr = v
|
m.config._groupAddr = v
|
||||||
case Discriminator:
|
|
||||||
m.config._discriminator = append(m.config._discriminator[:0], v...)
|
|
||||||
case DiscriminatorMatch:
|
|
||||||
m.config._discriminatorMatch = v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,13 +21,10 @@ type MulticastInterface struct {
|
|||||||
Listen bool
|
Listen bool
|
||||||
Port uint16
|
Port uint16
|
||||||
Priority uint8
|
Priority uint8
|
||||||
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupAddress string
|
type GroupAddress string
|
||||||
type Discriminator []byte
|
|
||||||
type DiscriminatorMatch func([]byte) bool
|
|
||||||
|
|
||||||
func (a MulticastInterface) isSetupOption() {}
|
func (a MulticastInterface) isSetupOption() {}
|
||||||
func (a GroupAddress) isSetupOption() {}
|
func (a GroupAddress) isSetupOption() {}
|
||||||
func (a Discriminator) isSetupOption() {}
|
|
||||||
func (a DiscriminatorMatch) isSetupOption() {}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user