func updateNamespaceNetworkLinks(pid int, ports io.Reader) error { name := "netlink-" + strconv.Itoa(pid) nsPath := fmt.Sprintf("/proc/%d/ns/net", pid) path := fmt.Sprintf("/var/run/netns/%s", name) if err := os.MkdirAll("/var/run/netns", 0755); err != nil { return err } if err := os.Symlink(nsPath, path); err != nil && !os.IsExist(err) { return err } defer os.Remove(path) sourceAddr, errs := getHostIPFromNamespace(name) if errs != nil { return errs } // Enable routing in the namespace output, err := exec.Command("ip", "netns", "exec", name, "sysctl", "-w", "net.ipv4.conf.all.route_localnet=1").Output() if err != nil { log.Printf("gear: Failed to enable localnet routing: %v", err) log.Printf("gear: error output: %v", output) return err } // Enable ip forwarding output, err = exec.Command("ip", "netns", "exec", name, "sysctl", "-w", "net.ipv4.ip_forward=1").Output() if err != nil { log.Printf("gear: Failed to enable ipv4 forwarding: %v", err) log.Printf("gear: error output: %v", output) return err } // Restore a set of rules to the table cmd := exec.Command("ip", "netns", "exec", name, "iptables-restore") stdin, errp := cmd.StdinPipe() if errp != nil { log.Printf("gear: Could not open pipe to iptables-restore: %v", errp) return errp } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr defer stdin.Close() if err := cmd.Start(); err != nil { log.Printf("gear: Could not start iptables-restore: %v", errp) return err } fmt.Fprintf(stdin, "*nat\n") for { link := containers.NetworkLink{} if _, err := fmt.Fscanf(ports, "%s\t%v\t%v\t%s\n", &link.FromHost, &link.FromPort, &link.ToPort, &link.ToHost); err != nil { if err == io.EOF { break } log.Printf("gear: Could not read from network links file: %v", err) continue } if err := link.Check(); err != nil { log.Printf("gear: Link in file is not valid: %v", err) continue } if link.Complete() { srcIP, err := net.ResolveIPAddr("ip", link.FromHost) if err != nil { log.Printf("gear: Link source host does not resolve %v", err) continue } destIP, err := resolver.ResolveIP(link.ToHost) if err != nil { log.Printf("gear: Link destination host does not resolve %v", err) continue } data := containers.OutboundNetworkIptables{sourceAddr.String(), srcIP.IP.String(), link.FromPort, destIP.String(), link.ToPort} if err := containers.OutboundNetworkIptablesTemplate.Execute(stdin, &data); err != nil { log.Printf("gear: Unable to write network link rules: %v", err) return err } } } fmt.Fprintf(stdin, "COMMIT\n") stdin.Close() if err := cmd.Wait(); err != nil { log.Printf("gear: iptables-restore did not successfully complete: %v", err) return err } return nil }
func updateNamespaceNetworkLinks(name string, sourceAddr *net.IPAddr, ports io.Reader) error { // Enable routing in the namespace output, err := exec.Command("ip", "netns", "exec", name, "sysctl", "-w", "net.ipv4.conf.all.route_localnet=1").Output() if err != nil { log.Printf("gear: Failed to enable localnet routing: %v", err) log.Printf("gear: error output: %v", output) return err } // Enable ip forwarding output, err = exec.Command("ip", "netns", "exec", name, "sysctl", "-w", "net.ipv4.ip_forward=1").Output() if err != nil { log.Printf("gear: Failed to enable ipv4 forwarding: %v", err) log.Printf("gear: error output: %v", output) return err } // Restore a set of rules to the table cmd := exec.Command("ip", "netns", "exec", name, "iptables-restore") stdin, errp := cmd.StdinPipe() if errp != nil { log.Printf("gear: Could not open pipe to iptables-restore: %v", errp) return errp } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr defer stdin.Close() if err := cmd.Start(); err != nil { log.Printf("gear: Could not start iptables-restore: %v", errp) return err } fmt.Fprintf(stdin, "*nat\n") for { link := containers.NetworkLink{} if _, err := fmt.Fscanf(ports, "%s\t%v\t%v\t%s\n", &link.FromHost, &link.FromPort, &link.ToPort, &link.ToHost); err != nil { if err == io.EOF { break } log.Printf("gear: Could not read from network links file: %v", err) continue } if err := link.Check(); err != nil { log.Printf("gear: Link in file is not valid: %v", err) continue } if link.Complete() { srcIP, err := net.ResolveIPAddr("ip", link.FromHost) if err != nil { log.Printf("gear: Link source host does not resolve %v", err) continue } destIP, err := resolver.ResolveIP(link.ToHost) if err != nil { log.Printf("gear: Link destination host does not resolve %v", err) continue } log.Printf("Mapping %s(%s):%d -> %s:%d", sourceAddr.String(), srcIP.String(), link.FromPort, destIP.String(), link.ToPort) data := OutboundNetworkIptables{sourceAddr.String(), srcIP.IP.String(), link.FromPort, destIP.String(), link.ToPort} if err := OutboundNetworkIptablesTemplate.Execute(stdin, &data); err != nil { log.Printf("gear: Unable to write network link rules: %v", err) return err } } } fmt.Fprintf(stdin, "COMMIT\n") stdin.Close() if err := cmd.Wait(); err != nil { log.Printf("gear: iptables-restore did not successfully complete: %v", err) return err } return nil }