Пример #1
0
func parseAddrs(addrs string) ([]string, []string) {
	adrs := strings.Split(addrs, ",")
	parsedIPv4 := []string{}
	parsedIPv6 := []string{}

	if addrs != "" {
		for _, adr := range adrs {
			ip := net.ParseIP(adr)
			if ip != nil {
				if ip.To4() != nil {
					parsedIPv4 = append(parsedIPv4, adr)
				} else {
					parsedIPv6 = append(parsedIPv6, adr)
				}
			} else { //Not a valid single IP, could it be a CIDR?
				parsedIP, net, err := net.ParseCIDR(adr)
				if err == nil {
					if parsedIP.To4() != nil {
						parsedIPv4 = append(parsedIPv4, net.String())
					} else {
						parsedIPv6 = append(parsedIPv6, net.String())
					}
				} else {
					log.Fatalf("Incorrectly specified target IP or CIDR:", adr)
				}
			}
		}
	}

	return parsedIPv4, parsedIPv6
}
Пример #2
0
// checkPortGroups checks that network config is valid
// prevent assigning > 1 static IP to the same port group
// warn if assigning addresses in the same subnet to > 1 port group
func (v *Validator) checkPortGroups(counts map[string]int, ips map[string][]data.NetworkConfig) error {
	defer trace.End(trace.Begin(""))

	networks := make(map[string]string)

	for pg, config := range ips {
		if len(ips[pg]) > 1 {
			var msgIPs []string
			for _, v := range ips[pg] {
				msgIPs = append(msgIPs, v.IP.IP.String())
			}
			log.Errorf("Port group %q is configured for networks with more than one static IP: %s", pg, msgIPs)
			log.Error("All VCH networks on the same port group must have the same IP address")
			log.Error("To resolve this, configure static IP for one network and assign other networks to same port group.")
			log.Error("The static IP will be automatically configured for networks sharing the port group.")
			return fmt.Errorf("Incorrect static IP configuration for networks on port group %q", pg)
		}

		// check if same subnet assigned to multiple portgroups - this can cause routing problems
		_, net, _ := net.ParseCIDR(config[0].IP.String())
		netAddr := net.String()
		if networks[netAddr] != "" {
			log.Warnf("Unsupported static IP configuration: Same subnet %q is assigned to multiple port groups %q and %q", netAddr, networks[netAddr], pg)
		} else {
			networks[netAddr] = pg
		}
	}

	return nil
}
Пример #3
0
// Set implements the flag.Value Set method for SrcRestrictions.
func (s *SrcRestrictions) Set(val string) error {
	_, net, err := net.ParseCIDR(val)
	if err != nil {
		return errors.Errorf("invalid source restriction format %q: %s", val, err)
	}
	*s = append(*s, SourceCIDR{net.String()})
	return nil
}
Пример #4
0
// Set implements the flag.Value Set method for CIDRs.
func (c *CIDRs) Set(val string) error {
	_, net, err := net.ParseCIDR(val)
	if err != nil {
		return errors.Errorf("invalid CIDR format %q: %s", val, err)
	}
	*c = append(*c, net.String())
	return nil
}
Пример #5
0
func notifyWebhook(sn *backend.SubnetDef) error {
	if opts.notifyURL == "" {
		return nil
	}
	net := sn.Net
	net.IP += 1
	data := struct {
		Subnet string `json:"subnet"`
		MTU    int    `json:"mtu"`
	}{net.String(), sn.MTU}
	payload, _ := json.Marshal(data)
	res, err := http.Post(opts.notifyURL, "application/json", bytes.NewReader(payload))
	if err != nil {
		return err
	}
	res.Body.Close()
	return nil
}
Пример #6
0
func TestPrepareNetworksMulti(t *testing.T) {
	inp := "127.0.0.1 192.1.0.100/24\n10.0.0.0/8"
	out := []*net.IPNet{
		createNet("127.0.0.1", 32),
		createNet("192.1.0.0", 24),
		createNet("10.0.0.0", 8),
	}

	nets := prepareNetworks(inp)

	if len(nets) != len(out) {
		t.Errorf("prepareNetworks(%v) = %v; expected %v", inp, nets, out)
	}

	for idx, net := range nets {
		if net.String() != out[idx].String() {
			t.Errorf("prepareNetworks(%v) = %v; on pos %v expected %v != %v", inp, nets, idx, net, out[idx])
		}
	}
}
Пример #7
0
func TestPrepareNetworksSingle(t *testing.T) {
	test := map[string]*net.IPNet{
		"127.0.0.1":      createNet("127.0.0.1", 32),
		"192.168.1.1":    createNet("192.168.1.1", 32),
		"192.1.0.100/24": createNet("192.1.0.0", 24),
		"10.0.0.0/8":     createNet("10.0.0.0", 8),
	}

	for addr, net := range test {
		nets := prepareNetworks(addr)
		if nets == nil || len(nets) == 0 {
			t.Errorf("prepareNetworks(%v) = %v; expected %v", addr, nets, net)
		} else {
			net1 := nets[0]
			if net1.String() != net.String() {
				t.Errorf("prepareNetworks(%v) = %v; expected %v", addr, nets, net)
			}
		}
	}
}
Пример #8
0
func parseAddrs(addrs string) []string {
	adrs := strings.Split(addrs, ",")
	parsed := []string{}

	if addrs != "" {
		for _, adr := range adrs {
			ip := net.ParseIP(adr)
			if ip != nil {
				parsed = append(parsed, adr)
			} else { //Not a valid single IP, could it be a CIDR?
				_, net, err := net.ParseCIDR(adr)
				if err == nil {
					parsed = append(parsed, net.String())
				} else {
					log.Fatalln("Incorrectly specified target IP or CIDR:", adr)
				}
			}
		}
	}

	return parsed
}
Пример #9
0
// ConfigureNetworking is called once during host startup and passed the
// strategy and identifier of the networking coordinatior job. Currently the
// only strategy implemented uses flannel.
func (l *LibvirtLXCBackend) ConfigureNetworking(config *host.NetworkConfig) error {
	var err error
	l.bridgeAddr, l.bridgeNet, err = net.ParseCIDR(config.Subnet)
	if err != nil {
		return err
	}
	l.ipalloc.RequestIP(l.bridgeNet, l.bridgeAddr)

	err = netlink.CreateBridge(bridgeName, false)
	bridgeExists := os.IsExist(err)
	if err != nil && !bridgeExists {
		return err
	}

	bridge, err := net.InterfaceByName(bridgeName)
	if err != nil {
		return err
	}
	if !bridgeExists {
		// We need to explicitly assign the MAC address to avoid it changing to a lower value
		// See: https://github.com/flynn/flynn/issues/223
		b := random.Bytes(5)
		bridgeMAC := fmt.Sprintf("fe:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4])
		if err := netlink.NetworkSetMacAddress(bridge, bridgeMAC); err != nil {
			return err
		}
	}
	currAddrs, err := bridge.Addrs()
	if err != nil {
		return err
	}
	setIP := true
	for _, addr := range currAddrs {
		ip, net, _ := net.ParseCIDR(addr.String())
		if ip.Equal(l.bridgeAddr) && net.String() == l.bridgeNet.String() {
			setIP = false
		} else {
			if err := netlink.NetworkLinkDelIp(bridge, ip, net); err != nil {
				return err
			}
		}
	}
	if setIP {
		if err := netlink.NetworkLinkAddIp(bridge, l.bridgeAddr, l.bridgeNet); err != nil {
			return err
		}
	}
	if err := netlink.NetworkLinkUp(bridge); err != nil {
		return err
	}

	network, err := l.libvirt.LookupNetworkByName(libvirtNetName)
	if err != nil {
		// network doesn't exist
		networkConfig := &lt.Network{
			Name:    libvirtNetName,
			Bridge:  lt.Bridge{Name: bridgeName},
			Forward: lt.Forward{Mode: "bridge"},
		}
		network, err = l.libvirt.NetworkDefineXML(string(networkConfig.XML()))
		if err != nil {
			return err
		}
	}
	active, err := network.IsActive()
	if err != nil {
		return err
	}
	if !active {
		if err := network.Create(); err != nil {
			return err
		}
	}
	if defaultNet, err := l.libvirt.LookupNetworkByName("default"); err == nil {
		// The default network causes dnsmasq to run and bind to all interfaces,
		// including ours. This prevents discoverd from binding its DNS server.
		// We don't use it, so destroy it if it exists.
		defaultNet.Destroy()
	}

	// enable IP forwarding
	if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte("1\n"), 0644); err != nil {
		return err
	}

	// Set up iptables for outbound traffic masquerading from containers to the
	// rest of the network.
	if err := iptables.EnableOutboundNAT(bridgeName, l.bridgeNet.String()); err != nil {
		return err
	}

	// Read DNS config, discoverd uses the nameservers
	dnsConf, err := dns.ClientConfigFromFile("/etc/resolv.conf")
	if err != nil {
		return err
	}
	config.Resolvers = dnsConf.Servers

	// Write a resolv.conf to be bind-mounted into containers pointing at the
	// future discoverd DNS listener
	if err := os.MkdirAll("/etc/flynn", 0755); err != nil {
		return err
	}
	var resolvSearch string
	if len(dnsConf.Search) > 0 {
		resolvSearch = fmt.Sprintf("search %s\n", strings.Join(dnsConf.Search, " "))
	}
	if err := ioutil.WriteFile("/etc/flynn/resolv.conf", []byte(fmt.Sprintf("%snameserver %s\n", resolvSearch, l.bridgeAddr.String())), 0644); err != nil {
		return err
	}
	l.resolvConf = "/etc/flynn/resolv.conf"

	// Allocate IPs for running jobs
	for i, container := range l.containers {
		if !container.job.Config.HostNetwork {
			var err error
			l.containers[i].IP, err = l.ipalloc.RequestIP(l.bridgeNet, container.IP)
			if err != nil {
				grohl.Log(grohl.Data{"fn": "ConfigureNetworking", "at": "request_ip", "status": "error", "err": err})
			}
		}
	}

	close(l.networkConfigured)

	return nil
}
Пример #10
0
// ConfigureNetworking is called once during host startup and sets up the local
// bridge and forwarding rules for containers.
func (l *LibcontainerBackend) ConfigureNetworking(config *host.NetworkConfig) error {
	log := l.logger.New("fn", "ConfigureNetworking")
	var err error
	l.bridgeAddr, l.bridgeNet, err = net.ParseCIDR(config.Subnet)
	if err != nil {
		return err
	}
	l.ipalloc.RequestIP(l.bridgeNet, l.bridgeAddr)

	err = netlink.CreateBridge(l.bridgeName, false)
	bridgeExists := os.IsExist(err)
	if err != nil && !bridgeExists {
		return err
	}

	bridge, err := net.InterfaceByName(l.bridgeName)
	if err != nil {
		return err
	}
	if !bridgeExists {
		// We need to explicitly assign the MAC address to avoid it changing to a lower value
		// See: https://github.com/flynn/flynn/issues/223
		b := random.Bytes(5)
		bridgeMAC := fmt.Sprintf("fe:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4])
		if err := netlink.NetworkSetMacAddress(bridge, bridgeMAC); err != nil {
			return err
		}
	}
	currAddrs, err := bridge.Addrs()
	if err != nil {
		return err
	}
	setIP := true
	for _, addr := range currAddrs {
		ip, net, _ := net.ParseCIDR(addr.String())
		if ip.Equal(l.bridgeAddr) && net.String() == l.bridgeNet.String() {
			setIP = false
		} else {
			if err := netlink.NetworkLinkDelIp(bridge, ip, net); err != nil {
				return err
			}
		}
	}
	if setIP {
		if err := netlink.NetworkLinkAddIp(bridge, l.bridgeAddr, l.bridgeNet); err != nil {
			return err
		}
	}
	if err := netlink.NetworkLinkUp(bridge); err != nil {
		return err
	}

	// enable IP forwarding
	if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte("1\n"), 0644); err != nil {
		return err
	}

	// Set up iptables for outbound traffic masquerading from containers to the
	// rest of the network.
	if err := iptables.EnableOutboundNAT(l.bridgeName, l.bridgeNet.String()); err != nil {
		return err
	}

	// Read DNS config, discoverd uses the nameservers
	dnsConf, err := dns.ClientConfigFromFile("/etc/resolv.conf")
	if err != nil {
		return err
	}
	config.Resolvers = dnsConf.Servers

	// Write a resolv.conf to be bind-mounted into containers pointing at the
	// future discoverd DNS listener
	if err := os.MkdirAll("/etc/flynn", 0755); err != nil {
		return err
	}
	var resolvSearch string
	if len(dnsConf.Search) > 0 {
		resolvSearch = fmt.Sprintf("search %s\n", strings.Join(dnsConf.Search, " "))
	}
	if err := ioutil.WriteFile("/etc/flynn/resolv.conf", []byte(fmt.Sprintf("%snameserver %s\n", resolvSearch, l.bridgeAddr.String())), 0644); err != nil {
		return err
	}
	l.resolvConf = "/etc/flynn/resolv.conf"

	// Allocate IPs for running jobs
	l.containersMtx.Lock()
	defer l.containersMtx.Unlock()
	for _, container := range l.containers {
		if !container.job.Config.HostNetwork {
			if _, err := l.ipalloc.RequestIP(l.bridgeNet, container.IP); err != nil {
				log.Error("error requesting ip", "job.id", container.job.ID, "err", err)
			}
		}
	}

	close(l.networkConfigured)

	return nil
}