github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/node/node_address.go (about) 1 // Copyright 2016-2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package node 16 17 import ( 18 "bufio" 19 "fmt" 20 "net" 21 "os" 22 "strconv" 23 "strings" 24 25 "github.com/cilium/cilium/api/v1/models" 26 "github.com/cilium/cilium/common" 27 "github.com/cilium/cilium/pkg/byteorder" 28 "github.com/cilium/cilium/pkg/cidr" 29 "github.com/cilium/cilium/pkg/defaults" 30 "github.com/cilium/cilium/pkg/logging/logfields" 31 "github.com/cilium/cilium/pkg/option" 32 ) 33 34 var ( 35 ipv4ClusterCidrMaskSize = defaults.DefaultIPv4ClusterPrefixLen 36 37 ipv4Loopback net.IP 38 ipv4ExternalAddress net.IP 39 ipv4InternalAddress net.IP 40 ipv4NodePortAddress net.IP 41 ipv6Address net.IP 42 ipv6RouterAddress net.IP 43 ipv6NodePortAddress net.IP 44 ipv4AllocRange *cidr.CIDR 45 ipv6AllocRange *cidr.CIDR 46 47 ipsecKeyIdentity uint8 48 ) 49 50 func makeIPv6HostIP() net.IP { 51 ipstr := "fc00::10CA:1" 52 ip := net.ParseIP(ipstr) 53 if ip == nil { 54 log.WithField(logfields.IPAddr, ipstr).Fatal("Unable to parse IP") 55 } 56 57 return ip 58 } 59 60 // SetIPv4ClusterCidrMaskSize sets the size of the mask of the IPv4 cluster prefix 61 func SetIPv4ClusterCidrMaskSize(size int) { 62 ipv4ClusterCidrMaskSize = size 63 } 64 65 // InitDefaultPrefix initializes the node address and allocation prefixes with 66 // default values derived from the system. device can be set to the primary 67 // network device of the system in which case the first address with global 68 // scope will be regarded as the system's node address. 69 func InitDefaultPrefix(device string) { 70 if option.Config.EnableIPv4 { 71 ip, err := firstGlobalV4Addr(device, GetInternalIPv4()) 72 if err != nil { 73 return 74 } 75 76 if ipv4ExternalAddress == nil { 77 ipv4ExternalAddress = ip 78 } 79 80 if ipv4AllocRange == nil { 81 // If the IPv6AllocRange is not nil then the IPv4 allocation should be 82 // derived from the IPv6AllocRange. 83 // vvvv vvvv 84 // FD00:0000:0000:0000:0000:0000:0000:0000 85 if ipv6AllocRange != nil { 86 ip = net.IPv4(ipv6AllocRange.IP[8], 87 ipv6AllocRange.IP[9], 88 ipv6AllocRange.IP[10], 89 ipv6AllocRange.IP[11]) 90 } 91 v4range := fmt.Sprintf(defaults.DefaultIPv4Prefix+"/%d", 92 ip.To4()[3], defaults.DefaultIPv4PrefixLen) 93 _, ip4net, err := net.ParseCIDR(v4range) 94 if err != nil { 95 log.WithError(err).WithField(logfields.V4Prefix, v4range).Panic("BUG: Invalid default IPv4 prefix") 96 } 97 98 ipv4AllocRange = cidr.NewCIDR(ip4net) 99 log.WithField(logfields.V4Prefix, ipv4AllocRange).Info("Using autogenerated IPv4 allocation range") 100 } 101 102 if option.Config.EnableNodePort { 103 // device is always non-nil here 104 ip, err := firstGlobalV4Addr(device, nil) 105 if err != nil { 106 return 107 } 108 109 if ipv4NodePortAddress == nil { 110 ipv4NodePortAddress = ip 111 } 112 } 113 } 114 115 if option.Config.EnableIPv6 { 116 if ipv6Address == nil { 117 // Find a IPv6 node address first 118 ipv6Address, _ = firstGlobalV6Addr(device, GetIPv6Router()) 119 if ipv6Address == nil { 120 ipv6Address = makeIPv6HostIP() 121 } 122 } 123 124 if ipv6AllocRange == nil && ipv4AllocRange != nil { 125 // The IPv6 allocation should be derived from the IPv4 allocation. 126 ip := ipv4AllocRange.IP 127 v6range := fmt.Sprintf("%s%02x%02x:%02x%02x:0:0/%d", 128 option.Config.IPv6ClusterAllocCIDRBase, ip[0], ip[1], ip[2], ip[3], 129 defaults.IPv6NodePrefixLen) 130 131 _, ip6net, err := net.ParseCIDR(v6range) 132 if err != nil { 133 log.WithError(err).WithField(logfields.V6Prefix, v6range).Panic("BUG: Invalid default IPv6 prefix") 134 } 135 136 ipv6AllocRange = cidr.NewCIDR(ip6net) 137 log.WithField(logfields.V6Prefix, ipv6AllocRange).Info("Using autogenerated IPv6 allocation range") 138 } 139 140 if option.Config.EnableNodePort { 141 ip, err := firstGlobalV6Addr(device, nil) 142 if err != nil { 143 return 144 } 145 146 if ipv6NodePortAddress == nil { 147 ipv6NodePortAddress = ip 148 } 149 } 150 } 151 } 152 153 // GetIPv4ClusterRange returns the IPv4 prefix of the cluster 154 func GetIPv4ClusterRange() *net.IPNet { 155 if ipv4AllocRange == nil { 156 return nil 157 } 158 159 mask := net.CIDRMask(ipv4ClusterCidrMaskSize, 32) 160 return &net.IPNet{ 161 IP: ipv4AllocRange.IPNet.IP.Mask(mask), 162 Mask: mask, 163 } 164 } 165 166 // GetIPv4Loopback returns the loopback IPv4 address of this node. 167 func GetIPv4Loopback() net.IP { 168 return ipv4Loopback 169 } 170 171 // SetIPv4Loopback sets the loopback IPv4 address of this node. 172 func SetIPv4Loopback(ip net.IP) { 173 ipv4Loopback = ip 174 } 175 176 // GetIPv4AllocRange returns the IPv4 allocation prefix of this node 177 func GetIPv4AllocRange() *cidr.CIDR { 178 return ipv4AllocRange 179 } 180 181 // GetIPv6AllocRange returns the IPv6 allocation prefix of this node 182 func GetIPv6AllocRange() *cidr.CIDR { 183 if ipv6AllocRange == nil { 184 return nil 185 } 186 187 mask := net.CIDRMask(defaults.IPv6NodeAllocPrefixLen, 128) 188 return cidr.NewCIDR(&net.IPNet{ 189 IP: ipv6AllocRange.IPNet.IP.Mask(mask), 190 Mask: mask, 191 }) 192 } 193 194 // GetIPv6NodeRange returns the IPv6 allocation prefix of this node 195 func GetIPv6NodeRange() *cidr.CIDR { 196 return ipv6AllocRange 197 } 198 199 // SetExternalIPv4 sets the external IPv4 node address. It must be reachable on the network. 200 func SetExternalIPv4(ip net.IP) { 201 ipv4ExternalAddress = ip 202 } 203 204 // GetExternalIPv4 returns the external IPv4 node address 205 func GetExternalIPv4() net.IP { 206 return ipv4ExternalAddress 207 } 208 209 // SetInternalIPv4 sets the internal IPv4 node address, it is allocated from the node prefix 210 func SetInternalIPv4(ip net.IP) { 211 ipv4InternalAddress = ip 212 } 213 214 // GetInternalIPv4 returns the internal IPv4 node address 215 func GetInternalIPv4() net.IP { 216 return ipv4InternalAddress 217 } 218 219 // GetHostMasqueradeIPv4 returns the IPv4 address to be used for masquerading 220 // any traffic that is being forwarded from the host into the Cilium cluster. 221 func GetHostMasqueradeIPv4() net.IP { 222 return ipv4InternalAddress 223 } 224 225 // SetIPv4AllocRange sets the IPv4 address pool to use when allocating 226 // addresses for local endpoints 227 func SetIPv4AllocRange(net *cidr.CIDR) { 228 ipv4AllocRange = net 229 } 230 231 // Uninitialize resets this package to the default state, for use in 232 // testsuite code. 233 func Uninitialize() { 234 ipv4AllocRange = nil 235 ipv6AllocRange = nil 236 } 237 238 // GetNodePortIPv4 returns the node-port IPv4 address for NAT 239 func GetNodePortIPv4() net.IP { 240 return ipv4NodePortAddress 241 } 242 243 // GetNodePortIPv6 returns the node-port IPv4 address for NAT 244 func GetNodePortIPv6() net.IP { 245 return ipv6NodePortAddress 246 } 247 248 // SetIPv6NodeRange sets the IPv6 address pool to be used on this node 249 func SetIPv6NodeRange(net *net.IPNet) error { 250 if ones, _ := net.Mask.Size(); ones != defaults.IPv6NodePrefixLen { 251 return fmt.Errorf("prefix length must be /%d", defaults.IPv6NodePrefixLen) 252 } 253 254 copy := *net 255 ipv6AllocRange = cidr.NewCIDR(©) 256 257 return nil 258 } 259 260 // AutoComplete completes the parts of addressing that can be auto derived 261 func AutoComplete() error { 262 if option.Config.EnableHostIPRestore { 263 // Read the previous cilium host IPs from node_config.h for backward 264 // compatibility 265 ipv4GW, ipv6Router := getCiliumHostIPs() 266 267 if ipv4GW != nil && option.Config.EnableIPv4 { 268 log.Infof("Restored IPv4 internal node IP: %s", ipv4GW.String()) 269 SetInternalIPv4(ipv4GW) 270 } 271 272 if ipv6Router != nil && option.Config.EnableIPv6 { 273 log.Infof("Restored IPv6 router IP: %s", ipv6Router.String()) 274 SetIPv6Router(ipv6Router) 275 } 276 } 277 278 if option.Config.Device == "undefined" { 279 InitDefaultPrefix("") 280 } 281 282 if option.Config.EnableIPv6 && ipv6AllocRange == nil { 283 return fmt.Errorf("IPv6 allocation CIDR is not configured. Please specificy --ipv6-range") 284 } 285 286 if option.Config.EnableIPv4 && ipv4AllocRange == nil { 287 return fmt.Errorf("IPv4 allocation CIDR is not configured. Please specificy --ipv4-range") 288 } 289 290 return nil 291 } 292 293 // ValidatePostInit validates the entire addressing setup and completes it as 294 // required 295 func ValidatePostInit() error { 296 if option.Config.EnableIPv4 || option.Config.Tunnel != option.TunnelDisabled { 297 if ipv4ExternalAddress == nil { 298 return fmt.Errorf("external IPv4 node address could not be derived, please configure via --ipv4-node") 299 } 300 } 301 302 if option.Config.EnableIPv4 { 303 if ipv4InternalAddress == nil { 304 return fmt.Errorf("BUG: Internal IPv4 node address was not configured") 305 } 306 307 ones, _ := ipv4AllocRange.Mask.Size() 308 if ipv4ClusterCidrMaskSize > ones { 309 return fmt.Errorf("IPv4 per node allocation prefix (%s) must be inside cluster prefix (%s)", 310 ipv4AllocRange, GetIPv4ClusterRange()) 311 } 312 } 313 314 return nil 315 } 316 317 // SetIPv6 sets the IPv6 address of the node 318 func SetIPv6(ip net.IP) { 319 ipv6Address = ip 320 } 321 322 // GetIPv6 returns the IPv6 address of the node 323 func GetIPv6() net.IP { 324 return ipv6Address 325 } 326 327 // GetIPv6Router returns the IPv6 address of the node 328 func GetIPv6Router() net.IP { 329 return ipv6RouterAddress 330 } 331 332 // SetIPv6Router returns the IPv6 address of the node 333 func SetIPv6Router(ip net.IP) { 334 ipv6RouterAddress = ip 335 } 336 337 // IsHostIPv4 returns true if the IP specified is a host IP 338 func IsHostIPv4(ip net.IP) bool { 339 return ip.Equal(GetInternalIPv4()) || ip.Equal(GetExternalIPv4()) 340 } 341 342 // IsHostIPv6 returns true if the IP specified is a host IP 343 func IsHostIPv6(ip net.IP) bool { 344 return ip.Equal(GetIPv6()) || ip.Equal(GetIPv6Router()) 345 } 346 347 // GetNodeAddressing returns the NodeAddressing model for the local IPs. 348 func GetNodeAddressing() *models.NodeAddressing { 349 a := &models.NodeAddressing{} 350 351 if option.Config.EnableIPv6 { 352 a.IPV6 = &models.NodeAddressingElement{ 353 Enabled: option.Config.EnableIPv6, 354 IP: GetIPv6Router().String(), 355 AllocRange: GetIPv6AllocRange().String(), 356 } 357 } 358 359 if option.Config.EnableIPv4 { 360 a.IPV4 = &models.NodeAddressingElement{ 361 Enabled: option.Config.EnableIPv4, 362 IP: GetInternalIPv4().String(), 363 AllocRange: GetIPv4AllocRange().String(), 364 } 365 } 366 367 return a 368 } 369 370 func getCiliumHostIPsFromFile(nodeConfig string) (ipv4GW, ipv6Router net.IP) { 371 var hasIPv4, hasIPv6 bool 372 f, err := os.Open(nodeConfig) 373 switch { 374 case err != nil: 375 default: 376 defer f.Close() 377 scanner := bufio.NewScanner(f) 378 for scanner.Scan() { 379 txt := scanner.Text() 380 switch { 381 case !hasIPv6 && strings.Contains(txt, defaults.RestoreV6Addr): 382 defineLine := strings.Split(txt, defaults.RestoreV6Addr) 383 if len(defineLine) != 2 { 384 continue 385 } 386 ipv6 := common.C2GoArray(defineLine[1]) 387 if len(ipv6) != net.IPv6len { 388 continue 389 } 390 ipv6Router = net.IP(ipv6) 391 hasIPv6 = true 392 case !hasIPv4 && strings.Contains(txt, defaults.RestoreV4Addr): 393 defineLine := strings.Split(txt, defaults.RestoreV4Addr) 394 if len(defineLine) != 2 { 395 continue 396 } 397 ipv4 := common.C2GoArray(defineLine[1]) 398 if len(ipv4) != net.IPv6len { 399 continue 400 } 401 ipv4GW = net.IP(ipv4) 402 hasIPv4 = true 403 404 // Legacy cases based on the header defines: 405 case !hasIPv4 && strings.Contains(txt, "IPV4_GATEWAY"): 406 // #define IPV4_GATEWAY 0xee1c000a 407 defineLine := strings.Split(txt, " ") 408 if len(defineLine) != 3 { 409 continue 410 } 411 ipv4GWHex := strings.TrimPrefix(defineLine[2], "0x") 412 ipv4GWint64, err := strconv.ParseInt(ipv4GWHex, 16, 0) 413 if err != nil { 414 continue 415 } 416 if ipv4GWint64 != int64(0) { 417 bs := make([]byte, net.IPv4len) 418 byteorder.NetworkToHostPut(bs, uint32(ipv4GWint64)) 419 ipv4GW = net.IPv4(bs[0], bs[1], bs[2], bs[3]) 420 hasIPv4 = true 421 } 422 case !hasIPv6 && strings.Contains(txt, " ROUTER_IP "): 423 // #define ROUTER_IP 0xf0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8a, 0xd6 424 defineLine := strings.Split(txt, " ROUTER_IP ") 425 if len(defineLine) != 2 { 426 continue 427 } 428 ipv6 := common.C2GoArray(defineLine[1]) 429 if len(ipv6) != net.IPv6len { 430 continue 431 } 432 ipv6Router = net.IP(ipv6) 433 hasIPv6 = true 434 } 435 } 436 } 437 return ipv4GW, ipv6Router 438 } 439 440 // getCiliumHostIPs returns the Cilium IPv4 gateway and router IPv6 address from 441 // the node_config.h file if is present; or by deriving it from 442 // defaults.HostDevice interface, on which only the IPv4 is possible to derive. 443 func getCiliumHostIPs() (ipv4GW, ipv6Router net.IP) { 444 nodeConfig := option.Config.GetNodeConfigPath() 445 ipv4GW, ipv6Router = getCiliumHostIPsFromFile(nodeConfig) 446 if ipv4GW != nil { 447 return ipv4GW, ipv6Router 448 } 449 return getCiliumHostIPsFromNetDev(option.Config.HostDevice) 450 } 451 452 // SetIPsecKeyIdentity sets the IPsec key identity an opaque value used to 453 // identity encryption keys used on the node. 454 func SetIPsecKeyIdentity(id uint8) { 455 ipsecKeyIdentity = id 456 } 457 458 // GetIPsecKeyIdentity returns the IPsec key identity of the node 459 func GetIPsecKeyIdentity() uint8 { 460 return ipsecKeyIdentity 461 }