func (l *Link) Disable() { // We do not care about errors here because the link may not // exist in iptables // -D == iptables delete flag l.toggle("-D", true) // call this on Firewalld reload iptables.OnReloaded(func() { l.toggle("-D", true) }) l.IsEnabled = false }
func (l *Link) Enable() error { // -A == iptables append flag if err := l.toggle("-A", false); err != nil { return err } // call this on Firewalld reload iptables.OnReloaded(func() { l.toggle("-I", false) }) l.IsEnabled = true return nil }
func InitDriver(config *Config) error { var ( networkv4 *net.IPNet networkv6 *net.IPNet addrv4 net.Addr addrsv6 []net.Addr bridgeIPv6 = "fe80::1/64" ) // try to modprobe bridge first // see gh#12177 if out, err := exec.Command("modprobe", "-va", "bridge", "nf_nat", "br_netfilter").Output(); err != nil { logrus.Warnf("Running modprobe bridge nf_nat failed with message: %s, error: %v", out, err) } initPortMapper() if config.DefaultIp != nil { defaultBindingIP = config.DefaultIp } hairpinMode = !config.EnableUserlandProxy bridgeIface = config.Iface usingDefaultBridge := false if bridgeIface == "" { usingDefaultBridge = true bridgeIface = DefaultNetworkBridge } addrv4, addrsv6, err := networkdriver.GetIfaceAddr(bridgeIface) if err != nil { // No Bridge existent, create one // If we're not using the default bridge, fail without trying to create it if !usingDefaultBridge { return err } logrus.Info("Bridge interface not found, trying to create it") // If the iface is not found, try to create it if err := configureBridge(config.IP, bridgeIPv6, config.EnableIPv6); err != nil { logrus.Errorf("Could not configure Bridge: %s", err) return err } addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface) if err != nil { return err } if config.FixedCIDRv6 != "" { // Setting route to global IPv6 subnet logrus.Infof("Adding route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface) if err := netlink.AddRoute(config.FixedCIDRv6, "", "", bridgeIface); err != nil { logrus.Fatalf("Could not add route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface) } } } else { // Bridge exists already, getting info... // Validate that the bridge ip matches the ip specified by BridgeIP if config.IP != "" { networkv4 = addrv4.(*net.IPNet) bip, _, err := net.ParseCIDR(config.IP) if err != nil { return err } if !networkv4.IP.Equal(bip) { return fmt.Errorf("Bridge ip (%s) does not match existing bridge configuration %s", networkv4.IP, bip) } } // A bridge might exist but not have any IPv6 addr associated with it yet // (for example, an existing Docker installation that has only been used // with IPv4 and docker0 already is set up) In that case, we can perform // the bridge init for IPv6 here, else we will error out below if --ipv6=true if len(addrsv6) == 0 && config.EnableIPv6 { if err := setupIPv6Bridge(bridgeIPv6); err != nil { return err } // Recheck addresses now that IPv6 is setup on the bridge addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface) if err != nil { return err } } // TODO: Check if route to config.FixedCIDRv6 is set } if config.EnableIPv6 { bip6, _, err := net.ParseCIDR(bridgeIPv6) if err != nil { return err } found := false for _, addrv6 := range addrsv6 { networkv6 = addrv6.(*net.IPNet) if networkv6.IP.Equal(bip6) { found = true break } } if !found { return fmt.Errorf("Bridge IPv6 does not match existing bridge configuration %s", bip6) } } networkv4 = addrv4.(*net.IPNet) if config.EnableIPv6 { if len(addrsv6) == 0 { return errors.New("IPv6 enabled but no IPv6 detected") } bridgeIPv6Addr = networkv6.IP } if config.EnableIptables { if err := iptables.FirewalldInit(); err != nil { logrus.Debugf("Error initializing firewalld: %v", err) } } // Configure iptables for link support if config.EnableIptables { if err := setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq); err != nil { logrus.Errorf("Error configuring iptables: %s", err) return err } // call this on Firewalld reload iptables.OnReloaded(func() { setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq) }) } if config.EnableIpForward { // Enable IPv4 forwarding if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil { logrus.Warnf("Unable to enable IPv4 forwarding: %v", err) } if config.FixedCIDRv6 != "" { // Enable IPv6 forwarding if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil { logrus.Warnf("Unable to enable IPv6 default forwarding: %v", err) } if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/all/forwarding", []byte{'1', '\n'}, 0644); err != nil { logrus.Warnf("Unable to enable IPv6 all forwarding: %v", err) } } } if hairpinMode { // Enable loopback adresses routing sysPath := filepath.Join("/proc/sys/net/ipv4/conf", bridgeIface, "route_localnet") if err := ioutil.WriteFile(sysPath, []byte{'1', '\n'}, 0644); err != nil { logrus.Warnf("Unable to enable local routing for hairpin mode: %v", err) } } // We can always try removing the iptables if err := iptables.RemoveExistingChain("DOCKER", iptables.Nat); err != nil { return err } if config.EnableIptables { _, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat, hairpinMode) if err != nil { return err } // call this on Firewalld reload iptables.OnReloaded(func() { iptables.NewChain("DOCKER", bridgeIface, iptables.Nat, hairpinMode) }) chain, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter, hairpinMode) if err != nil { return err } // call this on Firewalld reload iptables.OnReloaded(func() { iptables.NewChain("DOCKER", bridgeIface, iptables.Filter, hairpinMode) }) portMapper.SetIptablesChain(chain) } bridgeIPv4Network = networkv4 if config.FixedCIDR != "" { _, subnet, err := net.ParseCIDR(config.FixedCIDR) if err != nil { return err } logrus.Debugf("Subnet: %v", subnet) if err := ipAllocator.RegisterSubnet(bridgeIPv4Network, subnet); err != nil { logrus.Errorf("Error registering subnet for IPv4 bridge network: %s", err) return err } } if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv4, bridgeIPv4Network); err != nil { return err } else { gatewayIPv4 = gateway } if config.FixedCIDRv6 != "" { _, subnet, err := net.ParseCIDR(config.FixedCIDRv6) if err != nil { return err } logrus.Debugf("Subnet: %v", subnet) if err := ipAllocator.RegisterSubnet(subnet, subnet); err != nil { logrus.Errorf("Error registering subnet for IPv6 bridge network: %s", err) return err } globalIPv6Network = subnet if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv6, globalIPv6Network); err != nil { return err } else { gatewayIPv6 = gateway } } // Block BridgeIP in IP allocator ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP) if config.EnableIptables { iptables.OnReloaded(portMapper.ReMapAll) // call this on Firewalld reload } return nil }