network.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. package docker
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "net"
  8. "os/exec"
  9. "strconv"
  10. "strings"
  11. )
  12. var NetworkBridgeIface string
  13. const (
  14. portRangeStart = 49153
  15. portRangeEnd = 65535
  16. )
  17. // Calculates the first and last IP addresses in an IPNet
  18. func networkRange(network *net.IPNet) (net.IP, net.IP) {
  19. netIP := network.IP.To4()
  20. firstIP := netIP.Mask(network.Mask)
  21. lastIP := net.IPv4(0, 0, 0, 0).To4()
  22. for i := 0; i < len(lastIP); i++ {
  23. lastIP[i] = netIP[i] | ^network.Mask[i]
  24. }
  25. return firstIP, lastIP
  26. }
  27. // Converts a 4 bytes IP into a 32 bit integer
  28. func ipToInt(ip net.IP) int32 {
  29. return int32(binary.BigEndian.Uint32(ip.To4()))
  30. }
  31. // Converts 32 bit integer into a 4 bytes IP address
  32. func intToIp(n int32) net.IP {
  33. b := make([]byte, 4)
  34. binary.BigEndian.PutUint32(b, uint32(n))
  35. return net.IP(b)
  36. }
  37. // Given a netmask, calculates the number of available hosts
  38. func networkSize(mask net.IPMask) int32 {
  39. m := net.IPv4Mask(0, 0, 0, 0)
  40. for i := 0; i < net.IPv4len; i++ {
  41. m[i] = ^mask[i]
  42. }
  43. return int32(binary.BigEndian.Uint32(m)) + 1
  44. }
  45. // Wrapper around the iptables command
  46. func iptables(args ...string) error {
  47. path, err := exec.LookPath("iptables")
  48. if err != nil {
  49. return fmt.Errorf("command not found: iptables")
  50. }
  51. if err := exec.Command(path, args...).Run(); err != nil {
  52. return fmt.Errorf("iptables failed: iptables %v", strings.Join(args, " "))
  53. }
  54. return nil
  55. }
  56. // Return the IPv4 address of a network interface
  57. func getIfaceAddr(name string) (net.Addr, error) {
  58. iface, err := net.InterfaceByName(name)
  59. if err != nil {
  60. return nil, err
  61. }
  62. addrs, err := iface.Addrs()
  63. if err != nil {
  64. return nil, err
  65. }
  66. var addrs4 []net.Addr
  67. for _, addr := range addrs {
  68. ip := (addr.(*net.IPNet)).IP
  69. if ip4 := ip.To4(); len(ip4) == net.IPv4len {
  70. addrs4 = append(addrs4, addr)
  71. }
  72. }
  73. switch {
  74. case len(addrs4) == 0:
  75. return nil, fmt.Errorf("Interface %v has no IP addresses", name)
  76. case len(addrs4) > 1:
  77. fmt.Printf("Interface %v has more than 1 IPv4 address. Defaulting to using %v\n",
  78. name, (addrs4[0].(*net.IPNet)).IP)
  79. }
  80. return addrs4[0], nil
  81. }
  82. // Port mapper takes care of mapping external ports to containers by setting
  83. // up iptables rules.
  84. // It keeps track of all mappings and is able to unmap at will
  85. type PortMapper struct {
  86. mapping map[int]net.TCPAddr
  87. }
  88. func (mapper *PortMapper) cleanup() error {
  89. // Ignore errors - This could mean the chains were never set up
  90. iptables("-t", "nat", "-D", "PREROUTING", "-m", "addrtype", "--dst-type", "LOCAL", "-j", "DOCKER")
  91. iptables("-t", "nat", "-D", "OUTPUT", "-m", "addrtype", "--dst-type", "LOCAL", "-j", "DOCKER")
  92. // Also cleanup rules created by older versions, or -X might fail.
  93. iptables("-t", "nat", "-D", "PREROUTING", "-j", "DOCKER")
  94. iptables("-t", "nat", "-D", "OUTPUT", "-j", "DOCKER")
  95. iptables("-t", "nat", "-F", "DOCKER")
  96. iptables("-t", "nat", "-X", "DOCKER")
  97. mapper.mapping = make(map[int]net.TCPAddr)
  98. return nil
  99. }
  100. func (mapper *PortMapper) setup() error {
  101. if err := iptables("-t", "nat", "-N", "DOCKER"); err != nil {
  102. return fmt.Errorf("Failed to create DOCKER chain: %s", err)
  103. }
  104. if err := iptables("-t", "nat", "-A", "PREROUTING", "-m", "addrtype", "--dst-type", "LOCAL", "-j", "DOCKER"); err != nil {
  105. return fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
  106. }
  107. if err := iptables("-t", "nat", "-A", "OUTPUT", "-m", "addrtype", "--dst-type", "LOCAL", "-j", "DOCKER"); err != nil {
  108. return fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
  109. }
  110. return nil
  111. }
  112. func (mapper *PortMapper) iptablesForward(rule string, port int, dest net.TCPAddr) error {
  113. return iptables("-t", "nat", rule, "DOCKER", "-p", "tcp", "--dport", strconv.Itoa(port),
  114. "-j", "DNAT", "--to-destination", net.JoinHostPort(dest.IP.String(), strconv.Itoa(dest.Port)))
  115. }
  116. func (mapper *PortMapper) Map(port int, dest net.TCPAddr) error {
  117. if err := mapper.iptablesForward("-A", port, dest); err != nil {
  118. return err
  119. }
  120. mapper.mapping[port] = dest
  121. return nil
  122. }
  123. func (mapper *PortMapper) Unmap(port int) error {
  124. dest, ok := mapper.mapping[port]
  125. if !ok {
  126. return errors.New("Port is not mapped")
  127. }
  128. if err := mapper.iptablesForward("-D", port, dest); err != nil {
  129. return err
  130. }
  131. delete(mapper.mapping, port)
  132. return nil
  133. }
  134. func newPortMapper() (*PortMapper, error) {
  135. mapper := &PortMapper{}
  136. if err := mapper.cleanup(); err != nil {
  137. return nil, err
  138. }
  139. if err := mapper.setup(); err != nil {
  140. return nil, err
  141. }
  142. return mapper, nil
  143. }
  144. // Port allocator: Atomatically allocate and release networking ports
  145. type PortAllocator struct {
  146. ports chan (int)
  147. }
  148. func (alloc *PortAllocator) populate(start, end int) {
  149. alloc.ports = make(chan int, end-start)
  150. for port := start; port < end; port++ {
  151. alloc.ports <- port
  152. }
  153. }
  154. func (alloc *PortAllocator) Acquire() (int, error) {
  155. select {
  156. case port := <-alloc.ports:
  157. return port, nil
  158. default:
  159. return -1, errors.New("No more ports available")
  160. }
  161. return -1, nil
  162. }
  163. func (alloc *PortAllocator) Release(port int) error {
  164. select {
  165. case alloc.ports <- port:
  166. return nil
  167. default:
  168. return errors.New("Too many ports have been released")
  169. }
  170. panic("unreachable")
  171. }
  172. func newPortAllocator(start, end int) (*PortAllocator, error) {
  173. allocator := &PortAllocator{}
  174. allocator.populate(start, end)
  175. return allocator, nil
  176. }
  177. // IP allocator: Atomatically allocate and release networking ports
  178. type IPAllocator struct {
  179. network *net.IPNet
  180. queueAlloc chan allocatedIP
  181. queueReleased chan net.IP
  182. inUse map[int32]struct{}
  183. }
  184. type allocatedIP struct {
  185. ip net.IP
  186. err error
  187. }
  188. func (alloc *IPAllocator) run() {
  189. firstIP, _ := networkRange(alloc.network)
  190. ipNum := ipToInt(firstIP)
  191. ownIP := ipToInt(alloc.network.IP)
  192. size := networkSize(alloc.network.Mask)
  193. pos := int32(1)
  194. max := size - 2 // -1 for the broadcast address, -1 for the gateway address
  195. for {
  196. var (
  197. newNum int32
  198. inUse bool
  199. )
  200. // Find first unused IP, give up after one whole round
  201. for attempt := int32(0); attempt < max; attempt++ {
  202. newNum = ipNum + pos
  203. pos = pos%max + 1
  204. // The network's IP is never okay to use
  205. if newNum == ownIP {
  206. continue
  207. }
  208. if _, inUse = alloc.inUse[newNum]; !inUse {
  209. // We found an unused IP
  210. break
  211. }
  212. }
  213. ip := allocatedIP{ip: intToIp(newNum)}
  214. if inUse {
  215. ip.err = errors.New("No unallocated IP available")
  216. }
  217. select {
  218. case alloc.queueAlloc <- ip:
  219. alloc.inUse[newNum] = struct{}{}
  220. case released := <-alloc.queueReleased:
  221. r := ipToInt(released)
  222. delete(alloc.inUse, r)
  223. if inUse {
  224. // If we couldn't allocate a new IP, the released one
  225. // will be the only free one now, so instantly use it
  226. // next time
  227. pos = r - ipNum
  228. } else {
  229. // Use same IP as last time
  230. if pos == 1 {
  231. pos = max
  232. } else {
  233. pos--
  234. }
  235. }
  236. }
  237. }
  238. }
  239. func (alloc *IPAllocator) Acquire() (net.IP, error) {
  240. ip := <-alloc.queueAlloc
  241. return ip.ip, ip.err
  242. }
  243. func (alloc *IPAllocator) Release(ip net.IP) {
  244. alloc.queueReleased <- ip
  245. }
  246. func newIPAllocator(network *net.IPNet) *IPAllocator {
  247. alloc := &IPAllocator{
  248. network: network,
  249. queueAlloc: make(chan allocatedIP),
  250. queueReleased: make(chan net.IP),
  251. inUse: make(map[int32]struct{}),
  252. }
  253. go alloc.run()
  254. return alloc
  255. }
  256. // Network interface represents the networking stack of a container
  257. type NetworkInterface struct {
  258. IPNet net.IPNet
  259. Gateway net.IP
  260. manager *NetworkManager
  261. extPorts []int
  262. }
  263. // Allocate an external TCP port and map it to the interface
  264. func (iface *NetworkInterface) AllocatePort(port int) (int, error) {
  265. extPort, err := iface.manager.portAllocator.Acquire()
  266. if err != nil {
  267. return -1, err
  268. }
  269. if err := iface.manager.portMapper.Map(extPort, net.TCPAddr{IP: iface.IPNet.IP, Port: port}); err != nil {
  270. iface.manager.portAllocator.Release(extPort)
  271. return -1, err
  272. }
  273. iface.extPorts = append(iface.extPorts, extPort)
  274. return extPort, nil
  275. }
  276. // Release: Network cleanup - release all resources
  277. func (iface *NetworkInterface) Release() {
  278. for _, port := range iface.extPorts {
  279. if err := iface.manager.portMapper.Unmap(port); err != nil {
  280. log.Printf("Unable to unmap port %v: %v", port, err)
  281. }
  282. if err := iface.manager.portAllocator.Release(port); err != nil {
  283. log.Printf("Unable to release port %v: %v", port, err)
  284. }
  285. }
  286. iface.manager.ipAllocator.Release(iface.IPNet.IP)
  287. }
  288. // Network Manager manages a set of network interfaces
  289. // Only *one* manager per host machine should be used
  290. type NetworkManager struct {
  291. bridgeIface string
  292. bridgeNetwork *net.IPNet
  293. ipAllocator *IPAllocator
  294. portAllocator *PortAllocator
  295. portMapper *PortMapper
  296. }
  297. // Allocate a network interface
  298. func (manager *NetworkManager) Allocate() (*NetworkInterface, error) {
  299. ip, err := manager.ipAllocator.Acquire()
  300. if err != nil {
  301. return nil, err
  302. }
  303. iface := &NetworkInterface{
  304. IPNet: net.IPNet{IP: ip, Mask: manager.bridgeNetwork.Mask},
  305. Gateway: manager.bridgeNetwork.IP,
  306. manager: manager,
  307. }
  308. return iface, nil
  309. }
  310. func newNetworkManager(bridgeIface string) (*NetworkManager, error) {
  311. addr, err := getIfaceAddr(bridgeIface)
  312. if err != nil {
  313. return nil, fmt.Errorf("Couldn't find bridge interface %s (%s).\nPlease create it with 'ip link add lxcbr0 type bridge; ip addr add ADDRESS/MASK dev lxcbr0'", bridgeIface, err)
  314. }
  315. network := addr.(*net.IPNet)
  316. ipAllocator := newIPAllocator(network)
  317. portAllocator, err := newPortAllocator(portRangeStart, portRangeEnd)
  318. if err != nil {
  319. return nil, err
  320. }
  321. portMapper, err := newPortMapper()
  322. if err != nil {
  323. return nil, err
  324. }
  325. manager := &NetworkManager{
  326. bridgeIface: bridgeIface,
  327. bridgeNetwork: network,
  328. ipAllocator: ipAllocator,
  329. portAllocator: portAllocator,
  330. portMapper: portMapper,
  331. }
  332. return manager, nil
  333. }