From ee4495cdd3c4bef74f02d65d8ad32d80fe7d0ca7 Mon Sep 17 00:00:00 2001 From: Jack Doan Date: Mon, 14 Oct 2024 20:29:27 -0400 Subject: [PATCH 1/5] relay fixes for multi-IP hosts --- relay_manager.go | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/relay_manager.go b/relay_manager.go index bbc151db1..61decee69 100644 --- a/relay_manager.go +++ b/relay_manager.go @@ -280,8 +280,7 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f msg, err := resp.Marshal() if err != nil { - logMsg. - WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") + logMsg.WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") } else { f.SendMessageToHostInfo(header.Control, 0, h, msg, make([]byte, 12), make([]byte, mtu)) rm.l.WithFields(logrus.Fields{ @@ -335,29 +334,27 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f } if v == cert.Version1 { - if !h.vpnAddrs[0].Is4() { + if !from.Is4() { //TODO: log it return } - - b := h.vpnAddrs[0].As4() + b := from.As4() req.OldRelayFromAddr = binary.BigEndian.Uint32(b[:]) b = target.As4() req.OldRelayToAddr = binary.BigEndian.Uint32(b[:]) } else { - req.RelayFromAddr = netAddrToProtoAddr(h.vpnAddrs[0]) + req.RelayFromAddr = netAddrToProtoAddr(from) req.RelayToAddr = netAddrToProtoAddr(target) } msg, err := req.Marshal() if err != nil { - logMsg. - WithError(err).Error("relayManager Failed to marshal Control message to create relay") + logMsg.WithError(err).Error("relayManager Failed to marshal Control message to create relay") } else { f.SendMessageToHostInfo(header.Control, 0, peer, msg, make([]byte, 12), make([]byte, mtu)) rm.l.WithFields(logrus.Fields{ //TODO: IPV6-WORK another lazy used to use the req object - "relayFrom": h.vpnAddrs[0], + "relayFrom": from, "relayTo": target, "initiatorRelayIndex": req.InitiatorRelayIndex, "responderRelayIndex": req.ResponderRelayIndex, @@ -375,8 +372,7 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f } _, err := AddRelay(rm.l, h, f.hostMap, target, &m.InitiatorRelayIndex, ForwardingType, state) if err != nil { - logMsg. - WithError(err).Error("relayManager Failed to allocate a local index for relay") + logMsg.WithError(err).Error("relayManager Failed to allocate a local index for relay") return } } else { @@ -397,29 +393,28 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f } if v == cert.Version1 { - if !h.vpnAddrs[0].Is4() { + if !from.Is4() { //TODO: log it return } - b := h.vpnAddrs[0].As4() + b := from.As4() resp.OldRelayFromAddr = binary.BigEndian.Uint32(b[:]) b = target.As4() resp.OldRelayToAddr = binary.BigEndian.Uint32(b[:]) } else { - resp.RelayFromAddr = netAddrToProtoAddr(h.vpnAddrs[0]) + resp.RelayFromAddr = netAddrToProtoAddr(from) resp.RelayToAddr = netAddrToProtoAddr(target) } msg, err := resp.Marshal() if err != nil { - rm.l. - WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") + rm.l.WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") } else { f.SendMessageToHostInfo(header.Control, 0, h, msg, make([]byte, 12), make([]byte, mtu)) rm.l.WithFields(logrus.Fields{ //TODO: IPV6-WORK more lazy, used to use resp object - "relayFrom": h.vpnAddrs[0], + "relayFrom": from, "relayTo": target, "initiatorRelayIndex": resp.InitiatorRelayIndex, "responderRelayIndex": resp.ResponderRelayIndex, From 0f475ade076841f5624b6c38ce183ef02ec05fe1 Mon Sep 17 00:00:00 2001 From: Jack Doan Date: Mon, 14 Oct 2024 22:42:15 -0400 Subject: [PATCH 2/5] more relay fixes --- inside.go | 9 ++++++++- outside.go | 11 +++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/inside.go b/inside.go index 6813237ed..facf507ba 100644 --- a/inside.go +++ b/inside.go @@ -330,7 +330,14 @@ func (f *Interface) sendNoMetrics(t header.MessageType, st header.MessageSubType } else { // Try to send via a relay for _, relayIP := range hostinfo.relayState.CopyRelayIps() { - relayHostInfo, relay, err := f.hostMap.QueryVpnAddrRelayFor(hostinfo.vpnAddrs[0], relayIP) + var relayHostInfo *HostInfo + var relay *Relay + for _, vpnAddr := range hostinfo.vpnAddrs { + relayHostInfo, relay, err = f.hostMap.QueryVpnAddrRelayFor(vpnAddr, relayIP) + if err == nil { + break + } + } if err != nil { hostinfo.relayState.DeleteRelay(relayIP) hostinfo.logger(f.l).WithField("relay", relayIP).WithError(err).Info("sendNoMetrics failed to find HostInfo") diff --git a/outside.go b/outside.go index 91af76712..b0a811631 100644 --- a/outside.go +++ b/outside.go @@ -104,9 +104,16 @@ func (f *Interface) readOutsidePackets(ip netip.AddrPort, via *ViaSender, out [] return case ForwardingType: // Find the target HostInfo relay object - targetHI, targetRelay, err := f.hostMap.QueryVpnAddrRelayFor(hostinfo.vpnAddrs[0], relay.PeerAddr) + var targetHI *HostInfo + var targetRelay *Relay + for _, vpnAddr := range hostinfo.vpnAddrs { + targetHI, targetRelay, err = f.hostMap.QueryVpnAddrRelayFor(vpnAddr, relay.PeerAddr) + if err == nil { + break + } + } if err != nil { - hostinfo.logger(f.l).WithField("relayTo", relay.PeerAddr).WithError(err).Info("Failed to find target host info by ip") + hostinfo.logger(f.l).WithField("relayTo", relay.PeerAddr).WithError(err).WithField("hostinfo.vpnAddrs", hostinfo.vpnAddrs).Info("Failed to find target host info by ip") return } From 59eb10870041f441b5a8881e93e603729b874dec Mon Sep 17 00:00:00 2001 From: Jack Doan Date: Mon, 14 Oct 2024 22:45:37 -0400 Subject: [PATCH 3/5] more relay fixes --- hostmap.go | 23 +++++++++++++---------- inside.go | 9 +-------- outside.go | 9 +-------- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/hostmap.go b/hostmap.go index d5fa032e2..0439061fd 100644 --- a/hostmap.go +++ b/hostmap.go @@ -452,21 +452,24 @@ func (hm *HostMap) QueryVpnAddr(vpnIp netip.Addr) *HostInfo { return hm.queryVpnAddr(vpnIp, nil) } -func (hm *HostMap) QueryVpnAddrRelayFor(targetIp, relayHostIp netip.Addr) (*HostInfo, *Relay, error) { +func (hm *HostMap) QueryVpnAddrsRelayFor(targetIps []netip.Addr, relayHostIp netip.Addr) (*HostInfo, *Relay, error) { hm.RLock() defer hm.RUnlock() - h, ok := hm.Hosts[relayHostIp] - if !ok { - return nil, nil, errors.New("unable to find host") - } - for h != nil { - r, ok := h.relayState.QueryRelayForByIp(targetIp) - if ok && r.State == Established { - return h, r, nil + for _, targetIp := range targetIps { + h, ok := hm.Hosts[relayHostIp] + if !ok { + return nil, nil, errors.New("unable to find host") + } + for h != nil { + r, ok := h.relayState.QueryRelayForByIp(targetIp) + if ok && r.State == Established { + return h, r, nil + } + h = h.next } - h = h.next } + return nil, nil, errors.New("unable to find host with relay") } diff --git a/inside.go b/inside.go index facf507ba..c913b3044 100644 --- a/inside.go +++ b/inside.go @@ -330,14 +330,7 @@ func (f *Interface) sendNoMetrics(t header.MessageType, st header.MessageSubType } else { // Try to send via a relay for _, relayIP := range hostinfo.relayState.CopyRelayIps() { - var relayHostInfo *HostInfo - var relay *Relay - for _, vpnAddr := range hostinfo.vpnAddrs { - relayHostInfo, relay, err = f.hostMap.QueryVpnAddrRelayFor(vpnAddr, relayIP) - if err == nil { - break - } - } + relayHostInfo, relay, err := f.hostMap.QueryVpnAddrsRelayFor(hostinfo.vpnAddrs, relayIP) if err != nil { hostinfo.relayState.DeleteRelay(relayIP) hostinfo.logger(f.l).WithField("relay", relayIP).WithError(err).Info("sendNoMetrics failed to find HostInfo") diff --git a/outside.go b/outside.go index b0a811631..0f2f50381 100644 --- a/outside.go +++ b/outside.go @@ -104,14 +104,7 @@ func (f *Interface) readOutsidePackets(ip netip.AddrPort, via *ViaSender, out [] return case ForwardingType: // Find the target HostInfo relay object - var targetHI *HostInfo - var targetRelay *Relay - for _, vpnAddr := range hostinfo.vpnAddrs { - targetHI, targetRelay, err = f.hostMap.QueryVpnAddrRelayFor(vpnAddr, relay.PeerAddr) - if err == nil { - break - } - } + targetHI, targetRelay, err := f.hostMap.QueryVpnAddrsRelayFor(hostinfo.vpnAddrs, relay.PeerAddr) if err != nil { hostinfo.logger(f.l).WithField("relayTo", relay.PeerAddr).WithError(err).WithField("hostinfo.vpnAddrs", hostinfo.vpnAddrs).Info("Failed to find target host info by ip") return From 6e55c1d2e362869138d4a47318681a6e6ad8777b Mon Sep 17 00:00:00 2001 From: Jack Doan Date: Mon, 14 Oct 2024 22:48:29 -0400 Subject: [PATCH 4/5] tighter loop --- hostmap.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hostmap.go b/hostmap.go index 0439061fd..00173c45b 100644 --- a/hostmap.go +++ b/hostmap.go @@ -456,18 +456,19 @@ func (hm *HostMap) QueryVpnAddrsRelayFor(targetIps []netip.Addr, relayHostIp net hm.RLock() defer hm.RUnlock() - for _, targetIp := range targetIps { - h, ok := hm.Hosts[relayHostIp] - if !ok { - return nil, nil, errors.New("unable to find host") - } - for h != nil { + h, ok := hm.Hosts[relayHostIp] + if !ok { + return nil, nil, errors.New("unable to find host") + } + + for h != nil { + for _, targetIp := range targetIps { r, ok := h.relayState.QueryRelayForByIp(targetIp) if ok && r.State == Established { return h, r, nil } - h = h.next } + h = h.next } return nil, nil, errors.New("unable to find host with relay") From 9036c07b4d47c3d789e0fa733b36eed72be2bd76 Mon Sep 17 00:00:00 2001 From: Jack Doan Date: Mon, 14 Oct 2024 22:49:29 -0400 Subject: [PATCH 5/5] Revert "relay fixes for multi-IP hosts" This reverts commit ee4495cdd3c4bef74f02d65d8ad32d80fe7d0ca7. --- relay_manager.go | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/relay_manager.go b/relay_manager.go index 61decee69..bbc151db1 100644 --- a/relay_manager.go +++ b/relay_manager.go @@ -280,7 +280,8 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f msg, err := resp.Marshal() if err != nil { - logMsg.WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") + logMsg. + WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") } else { f.SendMessageToHostInfo(header.Control, 0, h, msg, make([]byte, 12), make([]byte, mtu)) rm.l.WithFields(logrus.Fields{ @@ -334,27 +335,29 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f } if v == cert.Version1 { - if !from.Is4() { + if !h.vpnAddrs[0].Is4() { //TODO: log it return } - b := from.As4() + + b := h.vpnAddrs[0].As4() req.OldRelayFromAddr = binary.BigEndian.Uint32(b[:]) b = target.As4() req.OldRelayToAddr = binary.BigEndian.Uint32(b[:]) } else { - req.RelayFromAddr = netAddrToProtoAddr(from) + req.RelayFromAddr = netAddrToProtoAddr(h.vpnAddrs[0]) req.RelayToAddr = netAddrToProtoAddr(target) } msg, err := req.Marshal() if err != nil { - logMsg.WithError(err).Error("relayManager Failed to marshal Control message to create relay") + logMsg. + WithError(err).Error("relayManager Failed to marshal Control message to create relay") } else { f.SendMessageToHostInfo(header.Control, 0, peer, msg, make([]byte, 12), make([]byte, mtu)) rm.l.WithFields(logrus.Fields{ //TODO: IPV6-WORK another lazy used to use the req object - "relayFrom": from, + "relayFrom": h.vpnAddrs[0], "relayTo": target, "initiatorRelayIndex": req.InitiatorRelayIndex, "responderRelayIndex": req.ResponderRelayIndex, @@ -372,7 +375,8 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f } _, err := AddRelay(rm.l, h, f.hostMap, target, &m.InitiatorRelayIndex, ForwardingType, state) if err != nil { - logMsg.WithError(err).Error("relayManager Failed to allocate a local index for relay") + logMsg. + WithError(err).Error("relayManager Failed to allocate a local index for relay") return } } else { @@ -393,28 +397,29 @@ func (rm *relayManager) handleCreateRelayRequest(v cert.Version, h *HostInfo, f } if v == cert.Version1 { - if !from.Is4() { + if !h.vpnAddrs[0].Is4() { //TODO: log it return } - b := from.As4() + b := h.vpnAddrs[0].As4() resp.OldRelayFromAddr = binary.BigEndian.Uint32(b[:]) b = target.As4() resp.OldRelayToAddr = binary.BigEndian.Uint32(b[:]) } else { - resp.RelayFromAddr = netAddrToProtoAddr(from) + resp.RelayFromAddr = netAddrToProtoAddr(h.vpnAddrs[0]) resp.RelayToAddr = netAddrToProtoAddr(target) } msg, err := resp.Marshal() if err != nil { - rm.l.WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") + rm.l. + WithError(err).Error("relayManager Failed to marshal Control CreateRelayResponse message to create relay") } else { f.SendMessageToHostInfo(header.Control, 0, h, msg, make([]byte, 12), make([]byte, mtu)) rm.l.WithFields(logrus.Fields{ //TODO: IPV6-WORK more lazy, used to use resp object - "relayFrom": from, + "relayFrom": h.vpnAddrs[0], "relayTo": target, "initiatorRelayIndex": resp.InitiatorRelayIndex, "responderRelayIndex": resp.ResponderRelayIndex,