listen_addr.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. package cluster
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. )
  7. var (
  8. errNoSuchInterface = errors.New("no such interface")
  9. errNoIP = errors.New("could not find the system's IP address")
  10. errMustSpecifyListenAddr = errors.New("must specify a listening address because the address to advertise is not recognized as a system address")
  11. errBadListenAddr = errors.New("listen address must be an IP address or network interface (with optional port number)")
  12. errBadAdvertiseAddr = errors.New("advertise address must be an IP address or network interface (with optional port number)")
  13. errBadDefaultAdvertiseAddr = errors.New("default advertise address must be an IP address or network interface (without a port number)")
  14. )
  15. func resolveListenAddr(specifiedAddr string) (string, string, error) {
  16. specifiedHost, specifiedPort, err := net.SplitHostPort(specifiedAddr)
  17. if err != nil {
  18. return "", "", fmt.Errorf("could not parse listen address %s", specifiedAddr)
  19. }
  20. // Does the host component match any of the interface names on the
  21. // system? If so, use the address from that interface.
  22. interfaceAddr, err := resolveInterfaceAddr(specifiedHost)
  23. if err == nil {
  24. return interfaceAddr.String(), specifiedPort, nil
  25. }
  26. if err != errNoSuchInterface {
  27. return "", "", err
  28. }
  29. // If it's not an interface, it must be an IP (for now)
  30. if net.ParseIP(specifiedHost) == nil {
  31. return "", "", errBadListenAddr
  32. }
  33. return specifiedHost, specifiedPort, nil
  34. }
  35. func (c *Cluster) resolveAdvertiseAddr(advertiseAddr, listenAddrPort string) (string, string, error) {
  36. // Approach:
  37. // - If an advertise address is specified, use that. Resolve the
  38. // interface's address if an interface was specified in
  39. // advertiseAddr. Fill in the port from listenAddrPort if necessary.
  40. // - If DefaultAdvertiseAddr is not empty, use that with the port from
  41. // listenAddrPort. Resolve the interface's address from
  42. // if an interface name was specified in DefaultAdvertiseAddr.
  43. // - Otherwise, try to autodetect the system's address. Use the port in
  44. // listenAddrPort with this address if autodetection succeeds.
  45. if advertiseAddr != "" {
  46. advertiseHost, advertisePort, err := net.SplitHostPort(advertiseAddr)
  47. if err != nil {
  48. // Not a host:port specification
  49. advertiseHost = advertiseAddr
  50. advertisePort = listenAddrPort
  51. }
  52. // Does the host component match any of the interface names on the
  53. // system? If so, use the address from that interface.
  54. interfaceAddr, err := resolveInterfaceAddr(advertiseHost)
  55. if err == nil {
  56. return interfaceAddr.String(), advertisePort, nil
  57. }
  58. if err != errNoSuchInterface {
  59. return "", "", err
  60. }
  61. // If it's not an interface, it must be an IP (for now)
  62. if net.ParseIP(advertiseHost) == nil {
  63. return "", "", errBadAdvertiseAddr
  64. }
  65. return advertiseHost, advertisePort, nil
  66. }
  67. if c.config.DefaultAdvertiseAddr != "" {
  68. // Does the default advertise address component match any of the
  69. // interface names on the system? If so, use the address from
  70. // that interface.
  71. interfaceAddr, err := resolveInterfaceAddr(c.config.DefaultAdvertiseAddr)
  72. if err == nil {
  73. return interfaceAddr.String(), listenAddrPort, nil
  74. }
  75. if err != errNoSuchInterface {
  76. return "", "", err
  77. }
  78. // If it's not an interface, it must be an IP (for now)
  79. if net.ParseIP(c.config.DefaultAdvertiseAddr) == nil {
  80. return "", "", errBadDefaultAdvertiseAddr
  81. }
  82. return c.config.DefaultAdvertiseAddr, listenAddrPort, nil
  83. }
  84. systemAddr, err := c.resolveSystemAddr()
  85. if err != nil {
  86. return "", "", err
  87. }
  88. return systemAddr.String(), listenAddrPort, nil
  89. }
  90. func resolveInterfaceAddr(specifiedInterface string) (net.IP, error) {
  91. // Use a specific interface's IP address.
  92. intf, err := net.InterfaceByName(specifiedInterface)
  93. if err != nil {
  94. return nil, errNoSuchInterface
  95. }
  96. addrs, err := intf.Addrs()
  97. if err != nil {
  98. return nil, err
  99. }
  100. var interfaceAddr4, interfaceAddr6 net.IP
  101. for _, addr := range addrs {
  102. ipAddr, ok := addr.(*net.IPNet)
  103. if ok {
  104. if ipAddr.IP.To4() != nil {
  105. // IPv4
  106. if interfaceAddr4 != nil {
  107. return nil, fmt.Errorf("interface %s has more than one IPv4 address", specifiedInterface)
  108. }
  109. interfaceAddr4 = ipAddr.IP
  110. } else {
  111. // IPv6
  112. if interfaceAddr6 != nil {
  113. return nil, fmt.Errorf("interface %s has more than one IPv6 address", specifiedInterface)
  114. }
  115. interfaceAddr6 = ipAddr.IP
  116. }
  117. }
  118. }
  119. if interfaceAddr4 == nil && interfaceAddr6 == nil {
  120. return nil, fmt.Errorf("interface %s has no usable IPv4 or IPv6 address", specifiedInterface)
  121. }
  122. // In the case that there's exactly one IPv4 address
  123. // and exactly one IPv6 address, favor IPv4 over IPv6.
  124. if interfaceAddr4 != nil {
  125. return interfaceAddr4, nil
  126. }
  127. return interfaceAddr6, nil
  128. }
  129. func (c *Cluster) resolveSystemAddr() (net.IP, error) {
  130. // Use the system's only IP address, or fail if there are
  131. // multiple addresses to choose from.
  132. interfaces, err := net.Interfaces()
  133. if err != nil {
  134. return nil, err
  135. }
  136. var systemAddr net.IP
  137. var systemInterface net.Interface
  138. // List Docker-managed subnets
  139. v4Subnets := c.config.NetworkSubnetsProvider.V4Subnets()
  140. v6Subnets := c.config.NetworkSubnetsProvider.V6Subnets()
  141. ifaceLoop:
  142. for _, intf := range interfaces {
  143. // Skip inactive interfaces and loopback interfaces
  144. if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 {
  145. continue
  146. }
  147. addrs, err := intf.Addrs()
  148. if err != nil {
  149. continue
  150. }
  151. var interfaceAddr4, interfaceAddr6 net.IP
  152. for _, addr := range addrs {
  153. ipAddr, ok := addr.(*net.IPNet)
  154. // Skip loopback and link-local addresses
  155. if !ok || !ipAddr.IP.IsGlobalUnicast() {
  156. continue
  157. }
  158. if ipAddr.IP.To4() != nil {
  159. // IPv4
  160. // Ignore addresses in subnets that are managed by Docker.
  161. for _, subnet := range v4Subnets {
  162. if subnet.Contains(ipAddr.IP) {
  163. continue ifaceLoop
  164. }
  165. }
  166. if interfaceAddr4 != nil {
  167. return nil, fmt.Errorf("could not choose an IP address to advertise since this system has multiple addresses on interface %s (%s and %s)", intf.Name, interfaceAddr4, ipAddr.IP)
  168. }
  169. interfaceAddr4 = ipAddr.IP
  170. } else {
  171. // IPv6
  172. // Ignore addresses in subnets that are managed by Docker.
  173. for _, subnet := range v6Subnets {
  174. if subnet.Contains(ipAddr.IP) {
  175. continue ifaceLoop
  176. }
  177. }
  178. if interfaceAddr6 != nil {
  179. return nil, fmt.Errorf("could not choose an IP address to advertise since this system has multiple addresses on interface %s (%s and %s)", intf.Name, interfaceAddr6, ipAddr.IP)
  180. }
  181. interfaceAddr6 = ipAddr.IP
  182. }
  183. }
  184. // In the case that this interface has exactly one IPv4 address
  185. // and exactly one IPv6 address, favor IPv4 over IPv6.
  186. if interfaceAddr4 != nil {
  187. if systemAddr != nil {
  188. return nil, fmt.Errorf("could not choose an IP address to advertise since this system has multiple addresses on different interfaces (%s on %s and %s on %s)", systemAddr, systemInterface.Name, interfaceAddr4, intf.Name)
  189. }
  190. systemAddr = interfaceAddr4
  191. systemInterface = intf
  192. } else if interfaceAddr6 != nil {
  193. if systemAddr != nil {
  194. return nil, fmt.Errorf("could not choose an IP address to advertise since this system has multiple addresses on different interfaces (%s on %s and %s on %s)", systemAddr, systemInterface.Name, interfaceAddr6, intf.Name)
  195. }
  196. systemAddr = interfaceAddr6
  197. systemInterface = intf
  198. }
  199. }
  200. if systemAddr == nil {
  201. return nil, errNoIP
  202. }
  203. return systemAddr, nil
  204. }
  205. func listSystemIPs() []net.IP {
  206. interfaces, err := net.Interfaces()
  207. if err != nil {
  208. return nil
  209. }
  210. var systemAddrs []net.IP
  211. for _, intf := range interfaces {
  212. addrs, err := intf.Addrs()
  213. if err != nil {
  214. continue
  215. }
  216. for _, addr := range addrs {
  217. ipAddr, ok := addr.(*net.IPNet)
  218. if ok {
  219. systemAddrs = append(systemAddrs, ipAddr.IP)
  220. }
  221. }
  222. }
  223. return systemAddrs
  224. }