Add a way to trigger punch backs via lighthouse (#394)
This commit is contained in:
parent
2a4beb41b9
commit
b6234abfb3
|
@ -65,6 +65,12 @@ func (c *Control) ShutdownBlock() {
|
|||
// RebindUDPServer asks the UDP listener to rebind it's listener. Mainly used on mobile clients when interfaces change
|
||||
func (c *Control) RebindUDPServer() {
|
||||
_ = c.f.outside.Rebind()
|
||||
|
||||
// Trigger a lighthouse update, useful for mobile clients that should have an update interval of 0
|
||||
c.f.lightHouse.SendUpdate(c.f)
|
||||
|
||||
// Let the main interface know that we rebound so that underlying tunnels know to trigger punches from their remotes
|
||||
c.f.rebindCount++
|
||||
}
|
||||
|
||||
// ListHostmap returns details about the actual or pending (handshaking) hostmap
|
||||
|
|
|
@ -51,6 +51,11 @@ type HostInfo struct {
|
|||
recvError int
|
||||
remoteCidr *CIDRTree
|
||||
|
||||
// lastRebindCount is the other side of Interface.rebindCount, if these values don't match then we need to ask LH
|
||||
// for a punch from the remote end of this tunnel. The goal being to prime their conntrack for our traffic just like
|
||||
// with a handshake
|
||||
lastRebindCount int8
|
||||
|
||||
lastRoam time.Time
|
||||
lastRoamRemote *udpAddr
|
||||
}
|
||||
|
|
12
inside.go
12
inside.go
|
@ -229,6 +229,18 @@ func (f *Interface) sendNoMetrics(t NebulaMessageType, st NebulaMessageSubType,
|
|||
out = HeaderEncode(out, Version, uint8(t), uint8(st), hostinfo.remoteIndexId, c)
|
||||
f.connectionManager.Out(hostinfo.hostId)
|
||||
|
||||
// Query our LH if we haven't since the last time we've been rebound, this will cause the remote to punch against
|
||||
// all our IPs and enable a faster roaming.
|
||||
if hostinfo.lastRebindCount != f.rebindCount {
|
||||
//NOTE: there is an update hole if a tunnel isn't used and exactly 256 rebinds occur before the tunnel is
|
||||
// finally used again. This tunnel would eventually be torn down and recreated if this action didn't help.
|
||||
f.lightHouse.Query(hostinfo.hostId, f)
|
||||
hostinfo.lastRebindCount = f.rebindCount
|
||||
if l.Level >= logrus.DebugLevel {
|
||||
l.WithField("vpnIp", hostinfo.hostId).Debug("Lighthouse update triggered for punch due to rebind counter")
|
||||
}
|
||||
}
|
||||
|
||||
out, err = ci.eKey.EncryptDanger(out, out, p, c, nb)
|
||||
//TODO: see above note on lock
|
||||
//ci.writeLock.Unlock()
|
||||
|
|
|
@ -61,7 +61,10 @@ type Interface struct {
|
|||
dropMulticast bool
|
||||
udpBatchSize int
|
||||
routines int
|
||||
version string
|
||||
|
||||
// rebindCount is used to decide if an active tunnel should trigger a punch notification through a lighthouse
|
||||
rebindCount int8
|
||||
version string
|
||||
|
||||
conntrackCacheTimeout time.Duration
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ type LightHouse struct {
|
|||
staticList map[uint32]struct{}
|
||||
lighthouses map[uint32]struct{}
|
||||
interval int
|
||||
nebulaPort int
|
||||
nebulaPort uint32
|
||||
punchBack bool
|
||||
punchDelay time.Duration
|
||||
|
||||
|
@ -54,7 +54,7 @@ type EncWriter interface {
|
|||
SendMessageToAll(t NebulaMessageType, st NebulaMessageSubType, vpnIp uint32, p, nb, out []byte)
|
||||
}
|
||||
|
||||
func NewLightHouse(amLighthouse bool, myIp uint32, ips []uint32, interval int, nebulaPort int, pc *udpConn, punchBack bool, punchDelay time.Duration, metricsEnabled bool) *LightHouse {
|
||||
func NewLightHouse(amLighthouse bool, myIp uint32, ips []uint32, interval int, nebulaPort uint32, pc *udpConn, punchBack bool, punchDelay time.Duration, metricsEnabled bool) *LightHouse {
|
||||
h := LightHouse{
|
||||
amLighthouse: amLighthouse,
|
||||
myIp: myIp,
|
||||
|
@ -208,12 +208,6 @@ func (lh *LightHouse) IsLighthouseIP(vpnIP uint32) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Quick generators for protobuf
|
||||
|
||||
func NewLhQueryByIpString(VpnIp string) *NebulaMeta {
|
||||
return NewLhQueryByInt(ip2int(net.ParseIP(VpnIp)))
|
||||
}
|
||||
|
||||
func NewLhQueryByInt(VpnIp uint32) *NebulaMeta {
|
||||
return &NebulaMeta{
|
||||
Type: NebulaMeta_HostQuery,
|
||||
|
@ -223,15 +217,10 @@ func NewLhQueryByInt(VpnIp uint32) *NebulaMeta {
|
|||
}
|
||||
}
|
||||
|
||||
func NewLhWhoami() *NebulaMeta {
|
||||
return &NebulaMeta{
|
||||
Type: NebulaMeta_HostWhoami,
|
||||
Details: &NebulaMetaDetails{},
|
||||
}
|
||||
func NewIpAndPort(ip net.IP, port uint32) IpAndPort {
|
||||
return IpAndPort{Ip: ip2int(ip), Port: port}
|
||||
}
|
||||
|
||||
// End Quick generators for protobuf
|
||||
|
||||
func NewIpAndPortFromUDPAddr(addr udpAddr) IpAndPort {
|
||||
return IpAndPort{Ip: udp2ipInt(&addr), Port: uint32(addr.Port)}
|
||||
}
|
||||
|
@ -242,39 +231,43 @@ func (lh *LightHouse) LhUpdateWorker(f EncWriter) {
|
|||
}
|
||||
|
||||
for {
|
||||
ipp := []*IpAndPort{}
|
||||
|
||||
for _, e := range *localIps(lh.localAllowList) {
|
||||
// Only add IPs that aren't my VPN/tun IP
|
||||
if ip2int(e) != lh.myIp {
|
||||
ipp = append(ipp, &IpAndPort{Ip: ip2int(e), Port: uint32(lh.nebulaPort)})
|
||||
//fmt.Println(e)
|
||||
}
|
||||
}
|
||||
m := &NebulaMeta{
|
||||
Type: NebulaMeta_HostUpdateNotification,
|
||||
Details: &NebulaMetaDetails{
|
||||
VpnIp: lh.myIp,
|
||||
IpAndPorts: ipp,
|
||||
},
|
||||
}
|
||||
|
||||
lh.metricTx(NebulaMeta_HostUpdateNotification, int64(len(lh.lighthouses)))
|
||||
nb := make([]byte, 12, 12)
|
||||
out := make([]byte, mtu)
|
||||
for vpnIp := range lh.lighthouses {
|
||||
mm, err := proto.Marshal(m)
|
||||
if err != nil {
|
||||
l.Debugf("Invalid marshal to update")
|
||||
}
|
||||
//l.Error("LIGHTHOUSE PACKET SEND", mm)
|
||||
f.SendMessageToVpnIp(lightHouse, 0, vpnIp, mm, nb, out)
|
||||
|
||||
}
|
||||
lh.SendUpdate(f)
|
||||
time.Sleep(time.Second * time.Duration(lh.interval))
|
||||
}
|
||||
}
|
||||
|
||||
func (lh *LightHouse) SendUpdate(f EncWriter) {
|
||||
var ipps []*IpAndPort
|
||||
|
||||
for _, e := range *localIps(lh.localAllowList) {
|
||||
// Only add IPs that aren't my VPN/tun IP
|
||||
if ip2int(e) != lh.myIp {
|
||||
ipp := NewIpAndPort(e, lh.nebulaPort)
|
||||
ipps = append(ipps, &ipp)
|
||||
}
|
||||
}
|
||||
m := &NebulaMeta{
|
||||
Type: NebulaMeta_HostUpdateNotification,
|
||||
Details: &NebulaMetaDetails{
|
||||
VpnIp: lh.myIp,
|
||||
IpAndPorts: ipps,
|
||||
},
|
||||
}
|
||||
|
||||
lh.metricTx(NebulaMeta_HostUpdateNotification, int64(len(lh.lighthouses)))
|
||||
nb := make([]byte, 12, 12)
|
||||
out := make([]byte, mtu)
|
||||
for vpnIp := range lh.lighthouses {
|
||||
mm, err := proto.Marshal(m)
|
||||
if err != nil {
|
||||
l.Debugf("Invalid marshal to update")
|
||||
}
|
||||
//l.Error("LIGHTHOUSE PACKET SEND", mm)
|
||||
f.SendMessageToVpnIp(lightHouse, 0, vpnIp, mm, nb, out)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
type LightHouseHandler struct {
|
||||
lh *LightHouse
|
||||
nb []byte
|
||||
|
|
Loading…
Reference in New Issue