Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pkg/mesh/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func (t *Topology) Routes(kiloIfaceName string, kiloIface, privIface, tunlIface
Flags: int(netlink.FLAG_ONLINK),
Gw: segment.privateIPs[i],
LinkIndex: tunlIface,
Src: t.privateIP.IP,
Protocol: unix.RTPROT_STATIC,
Table: kiloTableIndex,
})
Expand Down Expand Up @@ -161,6 +162,7 @@ func (t *Topology) Routes(kiloIfaceName string, kiloIface, privIface, tunlIface
Flags: int(netlink.FLAG_ONLINK),
Gw: segment.privateIPs[i],
LinkIndex: tunlIface,
Src: t.privateIP.IP,
Protocol: unix.RTPROT_STATIC,
Table: kiloTableIndex,
})
Expand Down Expand Up @@ -304,8 +306,11 @@ func (t *Topology) PeerRoutes(name string, kiloIface int, additionalAllowedIPs [
}

func encapsulateRoute(route *netlink.Route, encapsulate encapsulation.Strategy, subnet *net.IPNet, tunlIface int) *netlink.Route {
if encapsulate == encapsulation.Always || (encapsulate == encapsulation.CrossSubnet && !subnet.Contains(route.Gw)) {
if encapsulate == encapsulation.Always || (encapsulate == encapsulation.CrossSubnet && subnet != nil && !subnet.Contains(route.Gw)) {
route.LinkIndex = tunlIface
if subnet != nil && route.Src == nil {
route.Src = subnet.IP
}
}
Comment on lines +309 to 314

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current logic for encapsulation when encapsulate == encapsulation.Always and subnet == nil could lead to issues. In this scenario, the route's LinkIndex is updated to tunlIface to enable encapsulation, but the source IP (Src) is not set. This might cause the kernel to select an incorrect source IP for the encapsulated packets.

To prevent this, we should avoid encapsulation altogether if a source IP (subnet) is not available.

I suggest modifying the condition to ensure subnet is not nil before attempting any encapsulation logic. This makes the function more robust and avoids creating potentially misconfigured routes.

Suggested change
if encapsulate == encapsulation.Always || (encapsulate == encapsulation.CrossSubnet && subnet != nil && !subnet.Contains(route.Gw)) {
route.LinkIndex = tunlIface
if subnet != nil && route.Src == nil {
route.Src = subnet.IP
}
}
if subnet != nil && (encapsulate == encapsulation.Always || (encapsulate == encapsulation.CrossSubnet && !subnet.Contains(route.Gw))) {
route.LinkIndex = tunlIface
if route.Src == nil {
route.Src = subnet.IP
}
}

return route
}
Expand Down
13 changes: 13 additions & 0 deletions pkg/mesh/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,13 +680,15 @@ func TestRoutes(t *testing.T) {
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["c"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["b"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: oneAddressCIDR(nodes["c"].InternalIP.IP),
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["c"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["b"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
Table: kiloTableIndex,
},
Expand Down Expand Up @@ -815,41 +817,47 @@ func TestRoutes(t *testing.T) {
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: nodes["a"].Subnet,
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: oneAddressCIDR(nodes["a"].InternalIP.IP),
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: oneAddressCIDR(mustTopoForGranularityAndHost(LogicalGranularity, nodes["c"].Name).segments[1].wireGuardIP),
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: nodes["b"].Subnet,
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: nodes["b"].InternalIP,
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
Table: kiloTableIndex,
},
Expand All @@ -858,34 +866,39 @@ func TestRoutes(t *testing.T) {
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: nodes["d"].Subnet,
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: &peers["a"].AllowedIPs[0],
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: &peers["a"].AllowedIPs[1],
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
{
Dst: &peers["b"].AllowedIPs[0],
Flags: int(netlink.FLAG_ONLINK),
Gw: nodes["b"].InternalIP.IP,
LinkIndex: tunlIface,
Src: nodes["c"].InternalIP.IP,
Protocol: unix.RTPROT_STATIC,
},
},
Expand Down