listen_addr.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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, and a system's IP address to use could not be uniquely identified")
  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 a non-zero IP address or network interface (with optional port number)")
  13. errBadDefaultAdvertiseAddr = errors.New("default advertise address must be a non-zero 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 ip := net.ParseIP(advertiseHost); ip == nil || ip.IsUnspecified() {
  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 ip := net.ParseIP(c.config.DefaultAdvertiseAddr); ip == nil || ip.IsUnspecified() {
  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 (%s and %s)", specifiedInterface, interfaceAddr4, ipAddr.IP)
  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 (%s and %s)", specifiedInterface, interfaceAddr6, ipAddr.IP)
  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) resolveSystemAddrViaSubnetCheck() (net.IP, error) {
  130. // Use the system's only IP address, or fail if there are
  131. // multiple addresses to choose from. Skip interfaces which
  132. // are managed by docker via subnet check.
  133. interfaces, err := net.Interfaces()
  134. if err != nil {
  135. return nil, err
  136. }
  137. var systemAddr net.IP
  138. var systemInterface string
  139. // List Docker-managed subnets
  140. v4Subnets := c.config.NetworkSubnetsProvider.V4Subnets()
  141. v6Subnets := c.config.NetworkSubnetsProvider.V6Subnets()
  142. ifaceLoop:
  143. for _, intf := range interfaces {
  144. // Skip inactive interfaces and loopback interfaces
  145. if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 {
  146. continue
  147. }
  148. addrs, err := intf.Addrs()
  149. if err != nil {
  150. continue
  151. }
  152. var interfaceAddr4, interfaceAddr6 net.IP
  153. for _, addr := range addrs {
  154. ipAddr, ok := addr.(*net.IPNet)
  155. // Skip loopback and link-local addresses
  156. if !ok || !ipAddr.IP.IsGlobalUnicast() {
  157. continue
  158. }
  159. if ipAddr.IP.To4() != nil {
  160. // IPv4
  161. // Ignore addresses in subnets that are managed by Docker.
  162. for _, subnet := range v4Subnets {
  163. if subnet.Contains(ipAddr.IP) {
  164. continue ifaceLoop
  165. }
  166. }
  167. if interfaceAddr4 != nil {
  168. return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr4, ipAddr.IP)
  169. }
  170. interfaceAddr4 = ipAddr.IP
  171. } else {
  172. // IPv6
  173. // Ignore addresses in subnets that are managed by Docker.
  174. for _, subnet := range v6Subnets {
  175. if subnet.Contains(ipAddr.IP) {
  176. continue ifaceLoop
  177. }
  178. }
  179. if interfaceAddr6 != nil {
  180. return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr6, ipAddr.IP)
  181. }
  182. interfaceAddr6 = ipAddr.IP
  183. }
  184. }
  185. // In the case that this interface has exactly one IPv4 address
  186. // and exactly one IPv6 address, favor IPv4 over IPv6.
  187. if interfaceAddr4 != nil {
  188. if systemAddr != nil {
  189. return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr4)
  190. }
  191. systemAddr = interfaceAddr4
  192. systemInterface = intf.Name
  193. } else if interfaceAddr6 != nil {
  194. if systemAddr != nil {
  195. return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr6)
  196. }
  197. systemAddr = interfaceAddr6
  198. systemInterface = intf.Name
  199. }
  200. }
  201. if systemAddr == nil {
  202. return nil, errNoIP
  203. }
  204. return systemAddr, nil
  205. }
  206. func listSystemIPs() []net.IP {
  207. interfaces, err := net.Interfaces()
  208. if err != nil {
  209. return nil
  210. }
  211. var systemAddrs []net.IP
  212. for _, intf := range interfaces {
  213. addrs, err := intf.Addrs()
  214. if err != nil {
  215. continue
  216. }
  217. for _, addr := range addrs {
  218. ipAddr, ok := addr.(*net.IPNet)
  219. if ok {
  220. systemAddrs = append(systemAddrs, ipAddr.IP)
  221. }
  222. }
  223. }
  224. return systemAddrs
  225. }
  226. func errMultipleIPs(interfaceA, interfaceB string, addrA, addrB net.IP) error {
  227. if interfaceA == interfaceB {
  228. return fmt.Errorf("could not choose an IP address to advertise since this system has multiple addresses on interface %s (%s and %s)", interfaceA, addrA, addrB)
  229. }
  230. return 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)", addrA, interfaceA, addrB, interfaceB)
  231. }