listen_addr.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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. errBadNetworkIdentifier = errors.New("must specify a valid IP address or interface name")
  12. errBadListenAddr = errors.New("listen address must be an IP address or network interface (with optional port number)")
  13. errBadAdvertiseAddr = errors.New("advertise address must be a non-zero IP address or network interface (with optional port number)")
  14. errBadDataPathAddr = errors.New("data path address must be a non-zero IP address or network interface (without a port number)")
  15. errBadDefaultAdvertiseAddr = errors.New("default advertise address must be a non-zero IP address or network interface (without a port number)")
  16. )
  17. func resolveListenAddr(specifiedAddr string) (string, string, error) {
  18. specifiedHost, specifiedPort, err := net.SplitHostPort(specifiedAddr)
  19. if err != nil {
  20. return "", "", fmt.Errorf("could not parse listen address %s", specifiedAddr)
  21. }
  22. // Does the host component match any of the interface names on the
  23. // system? If so, use the address from that interface.
  24. specifiedIP, err := resolveInputIPAddr(specifiedHost, true)
  25. if err != nil {
  26. if err == errBadNetworkIdentifier {
  27. err = errBadListenAddr
  28. }
  29. return "", "", err
  30. }
  31. return specifiedIP.String(), specifiedPort, nil
  32. }
  33. func (c *Cluster) resolveAdvertiseAddr(advertiseAddr, listenAddrPort string) (string, string, error) {
  34. // Approach:
  35. // - If an advertise address is specified, use that. Resolve the
  36. // interface's address if an interface was specified in
  37. // advertiseAddr. Fill in the port from listenAddrPort if necessary.
  38. // - If DefaultAdvertiseAddr is not empty, use that with the port from
  39. // listenAddrPort. Resolve the interface's address from
  40. // if an interface name was specified in DefaultAdvertiseAddr.
  41. // - Otherwise, try to autodetect the system's address. Use the port in
  42. // listenAddrPort with this address if autodetection succeeds.
  43. if advertiseAddr != "" {
  44. advertiseHost, advertisePort, err := net.SplitHostPort(advertiseAddr)
  45. if err != nil {
  46. // Not a host:port specification
  47. advertiseHost = advertiseAddr
  48. advertisePort = listenAddrPort
  49. }
  50. // Does the host component match any of the interface names on the
  51. // system? If so, use the address from that interface.
  52. advertiseIP, err := resolveInputIPAddr(advertiseHost, false)
  53. if err != nil {
  54. if err == errBadNetworkIdentifier {
  55. err = errBadAdvertiseAddr
  56. }
  57. return "", "", err
  58. }
  59. return advertiseIP.String(), advertisePort, nil
  60. }
  61. if c.config.DefaultAdvertiseAddr != "" {
  62. // Does the default advertise address component match any of the
  63. // interface names on the system? If so, use the address from
  64. // that interface.
  65. defaultAdvertiseIP, err := resolveInputIPAddr(c.config.DefaultAdvertiseAddr, false)
  66. if err != nil {
  67. if err == errBadNetworkIdentifier {
  68. err = errBadDefaultAdvertiseAddr
  69. }
  70. return "", "", err
  71. }
  72. return defaultAdvertiseIP.String(), listenAddrPort, nil
  73. }
  74. systemAddr, err := c.resolveSystemAddr()
  75. if err != nil {
  76. return "", "", err
  77. }
  78. return systemAddr.String(), listenAddrPort, nil
  79. }
  80. func resolveDataPathAddr(dataPathAddr string) (string, error) {
  81. if dataPathAddr == "" {
  82. // dataPathAddr is not defined
  83. return "", nil
  84. }
  85. // If a data path flag is specified try to resolve the IP address.
  86. dataPathIP, err := resolveInputIPAddr(dataPathAddr, false)
  87. if err != nil {
  88. if err == errBadNetworkIdentifier {
  89. err = errBadDataPathAddr
  90. }
  91. return "", err
  92. }
  93. return dataPathIP.String(), nil
  94. }
  95. func resolveInterfaceAddr(specifiedInterface string) (net.IP, error) {
  96. // Use a specific interface's IP address.
  97. intf, err := net.InterfaceByName(specifiedInterface)
  98. if err != nil {
  99. return nil, errNoSuchInterface
  100. }
  101. addrs, err := intf.Addrs()
  102. if err != nil {
  103. return nil, err
  104. }
  105. var interfaceAddr4, interfaceAddr6 net.IP
  106. for _, addr := range addrs {
  107. ipAddr, ok := addr.(*net.IPNet)
  108. if ok {
  109. if ipAddr.IP.To4() != nil {
  110. // IPv4
  111. if interfaceAddr4 != nil {
  112. return nil, fmt.Errorf("interface %s has more than one IPv4 address (%s and %s)", specifiedInterface, interfaceAddr4, ipAddr.IP)
  113. }
  114. interfaceAddr4 = ipAddr.IP
  115. } else {
  116. // IPv6
  117. if interfaceAddr6 != nil {
  118. return nil, fmt.Errorf("interface %s has more than one IPv6 address (%s and %s)", specifiedInterface, interfaceAddr6, ipAddr.IP)
  119. }
  120. interfaceAddr6 = ipAddr.IP
  121. }
  122. }
  123. }
  124. if interfaceAddr4 == nil && interfaceAddr6 == nil {
  125. return nil, fmt.Errorf("interface %s has no usable IPv4 or IPv6 address", specifiedInterface)
  126. }
  127. // In the case that there's exactly one IPv4 address
  128. // and exactly one IPv6 address, favor IPv4 over IPv6.
  129. if interfaceAddr4 != nil {
  130. return interfaceAddr4, nil
  131. }
  132. return interfaceAddr6, nil
  133. }
  134. // resolveInputIPAddr tries to resolve the IP address from the string passed as input
  135. // - tries to match the string as an interface name, if so returns the IP address associated with it
  136. // - on failure of previous step tries to parse the string as an IP address itself
  137. // if succeeds returns the IP address
  138. func resolveInputIPAddr(input string, isUnspecifiedValid bool) (net.IP, error) {
  139. // Try to see if it is an interface name
  140. interfaceAddr, err := resolveInterfaceAddr(input)
  141. if err == nil {
  142. return interfaceAddr, nil
  143. }
  144. // String matched interface but there is a potential ambiguity to be resolved
  145. if err != errNoSuchInterface {
  146. return nil, err
  147. }
  148. // String is not an interface check if it is a valid IP
  149. if ip := net.ParseIP(input); ip != nil && (isUnspecifiedValid || !ip.IsUnspecified()) {
  150. return ip, nil
  151. }
  152. // Not valid IP found
  153. return nil, errBadNetworkIdentifier
  154. }
  155. func (c *Cluster) resolveSystemAddrViaSubnetCheck() (net.IP, error) {
  156. // Use the system's only IP address, or fail if there are
  157. // multiple addresses to choose from. Skip interfaces which
  158. // are managed by docker via subnet check.
  159. interfaces, err := net.Interfaces()
  160. if err != nil {
  161. return nil, err
  162. }
  163. var systemAddr net.IP
  164. var systemInterface string
  165. // List Docker-managed subnets
  166. v4Subnets, v6Subnets := c.config.NetworkSubnetsProvider.Subnets()
  167. ifaceLoop:
  168. for _, intf := range interfaces {
  169. // Skip inactive interfaces and loopback interfaces
  170. if (intf.Flags&net.FlagUp == 0) || (intf.Flags&net.FlagLoopback) != 0 {
  171. continue
  172. }
  173. addrs, err := intf.Addrs()
  174. if err != nil {
  175. continue
  176. }
  177. var interfaceAddr4, interfaceAddr6 net.IP
  178. for _, addr := range addrs {
  179. ipAddr, ok := addr.(*net.IPNet)
  180. // Skip loopback and link-local addresses
  181. if !ok || !ipAddr.IP.IsGlobalUnicast() {
  182. continue
  183. }
  184. if ipAddr.IP.To4() != nil {
  185. // IPv4
  186. // Ignore addresses in subnets that are managed by Docker.
  187. for _, subnet := range v4Subnets {
  188. if subnet.Contains(ipAddr.IP) {
  189. continue ifaceLoop
  190. }
  191. }
  192. if interfaceAddr4 != nil {
  193. return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr4, ipAddr.IP)
  194. }
  195. interfaceAddr4 = ipAddr.IP
  196. } else {
  197. // IPv6
  198. // Ignore addresses in subnets that are managed by Docker.
  199. for _, subnet := range v6Subnets {
  200. if subnet.Contains(ipAddr.IP) {
  201. continue ifaceLoop
  202. }
  203. }
  204. if interfaceAddr6 != nil {
  205. return nil, errMultipleIPs(intf.Name, intf.Name, interfaceAddr6, ipAddr.IP)
  206. }
  207. interfaceAddr6 = ipAddr.IP
  208. }
  209. }
  210. // In the case that this interface has exactly one IPv4 address
  211. // and exactly one IPv6 address, favor IPv4 over IPv6.
  212. if interfaceAddr4 != nil {
  213. if systemAddr != nil {
  214. return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr4)
  215. }
  216. systemAddr = interfaceAddr4
  217. systemInterface = intf.Name
  218. } else if interfaceAddr6 != nil {
  219. if systemAddr != nil {
  220. return nil, errMultipleIPs(systemInterface, intf.Name, systemAddr, interfaceAddr6)
  221. }
  222. systemAddr = interfaceAddr6
  223. systemInterface = intf.Name
  224. }
  225. }
  226. if systemAddr == nil {
  227. return nil, errNoIP
  228. }
  229. return systemAddr, nil
  230. }
  231. func listSystemIPs() []net.IP {
  232. interfaces, err := net.Interfaces()
  233. if err != nil {
  234. return nil
  235. }
  236. var systemAddrs []net.IP
  237. for _, intf := range interfaces {
  238. addrs, err := intf.Addrs()
  239. if err != nil {
  240. continue
  241. }
  242. for _, addr := range addrs {
  243. ipAddr, ok := addr.(*net.IPNet)
  244. if ok {
  245. systemAddrs = append(systemAddrs, ipAddr.IP)
  246. }
  247. }
  248. }
  249. return systemAddrs
  250. }
  251. func errMultipleIPs(interfaceA, interfaceB string, addrA, addrB net.IP) error {
  252. if interfaceA == interfaceB {
  253. 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)
  254. }
  255. 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)
  256. }