1// +build !windows 2 3package libnetwork 4 5import ( 6 "fmt" 7 "net" 8 "os" 9 "os/exec" 10 "runtime" 11 12 "github.com/docker/docker/pkg/reexec" 13 "github.com/docker/libnetwork/iptables" 14 "github.com/sirupsen/logrus" 15 "github.com/vishvananda/netns" 16) 17 18func init() { 19 reexec.Register("setup-resolver", reexecSetupResolver) 20} 21 22const ( 23 // outputChain used for docker embed dns 24 outputChain = "DOCKER_OUTPUT" 25 //postroutingchain used for docker embed dns 26 postroutingchain = "DOCKER_POSTROUTING" 27) 28 29func reexecSetupResolver() { 30 runtime.LockOSThread() 31 defer runtime.UnlockOSThread() 32 33 if len(os.Args) < 4 { 34 logrus.Error("invalid number of arguments..") 35 os.Exit(1) 36 } 37 38 resolverIP, ipPort, _ := net.SplitHostPort(os.Args[2]) 39 _, tcpPort, _ := net.SplitHostPort(os.Args[3]) 40 rules := [][]string{ 41 {"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[2]}, 42 {"-t", "nat", "-I", postroutingchain, "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort}, 43 {"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[3]}, 44 {"-t", "nat", "-I", postroutingchain, "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort}, 45 } 46 47 f, err := os.OpenFile(os.Args[1], os.O_RDONLY, 0) 48 if err != nil { 49 logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err) 50 os.Exit(2) 51 } 52 defer f.Close() 53 54 nsFD := f.Fd() 55 if err = netns.Set(netns.NsHandle(nsFD)); err != nil { 56 logrus.Errorf("setting into container net ns %v failed, %v", os.Args[1], err) 57 os.Exit(3) 58 } 59 60 // insert outputChain and postroutingchain 61 err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "OUTPUT", "-d", resolverIP, "-j", outputChain) 62 if err == nil { 63 iptables.RawCombinedOutputNative("-t", "nat", "-F", outputChain) 64 } else { 65 iptables.RawCombinedOutputNative("-t", "nat", "-N", outputChain) 66 iptables.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain) 67 } 68 69 err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain) 70 if err == nil { 71 iptables.RawCombinedOutputNative("-t", "nat", "-F", postroutingchain) 72 } else { 73 iptables.RawCombinedOutputNative("-t", "nat", "-N", postroutingchain) 74 iptables.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain) 75 } 76 77 for _, rule := range rules { 78 if iptables.RawCombinedOutputNative(rule...) != nil { 79 logrus.Errorf("setting up rule failed, %v", rule) 80 } 81 } 82} 83 84func (r *resolver) setupIPTable() error { 85 if r.err != nil { 86 return r.err 87 } 88 laddr := r.conn.LocalAddr().String() 89 ltcpaddr := r.tcpListen.Addr().String() 90 91 cmd := &exec.Cmd{ 92 Path: reexec.Self(), 93 Args: append([]string{"setup-resolver"}, r.resolverKey, laddr, ltcpaddr), 94 Stdout: os.Stdout, 95 Stderr: os.Stderr, 96 } 97 if err := cmd.Run(); err != nil { 98 return fmt.Errorf("reexec failed: %v", err) 99 } 100 return nil 101} 102