mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-15 23:06:38 +00:00
Resolve tracer 'self' to v6 overlay address when peer is IPv6
The packet tracer resolved 'self' to the v4 overlay address unconditionally, causing "mixed address families" errors when tracing v6 traffic. Pick the self address matching the peer's address family. Add Engine.GetWgV6Addr() and rework parseAddress into resolveTraceAddresses which parses the non-self address first to determine the family, then resolves self accordingly.
This commit is contained in:
@@ -2159,6 +2159,14 @@ func (e *Engine) GetWgAddr() netip.Addr {
|
||||
return e.wgInterface.Address().IP
|
||||
}
|
||||
|
||||
// GetWgV6Addr returns the IPv6 overlay address of the WireGuard interface.
|
||||
func (e *Engine) GetWgV6Addr() netip.Addr {
|
||||
if e.wgInterface == nil {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return e.wgInterface.Address().IPv6
|
||||
}
|
||||
|
||||
func (e *Engine) RenewTun(fd int) error {
|
||||
e.syncMsgMux.Lock()
|
||||
wgInterface := e.wgInterface
|
||||
|
||||
@@ -24,14 +24,9 @@ func (s *Server) TracePacket(_ context.Context, req *proto.TracePacketRequest) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srcAddr, err := s.parseAddress(req.GetSourceIp(), engine)
|
||||
srcAddr, dstAddr, err := s.resolveTraceAddresses(req.GetSourceIp(), req.GetDestinationIp(), engine)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid source IP address: %w", err)
|
||||
}
|
||||
|
||||
dstAddr, err := s.parseAddress(req.GetDestinationIp(), engine)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid destination IP address: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
protocol, err := s.parseProtocol(req.GetProtocol())
|
||||
@@ -89,16 +84,59 @@ func (s *Server) getPacketTracer() (packetTracer, *internal.Engine, error) {
|
||||
return tracer, engine, nil
|
||||
}
|
||||
|
||||
func (s *Server) parseAddress(addr string, engine *internal.Engine) (netip.Addr, error) {
|
||||
if addr == "self" {
|
||||
return engine.GetWgAddr(), nil
|
||||
// resolveTraceAddresses parses src/dst, resolving "self" to the local overlay
|
||||
// address matching the peer's address family.
|
||||
func (s *Server) resolveTraceAddresses(src, dst string, engine *internal.Engine) (netip.Addr, netip.Addr, error) {
|
||||
srcSelf := src == "self"
|
||||
dstSelf := dst == "self"
|
||||
|
||||
if srcSelf && dstSelf {
|
||||
return netip.Addr{}, netip.Addr{}, fmt.Errorf("both source and destination cannot be 'self'")
|
||||
}
|
||||
|
||||
var srcAddr, dstAddr netip.Addr
|
||||
var err error
|
||||
|
||||
// Parse the non-self address first so we know the family for self resolution.
|
||||
if !srcSelf {
|
||||
if srcAddr, err = parseAddr(src); err != nil {
|
||||
return netip.Addr{}, netip.Addr{}, fmt.Errorf("invalid source IP: %w", err)
|
||||
}
|
||||
}
|
||||
if !dstSelf {
|
||||
if dstAddr, err = parseAddr(dst); err != nil {
|
||||
return netip.Addr{}, netip.Addr{}, fmt.Errorf("invalid destination IP: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the peer address to pick the right self address.
|
||||
peer := srcAddr
|
||||
if srcSelf {
|
||||
peer = dstAddr
|
||||
}
|
||||
|
||||
if srcSelf {
|
||||
srcAddr = selfAddr(engine, peer)
|
||||
}
|
||||
if dstSelf {
|
||||
dstAddr = selfAddr(engine, peer)
|
||||
}
|
||||
|
||||
return srcAddr, dstAddr, nil
|
||||
}
|
||||
|
||||
func selfAddr(engine *internal.Engine, peer netip.Addr) netip.Addr {
|
||||
if peer.Is6() {
|
||||
return engine.GetWgV6Addr()
|
||||
}
|
||||
return engine.GetWgAddr()
|
||||
}
|
||||
|
||||
func parseAddr(addr string) (netip.Addr, error) {
|
||||
a, err := netip.ParseAddr(addr)
|
||||
if err != nil {
|
||||
return netip.Addr{}, err
|
||||
}
|
||||
|
||||
return a.Unmap(), nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user