func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error { conf, err := loadNetConf(args.StdinData) if err != nil { return err } ns, err := netns.GetFromPath(args.Netns) if err != nil { return err } defer ns.Close() err = weavenet.WithNetNSUnsafe(ns, func() error { link, err := netlink.LinkByName(args.IfName) if err != nil { return err } return netlink.LinkDel(link) }) if err != nil { return fmt.Errorf("error removing interface: %s", err) } // Default IPAM is Weave's own if conf.IPAM.Type == "" { err = ipamplugin.NewIpam(c.weave).Release(args) } else { err = ipam.ExecDel(conf.IPAM.Type, args.StdinData) } if err != nil { return fmt.Errorf("unable to release IP address: %s", err) } return nil }
// NewSandbox provides a new sandbox instance created in an os specific way // provided a key which uniquely identifies the sandbox func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) { if !isRestore { err := createNetworkNamespace(key, osCreate) if err != nil { return nil, err } } else { once.Do(createBasePath) } n := &networkNamespace{path: key, isDefault: !osCreate} sboxNs, err := netns.GetFromPath(n.path) if err != nil { return nil, fmt.Errorf("failed get network namespace %q: %v", n.path, err) } defer sboxNs.Close() n.nlHandle, err = netlink.NewHandleAt(sboxNs) if err != nil { return nil, fmt.Errorf("failed to create a netlink handle: %v", err) } if err = n.loopbackUp(); err != nil { n.nlHandle.Delete() return nil, err } return n, nil }
// Search the network namespace of a process for interfaces matching a predicate func FindNetDevs(procPath string, processID int, match func(string) bool) ([]NetDev, error) { var netDevs []NetDev ns, err := netns.GetFromPath(fmt.Sprintf("%s/%d/ns/net", procPath, processID)) if err != nil { return nil, err } defer ns.Close() err = WithNetNS(ns, func() error { links, err := netlink.LinkList() if err != nil { return err } for _, link := range links { if match(link.Attrs().Name) { addrs, err := netlink.AddrList(link, netlink.FAMILY_V4) if err != nil { return err } netDev := NetDev{MAC: link.Attrs().HardwareAddr} for _, addr := range addrs { netDev.CIDRs = append(netDev.CIDRs, addr.IPNet) } netDevs = append(netDevs, netDev) } } return nil }) return netDevs, err }
// GetSandboxForExternalKey returns sandbox object for the supplied path func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) { if err := createNamespaceFile(key); err != nil { return nil, err } if err := mountNetworkNamespace(basePath, key); err != nil { return nil, err } n := &networkNamespace{path: key} sboxNs, err := netns.GetFromPath(n.path) if err != nil { return nil, fmt.Errorf("failed get network namespace %q: %v", n.path, err) } defer sboxNs.Close() n.nlHandle, err = netlink.NewHandleAt(sboxNs) if err != nil { return nil, fmt.Errorf("failed to create a netlink handle: %v", err) } if err = n.loopbackUp(); err != nil { n.nlHandle.Delete() return nil, err } return n, nil }
func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) { _, ok := s.(*networkNamespace) if !ok { t.Fatalf("The sandox interface returned is not of type networkNamespace") } sbNs, err := netns.GetFromPath(s.Key()) if err != nil { t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err) } defer sbNs.Close() nh, err := netlink.NewHandleAt(sbNs) if err != nil { t.Fatal(err) } defer nh.Delete() for _, suffix := range ifaceSuffixes { _, err = nh.LinkByName(sboxIfaceName + suffix) if err != nil { t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName+suffix, err) } } }
func NewNetNsContext(path string) (*NetNSContext, error) { runtime.LockOSThread() origns, err := netns.Get() if err != nil { return nil, fmt.Errorf("Error while getting current ns: %s", err.Error()) } newns, err := netns.GetFromPath(path) if err != nil { origns.Close() return nil, fmt.Errorf("Error while opening %s: %s", path, err.Error()) } if err = netns.Set(newns); err != nil { newns.Close() origns.Close() return nil, fmt.Errorf("Error while switching from root ns to %s: %s", path, err.Error()) } return &NetNSContext{ origns: origns, newns: newns, }, nil }
func deleteVxlanByVNI(path string, vni uint32) error { defer osl.InitOSContext()() nlh := ns.NlHandle() if path != "" { ns, err := netns.GetFromPath(path) if err != nil { return fmt.Errorf("failed to get ns handle for %s: %v", path, err) } defer ns.Close() nlh, err = netlink.NewHandleAt(ns) if err != nil { return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err) } defer nlh.Delete() } links, err := nlh.LinkList() if err != nil { return fmt.Errorf("failed to list interfaces while deleting vxlan interface by vni: %v", err) } for _, l := range links { if l.Type() == "vxlan" && (vni == 0 || l.(*netlink.Vxlan).VxlanId == int(vni)) { err = nlh.LinkDel(l) if err != nil { return fmt.Errorf("error deleting vxlan interface with id %d: %v", vni, err) } return nil } } return fmt.Errorf("could not find a vxlan interface to delete with id %d", vni) }
// Redirecter reexec function. func redirecter() { runtime.LockOSThread() defer runtime.UnlockOSThread() if len(os.Args) < 4 { logrus.Error("invalid number of arguments..") os.Exit(1) } var ingressPorts []*PortConfig if os.Args[3] != "" { var err error ingressPorts, err = readPortsFromFile(os.Args[3]) if err != nil { logrus.Errorf("Failed reading ingress ports file: %v", err) os.Exit(2) } } eIP, _, err := net.ParseCIDR(os.Args[2]) if err != nil { logrus.Errorf("Failed to parse endpoint IP %s: %v", os.Args[2], err) os.Exit(3) } rules := [][]string{} for _, iPort := range ingressPorts { rule := strings.Fields(fmt.Sprintf("-t nat -A PREROUTING -d %s -p %s --dport %d -j REDIRECT --to-port %d", eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, iPort.TargetPort)) rules = append(rules, rule) } ns, err := netns.GetFromPath(os.Args[1]) if err != nil { logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err) os.Exit(4) } defer ns.Close() if err := netns.Set(ns); err != nil { logrus.Errorf("setting into container net ns %v failed, %v", os.Args[1], err) os.Exit(5) } for _, rule := range rules { if err := iptables.RawCombinedOutputNative(rule...); err != nil { logrus.Errorf("setting up rule failed, %v: %v", rule, err) os.Exit(5) } } }
func (nu *NetNsNetLinkTopoUpdater) Start(path string) { name := getNetNSName(path) logging.GetLogger().Debugf("Starting NetLinkTopoUpdater for NetNS: %s", name) runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { logging.GetLogger().Errorf("Error while switching from root ns to %s: %s", name, err.Error()) return } defer origns.Close() time.Sleep(1 * time.Second) newns, err := netns.GetFromPath(path) if err != nil { logging.GetLogger().Errorf("Error while switching from root ns to %s: %s", name, err.Error()) return } defer newns.Close() err = netns.Set(newns) if err != nil { logging.GetLogger().Errorf("Error while switching from root ns to %s: %s", name, err.Error()) return } /* start a netlinks updater inside this namespace */ nu.Lock() nu.nlProbe = NewNetLinkProbe(nu.Graph, nu.Root) nu.Unlock() /* NOTE(safchain) don't Start just Run, need to keep it alive for the time life of the netns * and there is no need to have a new goroutine here */ nu.nlProbe.Run() nu.Lock() nu.nlProbe = nil nu.Unlock() logging.GetLogger().Debugf("NetLinkTopoUpdater stopped for NetNS: %s", name) netns.Set(origns) }
func populateVNITbl() { filepath.Walk(filepath.Dir(osl.GenerateKey("walk")), func(path string, info os.FileInfo, err error) error { _, fname := filepath.Split(path) if len(strings.Split(fname, "-")) <= 1 { return nil } ns, err := netns.GetFromPath(path) if err != nil { logrus.Errorf("Could not open namespace path %s during vni population: %v", path, err) return nil } defer ns.Close() nlh, err := netlink.NewHandleAt(ns, syscall.NETLINK_ROUTE) if err != nil { logrus.Errorf("Could not open netlink handle during vni population for ns %s: %v", path, err) return nil } defer nlh.Delete() err = nlh.SetSocketTimeout(soTimeout) if err != nil { logrus.Warnf("Failed to set the timeout on the netlink handle sockets for vni table population: %v", err) } links, err := nlh.LinkList() if err != nil { logrus.Errorf("Failed to list interfaces during vni population for ns %s: %v", path, err) return nil } for _, l := range links { if l.Type() == "vxlan" { vniTbl[uint32(l.(*netlink.Vxlan).VxlanId)] = path } } return nil }) }
func child() { // Create temp file for NS path := "/proc/self/ns/net" must(syscall.Mount("fs/rootfs", "fs/rootfs", "", syscall.MS_BIND, "")) must(os.MkdirAll("fs/rootfs/oldrootfs", 0700)) must(syscall.PivotRoot("fs/rootfs", "fs/rootfs/oldrootfs")) must(os.Chdir("/")) must(syscall.Unmount("/oldrootfs", syscall.MNT_DETACH)) must(os.Remove("/oldrootfs")) must(syscall.Mount("proc", "/proc", "proc", 0, "")) // Some devices syscall.Mknod("/dev/null", 0666, Mkdev(int64(1), int64(3))) syscall.Mknod("/dev/zero", 0666, Mkdev(int64(1), int64(5))) syscall.Mknod("/dev/random", 0666, Mkdev(int64(1), int64(8))) syscall.Mknod("/dev/urandom", 0666, Mkdev(int64(1), int64(9))) fmt.Println("Pid:", os.Getpid()) ns, err := netns.GetFromPath(path) if err != nil { fmt.Println("cant find ns") } must(netns.Set(ns)) routingUp() cmd := exec.Command(os.Args[2], os.Args[3:]...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { fmt.Println("ERROR", err) os.Exit(1) } routingDown() }
// New provides a new ipvs handle in the namespace pointed to by the // passed path. It will return a valid handle or an error in case an // error occured while creating the handle. func New(path string) (*Handle, error) { setup() n := netns.None() if path != "" { var err error n, err = netns.GetFromPath(path) if err != nil { return nil, err } } defer n.Close() sock, err := nl.GetNetlinkSocketAt(n, netns.None(), syscall.NETLINK_GENERIC) if err != nil { return nil, err } return &Handle{sock: sock}, nil }
// NewSandbox provides a new sandbox instance created in an os specific way // provided a key which uniquely identifies the sandbox func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) { if !isRestore { err := createNetworkNamespace(key, osCreate) if err != nil { return nil, err } } else { once.Do(createBasePath) } n := &networkNamespace{path: key, isDefault: !osCreate} sboxNs, err := netns.GetFromPath(n.path) if err != nil { return nil, fmt.Errorf("failed get network namespace %q: %v", n.path, err) } defer sboxNs.Close() n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE) if err != nil { return nil, fmt.Errorf("failed to create a netlink handle: %v", err) } err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout) if err != nil { logrus.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err) } // As starting point, disable IPv6 on all interfaces err = setIPv6(n.path, "all", false) if err != nil { logrus.Warnf("Failed to disable IPv6 on all interfaces on network namespace %q: %v", n.path, err) } if err = n.loopbackUp(); err != nil { n.nlHandle.Delete() return nil, err } return n, nil }
func reexecSetIPv6() { runtime.LockOSThread() defer runtime.UnlockOSThread() if len(os.Args) < 3 { logrus.Errorf("invalid number of arguments for %s", os.Args[0]) os.Exit(1) } ns, err := netns.GetFromPath(os.Args[1]) if err != nil { logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err) os.Exit(2) } defer ns.Close() if err = netns.Set(ns); err != nil { logrus.Errorf("setting into container netns %q failed: %v", os.Args[1], err) os.Exit(3) } var ( action = "disable" value = byte('1') path = fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", os.Args[2]) ) if os.Args[3] == "true" { action = "enable" value = byte('0') } if err = ioutil.WriteFile(path, []byte{value, '\n'}, 0644); err != nil { logrus.Errorf("failed to %s IPv6 forwarding for container's interface %s: %v", action, os.Args[2], err) os.Exit(4) } os.Exit(0) }
// GetSandboxForExternalKey returns sandbox object for the supplied path func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) { if err := createNamespaceFile(key); err != nil { return nil, err } if err := mountNetworkNamespace(basePath, key); err != nil { return nil, err } n := &networkNamespace{path: key} sboxNs, err := netns.GetFromPath(n.path) if err != nil { return nil, fmt.Errorf("failed get network namespace %q: %v", n.path, err) } defer sboxNs.Close() n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE) if err != nil { return nil, fmt.Errorf("failed to create a netlink handle: %v", err) } err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout) if err != nil { logrus.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err) } // As starting point, disable IPv6 on all interfaces err = setIPv6(n.path, "all", false) if err != nil { logrus.Warnf("Failed to disable IPv6 on all interfaces on network namespace %q: %v", n.path, err) } if err = n.loopbackUp(); err != nil { n.nlHandle.Delete() return nil, err } return n, nil }
func networkOnceInit() { populateVNITbl() if os.Getenv("_OVERLAY_HOST_MODE") != "" { hostMode = true return } err := createVxlan("testvxlan", 1) if err != nil { logrus.Errorf("Failed to create testvxlan interface: %v", err) return } defer deleteInterface("testvxlan") path := "/proc/self/ns/net" hNs, err := netns.GetFromPath(path) if err != nil { logrus.Errorf("Failed to get network namespace from path %s while setting host mode: %v", path, err) return } defer hNs.Close() nlh := ns.NlHandle() iface, err := nlh.LinkByName("testvxlan") if err != nil { logrus.Errorf("Failed to get link testvxlan while setting host mode: %v", err) return } // If we are not able to move the vxlan interface to a namespace // then fallback to host mode if err := nlh.LinkSetNsFd(iface, int(hNs)); err != nil { hostMode = true } }
func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error { defer InitOSContext()() newNs, err := netns.GetFromPath(path) if err != nil { return fmt.Errorf("failed get network namespace %q: %v", path, err) } defer newNs.Close() // Invoked before the namespace switch happens but after the namespace file // handle is obtained. if err := prefunc(int(newNs)); err != nil { return fmt.Errorf("failed in prefunc: %v", err) } if err = netns.Set(newNs); err != nil { return err } defer ns.SetNamespace() // Invoked after the namespace switch. return postfunc(ns.ParseHandlerInt()) }
func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) { key := info.Sandbox().Key() sbNs, err := netns.GetFromPath(key) if err != nil { t.Fatalf("Failed to get network namespace path %q: %v", key, err) } defer sbNs.Close() nh, err := netlink.NewHandleAt(sbNs) if err != nil { t.Fatal(err) } _, err = nh.LinkByName("eth0") if err != nil { t.Fatalf("Could not find the interface eth0 inside the sandbox: %v", err) } _, err = nh.LinkByName("eth1") if err != nil { t.Fatalf("Could not find the interface eth1 inside the sandbox: %v", err) } }
// Firewall marker reexec function. func fwMarker() { runtime.LockOSThread() defer runtime.UnlockOSThread() if len(os.Args) < 7 { logrus.Error("invalid number of arguments..") os.Exit(1) } var ingressPorts []*PortConfig if os.Args[5] != "" { var err error ingressPorts, err = readPortsFromFile(os.Args[5]) if err != nil { logrus.Errorf("Failed reading ingress ports file: %v", err) os.Exit(6) } } vip := os.Args[2] fwMark, err := strconv.ParseUint(os.Args[3], 10, 32) if err != nil { logrus.Errorf("bad fwmark value(%s) passed: %v", os.Args[3], err) os.Exit(2) } addDelOpt := os.Args[4] rules := [][]string{} for _, iPort := range ingressPorts { rule := strings.Fields(fmt.Sprintf("-t mangle %s PREROUTING -p %s --dport %d -j MARK --set-mark %d", addDelOpt, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, fwMark)) rules = append(rules, rule) } ns, err := netns.GetFromPath(os.Args[1]) if err != nil { logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err) os.Exit(3) } defer ns.Close() if err := netns.Set(ns); err != nil { logrus.Errorf("setting into container net ns %v failed, %v", os.Args[1], err) os.Exit(4) } if addDelOpt == "-A" { eIP, subnet, err := net.ParseCIDR(os.Args[6]) if err != nil { logrus.Errorf("Failed to parse endpoint IP %s: %v", os.Args[6], err) os.Exit(9) } ruleParams := strings.Fields(fmt.Sprintf("-m ipvs --ipvs -d %s -j SNAT --to-source %s", subnet, eIP)) if !iptables.Exists("nat", "POSTROUTING", ruleParams...) { rule := append(strings.Fields("-t nat -A POSTROUTING"), ruleParams...) rules = append(rules, rule) err := ioutil.WriteFile("/proc/sys/net/ipv4/vs/conntrack", []byte{'1', '\n'}, 0644) if err != nil { logrus.Errorf("Failed to write to /proc/sys/net/ipv4/vs/conntrack: %v", err) os.Exit(8) } } } rule := strings.Fields(fmt.Sprintf("-t mangle %s OUTPUT -d %s/32 -j MARK --set-mark %d", addDelOpt, vip, fwMark)) rules = append(rules, rule) rule = strings.Fields(fmt.Sprintf("-t nat %s OUTPUT -p icmp --icmp echo-request -d %s -j DNAT --to 127.0.0.1", addDelOpt, vip)) rules = append(rules, rule) for _, rule := range rules { if err := iptables.RawCombinedOutputNative(rule...); err != nil { logrus.Errorf("setting up rule failed, %v: %v", rule, err) os.Exit(5) } } }
// Firewall marker reexec function. func fwMarker() { runtime.LockOSThread() defer runtime.UnlockOSThread() if len(os.Args) < 7 { logrus.Error("invalid number of arguments..") os.Exit(1) } var ingressPorts []*PortConfig if os.Args[5] != "" { buf, err := ioutil.ReadFile(os.Args[5]) if err != nil { logrus.Errorf("Failed to read ports config file: %v", err) os.Exit(6) } var epRec EndpointRecord err = proto.Unmarshal(buf, &epRec) if err != nil { logrus.Errorf("Failed to unmarshal ports config data: %v", err) os.Exit(7) } ingressPorts = epRec.IngressPorts } vip := os.Args[2] fwMark, err := strconv.ParseUint(os.Args[3], 10, 32) if err != nil { logrus.Errorf("bad fwmark value(%s) passed: %v", os.Args[3], err) os.Exit(2) } addDelOpt := os.Args[4] rules := [][]string{} for _, iPort := range ingressPorts { rule := strings.Fields(fmt.Sprintf("-t nat %s PREROUTING -p %s --dport %d -j REDIRECT --to-port %d", addDelOpt, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, iPort.TargetPort)) rules = append(rules, rule) rule = strings.Fields(fmt.Sprintf("-t mangle %s PREROUTING -p %s --dport %d -j MARK --set-mark %d", addDelOpt, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, fwMark)) rules = append(rules, rule) } ns, err := netns.GetFromPath(os.Args[1]) if err != nil { logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err) os.Exit(3) } defer ns.Close() if err := netns.Set(ns); err != nil { logrus.Errorf("setting into container net ns %v failed, %v", os.Args[1], err) os.Exit(4) } if len(ingressPorts) != 0 && addDelOpt == "-A" { ruleParams := strings.Fields(fmt.Sprintf("-m ipvs --ipvs -j SNAT --to-source %s", os.Args[6])) if !iptables.Exists("nat", "POSTROUTING", ruleParams...) { rule := append(strings.Fields("-t nat -A POSTROUTING"), ruleParams...) rules = append(rules, rule) err := ioutil.WriteFile("/proc/sys/net/ipv4/vs/conntrack", []byte{'1', '\n'}, 0644) if err != nil { logrus.Errorf("Failed to write to /proc/sys/net/ipv4/vs/conntrack: %v", err) os.Exit(8) } } } rule := strings.Fields(fmt.Sprintf("-t mangle %s OUTPUT -d %s/32 -j MARK --set-mark %d", addDelOpt, vip, fwMark)) rules = append(rules, rule) for _, rule := range rules { if err := iptables.RawCombinedOutputNative(rule...); err != nil { logrus.Errorf("setting up rule failed, %v: %v", rule, err) os.Exit(5) } } }
func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error { conf, err := loadNetConf(args.StdinData) if err != nil { return err } if conf.IsGW { return fmt.Errorf("Gateway functionality not supported") } if conf.IPMasq { return fmt.Errorf("IP Masquerading functionality not supported") } result, err := c.getIP(conf.IPAM.Type, args) if err != nil { return fmt.Errorf("unable to allocate IP address: %s", err) } // If config says nothing about routes or gateway, default one will be via the bridge if result.IP4.Routes == nil && result.IP4.Gateway == nil { bridgeIP, err := findBridgeIP(conf.BrName, result.IP4.IP) if err == errBridgeNoIP { bridgeArgs := *args bridgeArgs.ContainerID = "weave:expose" bridgeIPResult, err := c.getIP(conf.IPAM.Type, &bridgeArgs) if err != nil { return fmt.Errorf("unable to allocate IP address for bridge: %s", err) } if err := assignBridgeIP(conf.BrName, bridgeIPResult.IP4.IP); err != nil { return fmt.Errorf("unable to assign IP address to bridge: %s", err) } bridgeIP = bridgeIPResult.IP4.IP.IP } else if err != nil { return err } result.IP4.Gateway = bridgeIP } ns, err := netns.GetFromPath(args.Netns) if err != nil { return err } defer ns.Close() id := args.ContainerID if len(id) < 5 { data := make([]byte, 5) _, err := rand.Reader.Read(data) if err != nil { return err } id = fmt.Sprintf("%x", data) } if err := weavenet.AttachContainer(ns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&result.IP4.IP}, false); err != nil { return err } if err := weavenet.WithNetNSLinkUnsafe(ns, args.IfName, func(link netlink.Link) error { return setupRoutes(link, args.IfName, result.IP4.IP, result.IP4.Gateway, result.IP4.Routes) }); err != nil { return fmt.Errorf("error setting up routes: %s", err) } result.DNS = conf.DNS return result.Print() }
// Redirecter reexec function. func redirecter() { runtime.LockOSThread() defer runtime.UnlockOSThread() if len(os.Args) < 4 { logrus.Error("invalid number of arguments..") os.Exit(1) } var ingressPorts []*PortConfig if os.Args[3] != "" { var err error ingressPorts, err = readPortsFromFile(os.Args[3]) if err != nil { logrus.Errorf("Failed reading ingress ports file: %v", err) os.Exit(2) } } eIP, _, err := net.ParseCIDR(os.Args[2]) if err != nil { logrus.Errorf("Failed to parse endpoint IP %s: %v", os.Args[2], err) os.Exit(3) } rules := [][]string{} for _, iPort := range ingressPorts { rule := strings.Fields(fmt.Sprintf("-t nat -A PREROUTING -d %s -p %s --dport %d -j REDIRECT --to-port %d", eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, iPort.TargetPort)) rules = append(rules, rule) // Allow only incoming connections to exposed ports iRule := strings.Fields(fmt.Sprintf("-I INPUT -d %s -p %s --dport %d -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT", eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.TargetPort)) rules = append(rules, iRule) // Allow only outgoing connections from exposed ports oRule := strings.Fields(fmt.Sprintf("-I OUTPUT -s %s -p %s --sport %d -m conntrack --ctstate ESTABLISHED -j ACCEPT", eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.TargetPort)) rules = append(rules, oRule) } ns, err := netns.GetFromPath(os.Args[1]) if err != nil { logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err) os.Exit(4) } defer ns.Close() if err := netns.Set(ns); err != nil { logrus.Errorf("setting into container net ns %v failed, %v", os.Args[1], err) os.Exit(5) } for _, rule := range rules { if err := iptables.RawCombinedOutputNative(rule...); err != nil { logrus.Errorf("setting up rule failed, %v: %v", rule, err) os.Exit(6) } } if len(ingressPorts) == 0 { return } // Ensure blocking rules for anything else in/to ingress network for _, rule := range [][]string{ {"-d", eIP.String(), "-p", "udp", "-j", "DROP"}, {"-d", eIP.String(), "-p", "tcp", "-j", "DROP"}, } { if !iptables.ExistsNative(iptables.Filter, "INPUT", rule...) { if err := iptables.RawCombinedOutputNative(append([]string{"-A", "INPUT"}, rule...)...); err != nil { logrus.Errorf("setting up rule failed, %v: %v", rule, err) os.Exit(7) } } rule[0] = "-s" if !iptables.ExistsNative(iptables.Filter, "OUTPUT", rule...) { if err := iptables.RawCombinedOutputNative(append([]string{"-A", "OUTPUT"}, rule...)...); err != nil { logrus.Errorf("setting up rule failed, %v: %v", rule, err) os.Exit(8) } } } }
func (p *GoPacketProbesHandler) RegisterProbe(n *graph.Node, capture *api.Capture, ft *flow.Table) error { name, ok := n.Metadata()["Name"] if !ok || name == "" { return fmt.Errorf("No name for node %v", n) } id := string(n.ID) ifName := name.(string) if _, ok := p.probes[id]; ok { return fmt.Errorf("Already registered %s", ifName) } nodes := p.graph.LookupShortestPath(n, graph.Metadata{"Type": "host"}, graph.Metadata{"RelationType": "ownership"}) if len(nodes) == 0 { return fmt.Errorf("Failed to determine probePath for %s", ifName) } runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return fmt.Errorf("Error while getting current ns: %s", err.Error()) } defer origns.Close() for _, node := range nodes { if node.Metadata()["Type"] == "netns" { name := node.Metadata()["Name"].(string) path := node.Metadata()["Path"].(string) logging.GetLogger().Debugf("Switching to namespace %s (path: %s)", name, path) newns, err := netns.GetFromPath(path) if err != nil { return fmt.Errorf("Error while opening ns %s (path: %s): %s", name, path, err.Error()) } defer newns.Close() if err := netns.Set(newns); err != nil { return fmt.Errorf("Error while switching from root ns to %s (path: %s): %s", name, path, err.Error()) } defer netns.Set(origns) } } probe := &GoPacketProbe{ NodeUUID: id, state: common.StoppedState, flowTable: ft, } switch capture.Type { case "pcap": handle, err := pcap.OpenLive(ifName, snaplen, true, time.Second) if err != nil { return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error()) } if err := handle.SetBPFFilter(capture.BPFFilter); err != nil { return fmt.Errorf("BPF Filter failed: %s", err) } probe.handle = handle probe.packetSource = gopacket.NewPacketSource(handle, getGoPacketFirstLayerType(n)) logging.GetLogger().Infof("PCAP Capture type %s started on %s", capture.Type, n.Metadata()["Name"]) default: var handle *AFPacketHandle fnc := func() error { handle, err = NewAFPacketHandle(ifName, snaplen) if err != nil { return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error()) } return nil } if err = common.Retry(fnc, 2, 100*time.Millisecond); err != nil { return err } probe.handle = handle probe.packetSource = gopacket.NewPacketSource(handle, getGoPacketFirstLayerType(n)) logging.GetLogger().Infof("AfPacket Capture started on %s", n.Metadata()["Name"]) } p.probesLock.Lock() p.probes[id] = probe p.probesLock.Unlock() p.wg.Add(1) go func() { defer p.wg.Done() probe.start() }() return nil }
func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error { i := &nwIface{srcName: srcName, dstName: dstPrefix, ns: n} i.processInterfaceOptions(options...) if i.master != "" { i.dstMaster = n.findDst(i.master, true) if i.dstMaster == "" { return fmt.Errorf("could not find an appropriate master %q for %q", i.master, i.srcName) } } n.Lock() if n.isDefault { i.dstName = i.srcName } else { i.dstName = fmt.Sprintf("%s%d", i.dstName, n.nextIfIndex) n.nextIfIndex++ } path := n.path isDefault := n.isDefault nlh := n.nlHandle nlhHost := ns.NlHandle() n.Unlock() // If it is a bridge interface we have to create the bridge inside // the namespace so don't try to lookup the interface using srcName if i.bridge { link := &netlink.Bridge{ LinkAttrs: netlink.LinkAttrs{ Name: i.srcName, }, } if err := nlh.LinkAdd(link); err != nil { return fmt.Errorf("failed to create bridge %q: %v", i.srcName, err) } } else { // Find the network interface identified by the SrcName attribute. iface, err := nlhHost.LinkByName(i.srcName) if err != nil { return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err) } // Move the network interface to the destination // namespace only if the namespace is not a default // type if !isDefault { newNs, err := netns.GetFromPath(path) if err != nil { return fmt.Errorf("failed get network namespace %q: %v", path, err) } defer newNs.Close() if err := nlhHost.LinkSetNsFd(iface, int(newNs)); err != nil { return fmt.Errorf("failed to set namespace on link %q: %v", i.srcName, err) } } } // Find the network interface identified by the SrcName attribute. iface, err := nlh.LinkByName(i.srcName) if err != nil { return fmt.Errorf("failed to get link by name %q: %v", i.srcName, err) } // Down the interface before configuring if err := nlh.LinkSetDown(iface); err != nil { return fmt.Errorf("failed to set link down: %v", err) } // Configure the interface now this is moved in the proper namespace. if err := configureInterface(nlh, iface, i); err != nil { return err } // Up the interface. cnt := 0 for err = nlh.LinkSetUp(iface); err != nil && cnt < 3; cnt++ { logrus.Debugf("retrying link setup because of: %v", err) time.Sleep(10 * time.Millisecond) err = nlh.LinkSetUp(iface) } if err != nil { return fmt.Errorf("failed to set link up: %v", err) } // Set the routes on the interface. This can only be done when the interface is up. if err := setInterfaceRoutes(nlh, iface, i); err != nil { return fmt.Errorf("error setting interface %q routes to %q: %v", iface.Attrs().Name, i.Routes(), err) } n.Lock() n.iFaces = append(n.iFaces, i) n.Unlock() return nil }