From 5164dc185aeb7dd1dbf110702d92b6bc7ccbc59c Mon Sep 17 00:00:00 2001 From: Manuel Buil Date: Fri, 21 Jul 2023 10:55:14 +0200 Subject: [PATCH] Fix tailscale bug with ip modes Signed-off-by: Manuel Buil --- pkg/agent/config/config.go | 20 +++++++++++++++---- pkg/cli/server/server.go | 40 +++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/pkg/agent/config/config.go b/pkg/agent/config/config.go index 183a939324..473c631a3f 100644 --- a/pkg/agent/config/config.go +++ b/pkg/agent/config/config.go @@ -33,6 +33,7 @@ import ( "github.com/rancher/wrangler/pkg/slice" "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/json" + utilsnet "k8s.io/utils/net" ) const ( @@ -405,14 +406,25 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N return nil, err } + // Pass ipv4, ipv6 or both depending on nodeIPs mode var vpnIPs []net.IP - if vpnInfo.IPv4Address != nil { - vpnIPs = append(vpnIPs, vpnInfo.IPv4Address) + dualNode, err := utilsnet.IsDualStackIPs(nodeIPs) + if err != nil { + return nil, errors.Wrapf(err, "failed to validate node-ip: %v", nodeIPs) } - if vpnInfo.IPv6Address != nil { - vpnIPs = append(vpnIPs, vpnInfo.IPv6Address) + if dualNode && vpnInfo.IPv4Address != nil && vpnInfo.IPv6Address != nil { + vpnIPs = append(vpnIPs, vpnInfo.IPv4Address, vpnInfo.IPv6Address) + } else { + if utilsnet.IsIPv4(nodeIPs[0]) && vpnInfo.IPv4Address != nil { + vpnIPs = append(vpnIPs, vpnInfo.IPv4Address) + } else if utilsnet.IsIPv6(nodeIPs[0]) && vpnInfo.IPv6Address != nil { + vpnIPs = append(vpnIPs, vpnInfo.IPv6Address) + } else { + return nil, errors.Errorf("address family mismatch when assigning VPN addresses to node: node=%v, VPN ipv4=%v ipv6=%v", nodeIPs, vpnInfo.IPv4Address, vpnInfo.IPv6Address) + } } + // Overwrite nodeip and flannel interface and throw a warning if user explicitly set those parameters if len(vpnIPs) != 0 { logrus.Infof("Node-ip changed to %v due to VPN", vpnIPs) if len(envInfo.NodeIP) != 0 { diff --git a/pkg/cli/server/server.go b/pkg/cli/server/server.go index 9341518508..6218295120 100644 --- a/pkg/cli/server/server.go +++ b/pkg/cli/server/server.go @@ -227,16 +227,36 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont serverConfig.ControlConfig.PrivateIP = util.GetFirstValidIPString(cmds.AgentConfig.NodeIP) } + // Ensure that we add the localhost name/ip and node name/ip to the SAN list. This list is shared by the + // certs for the supervisor, kube-apiserver cert, and etcd. DNS entries for the in-cluster kubernetes + // service endpoint are added later when the certificates are created. + nodeName, nodeIPs, err := util.GetHostnameAndIPs(cmds.AgentConfig.NodeName, cmds.AgentConfig.NodeIP) + if err != nil { + return err + } + serverConfig.ControlConfig.ServerNodeName = nodeName + serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, "127.0.0.1", "::1", "localhost", nodeName) + for _, ip := range nodeIPs { + serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, ip.String()) + } + // if not set, try setting advertise-ip from agent VPN if cmds.AgentConfig.VPNAuth != "" { vpnInfo, err := vpn.GetVPNInfo(cmds.AgentConfig.VPNAuth) if err != nil { return err } + + logrus.Debugf("Processing vpn node-ip based on the detected nodeIPs: %v", nodeIPs) + dualNode, err := utilsnet.IsDualStackIPs(nodeIPs) + if err != nil { + return errors.Wrapf(err, "failed to validate node-ip: %v", nodeIPs) + } + // If we are in ipv6-only mode, we should pass the ipv6 address. Otherwise, ipv4 - if utilsnet.IsIPv6CIDRString(util.JoinIPNets(serverConfig.ControlConfig.ClusterIPRanges)) { + if !dualNode && utilsnet.IsIPv6(nodeIPs[0]) { if vpnInfo.IPv6Address != nil { - logrus.Infof("Advertise-address changed to %v due to VPN", vpnInfo.IPv6Address) + logrus.Infof("Changed advertise-address to %v due to VPN", vpnInfo.IPv6Address) if serverConfig.ControlConfig.AdvertiseIP != "" { logrus.Warn("Conflict in the config detected. VPN integration overwrites advertise-address but the config is setting the advertise-address parameter") } @@ -245,8 +265,9 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont return errors.New("tailscale does not provide an ipv6 address") } } else { + // We are in dual-stack or ipv4-only mode if vpnInfo.IPv4Address != nil { - logrus.Infof("Advertise-address changed to %v due to VPN", vpnInfo.IPv4Address) + logrus.Infof("Changed advertise-address to %v due to VPN", vpnInfo.IPv4Address) if serverConfig.ControlConfig.AdvertiseIP != "" { logrus.Warn("Conflict in the config detected. VPN integration overwrites advertise-address but the config is setting the advertise-address parameter") } @@ -276,19 +297,6 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, serverConfig.ControlConfig.AdvertiseIP) } - // Ensure that we add the localhost name/ip and node name/ip to the SAN list. This list is shared by the - // certs for the supervisor, kube-apiserver cert, and etcd. DNS entries for the in-cluster kubernetes - // service endpoint are added later when the certificates are created. - nodeName, nodeIPs, err := util.GetHostnameAndIPs(cmds.AgentConfig.NodeName, cmds.AgentConfig.NodeIP) - if err != nil { - return err - } - serverConfig.ControlConfig.ServerNodeName = nodeName - serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, "127.0.0.1", "::1", "localhost", nodeName) - for _, ip := range nodeIPs { - serverConfig.ControlConfig.SANs = append(serverConfig.ControlConfig.SANs, ip.String()) - } - // configure ClusterIPRanges _, _, IPv6only, _ := util.GetFirstIP(nodeIPs) if len(cmds.ServerConfig.ClusterCIDR) == 0 {