Check if we are on ipv4, ipv6 or dualStack when doing tailscale

Signed-off-by: Manuel Buil <mbuil@suse.com>
This commit is contained in:
Manuel Buil 2023-06-29 16:23:14 +02:00
parent 2215870d5d
commit f21a01474d
4 changed files with 44 additions and 21 deletions

View File

@ -390,15 +390,24 @@ func get(ctx context.Context, envInfo *cmds.Agent, proxy proxy.Proxy) (*config.N
if err != nil {
return nil, err
}
if len(vpnInfo.IPs) != 0 {
logrus.Infof("Node-ip changed to %v due to VPN", vpnInfo.IPs)
var vpnIPs []net.IP
if vpnInfo.IPv4Address != nil {
vpnIPs = append(vpnIPs, vpnInfo.IPv4Address)
}
if vpnInfo.IPv6Address != nil {
vpnIPs = append(vpnIPs, vpnInfo.IPv6Address)
}
if len(vpnIPs) != 0 {
logrus.Infof("Node-ip changed to %v due to VPN", vpnIPs)
if len(envInfo.NodeIP) != 0 {
logrus.Warn("VPN provider overrides configured node-ip parameter")
}
if len(envInfo.NodeExternalIP) != 0 {
logrus.Warn("VPN provider overrides node-external-ip parameter")
}
nodeIPs = vpnInfo.IPs
nodeIPs = vpnIPs
flannelIface, err = net.InterfaceByName(vpnInfo.VPNInterface)
if err != nil {
return nil, errors.Wrapf(err, "unable to find vpn interface: %s", vpnInfo.VPNInterface)

View File

@ -228,12 +228,27 @@ func run(app *cli.Context, cfg *cmds.Server, leaderControllers server.CustomCont
if err != nil {
return err
}
if len(vpnInfo.IPs) != 0 {
logrus.Infof("Advertise-address changed to %v due to VPN", vpnInfo.IPs)
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")
// If we are in ipv6-only mode, we should pass the ipv6 address. Otherwise, ipv4
if utilsnet.IsIPv6CIDRString(util.JoinIPNets(serverConfig.ControlConfig.ClusterIPRanges)) {
if vpnInfo.IPv6Address != nil {
logrus.Infof("Advertise-address changed 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")
}
serverConfig.ControlConfig.AdvertiseIP = vpnInfo.IPv6Address.String()
} else {
return errors.New("tailscale does not provide an ipv6 address")
}
} else {
if vpnInfo.IPv4Address != nil {
logrus.Infof("Advertise-address changed 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")
}
serverConfig.ControlConfig.AdvertiseIP = vpnInfo.IPv4Address.String()
} else {
return errors.New("tailscale does not provide an ipv4 address")
}
serverConfig.ControlConfig.AdvertiseIP = vpnInfo.IPs[0].String()
}
logrus.Warn("Etcd IP (PrivateIP) remains the local IP. Running etcd traffic over VPN is not recommended due to performance issues")
} else {

View File

@ -10,6 +10,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
apinet "k8s.io/apimachinery/pkg/util/net"
netutils "k8s.io/utils/net"
)
// JoinIPs stringifies and joins a list of IP addresses with commas.
@ -85,10 +86,9 @@ func JoinIP4Nets(elems []*net.IPNet) string {
// If no IPv6 addresses are found, an error is raised.
func GetFirst6(elems []net.IP) (net.IP, error) {
for _, elem := range elems {
if elem == nil || elem.To16() == nil {
continue
if elem != nil && netutils.IsIPv6(elem) {
return elem, nil
}
return elem, nil
}
return nil, errors.New("no IPv6 address found")
}
@ -97,10 +97,9 @@ func GetFirst6(elems []net.IP) (net.IP, error) {
// If no IPv6 addresses are found, an error is raised.
func GetFirst6Net(elems []*net.IPNet) (*net.IPNet, error) {
for _, elem := range elems {
if elem == nil || elem.IP.To16() == nil {
continue
if elem != nil && netutils.IsIPv6(elem.IP) {
return elem, nil
}
return elem, nil
}
return nil, errors.New("no IPv6 CIDRs found")
}
@ -125,7 +124,7 @@ func GetFirst6String(elems []string) (string, error) {
func JoinIP6Nets(elems []*net.IPNet) string {
var strs []string
for _, elem := range elems {
if elem != nil && elem.IP.To4() == nil {
if elem != nil && netutils.IsIPv6(elem.IP) {
strs = append(strs, elem.String())
}
}

View File

@ -22,7 +22,8 @@ type TailscaleOutput struct {
// VPNInfo includes node information of the VPN. It is a general struct in case we want to add more vpn integrations
type VPNInfo struct {
IPs []net.IP
IPv4Address net.IP
IPv6Address net.IP
NodeID string
ProviderName string
VPNInterface string
@ -112,15 +113,14 @@ func getTailscaleInfo() (VPNInfo, error) {
logrus.Debugf("Output from tailscale status --json: %v", output)
var tailscaleOutput TailscaleOutput
var internalIPs []net.IP
err = json.Unmarshal([]byte(output), &tailscaleOutput)
if err != nil {
return VPNInfo{}, fmt.Errorf("failed to unmarshal tailscale output: %v", err)
}
for _, address := range tailscaleOutput.TailscaleIPs {
internalIPs = append(internalIPs, net.ParseIP(address))
}
// Errors are ignored because the interface might not have ipv4 or ipv6 addresses (that's the only possible error)
ipv4Address, _ := util.GetFirst4String(tailscaleOutput.TailscaleIPs)
ipv6Address, _ := util.GetFirst6String(tailscaleOutput.TailscaleIPs)
return VPNInfo{IPs: internalIPs, NodeID: "", ProviderName: "tailscale", VPNInterface: tailscaleIf}, nil
return VPNInfo{IPv4Address: net.ParseIP(ipv4Address), IPv6Address: net.ParseIP(ipv6Address), NodeID: "", ProviderName: "tailscale", VPNInterface: tailscaleIf}, nil
}