diff --git a/lib/vnet/osconfig.go b/lib/vnet/osconfig.go index c27336fe33c17..307b3363f0170 100644 --- a/lib/vnet/osconfig.go +++ b/lib/vnet/osconfig.go @@ -18,6 +18,7 @@ package vnet import ( "context" + "net" "net/netip" "os/exec" "strings" @@ -29,6 +30,7 @@ import ( type osConfig struct { tunName string tunIPv4 string + tunIPv4Net *net.IPNet tunIPv6 string cidrRanges []string dnsAddrs []string diff --git a/lib/vnet/osconfig_provider.go b/lib/vnet/osconfig_provider.go index a2f4bbf4233bd..64975a762d121 100644 --- a/lib/vnet/osconfig_provider.go +++ b/lib/vnet/osconfig_provider.go @@ -29,10 +29,11 @@ import ( // osConfigProvider fetches a target OS configuration based on cluster // configuration fetched via the client application process available over gRPC. type osConfigProvider struct { - cfg osConfigProviderConfig - dnsAddrs []string - tunIPv6 string - tunIPv4 string + cfg osConfigProviderConfig + dnsAddrs []string + tunIPv6 string + tunIPv4 string + tunIPv4Net *net.IPNet } // osConfigProviderConfig holds configuration parameters for an osConfigProvider. @@ -78,6 +79,7 @@ func (p *osConfigProvider) targetOSConfig(ctx context.Context) (*osConfig, error tunName: p.cfg.tunName, tunIPv6: p.tunIPv6, tunIPv4: p.tunIPv4, + tunIPv4Net: p.tunIPv4Net, dnsAddrs: p.dnsAddrs, dnsZones: targetOSConfig.GetDnsZones(), cidrRanges: targetOSConfig.GetIpv4CidrRanges(), @@ -89,7 +91,7 @@ func (p *osConfigProvider) setV4IPsFromFirstCIDR(cidrRange string) error { // Only set these once. return nil } - tunIPv4, dnsIPv4, err := ipsForCIDR(cidrRange) + tunIPv4, tunIPv4Net, dnsIPv4, err := ipsForCIDR(cidrRange) if err != nil { return trace.Wrap(err, "setting TUN IPv4 address for range %s", cidrRange) } @@ -97,25 +99,26 @@ func (p *osConfigProvider) setV4IPsFromFirstCIDR(cidrRange string) error { return trace.Wrap(err, "adding IPv4 DNS server at %s", dnsIPv4.String()) } p.tunIPv4 = tunIPv4.String() + p.tunIPv4Net = tunIPv4Net p.dnsAddrs = append(p.dnsAddrs, dnsIPv4.String()) return nil } // ipsForCIDR returns the V4 IPs to assign to the interface and use for DNS in // cidrRange. -func ipsForCIDR(cidrRange string) (tunIP net.IP, dnsIP net.IP, err error) { - _, ipnet, err := net.ParseCIDR(cidrRange) +func ipsForCIDR(cidrRange string) (tunIP net.IP, tunIPNet *net.IPNet, dnsIP net.IP, err error) { + _, tunIPNet, err = net.ParseCIDR(cidrRange) if err != nil { - return nil, nil, trace.Wrap(err, "parsing CIDR %q", cidrRange) + return nil, nil, nil, trace.Wrap(err, "parsing CIDR %q", cidrRange) } - // ipnet.IP is the network address, ending in 0s, like 100.64.0.0 + // tunIPNet.IP is the network address, ending in 0s, like 100.64.0.0 // Add 1 to assign the TUN address, like 100.64.0.1 - tunIP = ipnet.IP + tunIP = slices.Clone(tunIPNet.IP) tunIP[len(tunIP)-1]++ // Add 1 again to assign the DNS address, like 100.64.0.2 dnsIP = slices.Clone(tunIP) dnsIP[len(dnsIP)-1]++ - return tunIP, dnsIP, nil + return tunIP, tunIPNet, dnsIP, nil } diff --git a/lib/vnet/osconfig_provider_test.go b/lib/vnet/osconfig_provider_test.go index dd4014fd6123d..e368524ee465e 100644 --- a/lib/vnet/osconfig_provider_test.go +++ b/lib/vnet/osconfig_provider_test.go @@ -65,8 +65,9 @@ func TestOSConfigProvider(t *testing.T) { expectTargetOSConfig: &osConfig{ tunName: "testtun1", // Should be the first non-broadcast address in the CIDR range. - tunIPv4: "192.168.1.1", - tunIPv6: "fd01:2345:6789::1", + tunIPv4: "192.168.1.1", + tunIPv4Net: &net.IPNet{IP: []byte{192, 168, 1, 0}, Mask: []byte{255, 255, 255, 0}}, + tunIPv6: "fd01:2345:6789::1", // Should include the second non-broadcast address in the CIDR range. dnsAddrs: []string{"fd01:2345:6789::2", "192.168.1.2"}, dnsZones: []string{"test.example.com"}, @@ -79,15 +80,16 @@ func TestOSConfigProvider(t *testing.T) { ipv6Prefix: "fd01:2345:6789::", dnsIPv6: "fd01:2345:6789::2", dnsZones: []string{"test.example.com"}, - ipv4CIDRRanges: []string{"10.64.0.0/16", "192.168.1.0/24"}, + ipv4CIDRRanges: []string{"10.64.0.0/10", "192.168.1.0/24"}, expectTargetOSConfig: &osConfig{ tunName: "testtun1", // Should be chosen from the first CIDR range. tunIPv4: "10.64.0.1", + tunIPv4Net: &net.IPNet{IP: []byte{10, 64, 0, 0}, Mask: []byte{255, 192, 0, 0}}, tunIPv6: "fd01:2345:6789::1", dnsAddrs: []string{"fd01:2345:6789::2", "10.64.0.2"}, dnsZones: []string{"test.example.com"}, - cidrRanges: []string{"10.64.0.0/16", "192.168.1.0/24"}, + cidrRanges: []string{"10.64.0.0/10", "192.168.1.0/24"}, }, }, } { diff --git a/lib/vnet/osconfig_windows.go b/lib/vnet/osconfig_windows.go index 6ce2df16eb698..b480d2d7a5a67 100644 --- a/lib/vnet/osconfig_windows.go +++ b/lib/vnet/osconfig_windows.go @@ -68,8 +68,9 @@ func platformConfigureOS(ctx context.Context, cfg *osConfig, state *platformOSCo if !state.configuredV4Address { log.InfoContext(ctx, "Setting IPv4 address for the TUN device", "device", cfg.tunName, "address", cfg.tunIPv4) + netMask := maskForIPNet(cfg.tunIPv4Net) if err := runCommand(ctx, - "netsh", "interface", "ip", "set", "address", cfg.tunName, "static", cfg.tunIPv4, + "netsh", "interface", "ip", "set", "address", cfg.tunName, "static", cfg.tunIPv4, netMask, ); err != nil { return trace.Wrap(err) } @@ -126,7 +127,11 @@ func addrMaskForCIDR(cidr string) (string, string, error) { if err != nil { return "", "", trace.Wrap(err, "parsing CIDR range %s", cidr) } - return ipNet.IP.String(), net.IP(ipNet.Mask).String(), nil + return ipNet.IP.String(), maskForIPNet(ipNet), nil +} + +func maskForIPNet(ipNet *net.IPNet) string { + return net.IP(ipNet.Mask).String() } const (