github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/resolver_unix.go (about) 1 // +build !windows 2 3 package libnetwork 4 5 import ( 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 18 func init() { 19 reexec.Register("setup-resolver", reexecSetupResolver) 20 } 21 22 const ( 23 // outputChain used for docker embed dns 24 outputChain = "DOCKER_OUTPUT" 25 //postroutingchain used for docker embed dns 26 postroutingchain = "DOCKER_POSTROUTING" 27 ) 28 29 func 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 // TODO IPv6 support 61 iptable := iptables.GetIptable(iptables.IPv4) 62 63 // insert outputChain and postroutingchain 64 err = iptable.RawCombinedOutputNative("-t", "nat", "-C", "OUTPUT", "-d", resolverIP, "-j", outputChain) 65 if err == nil { 66 iptable.RawCombinedOutputNative("-t", "nat", "-F", outputChain) 67 } else { 68 iptable.RawCombinedOutputNative("-t", "nat", "-N", outputChain) 69 iptable.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain) 70 } 71 72 err = iptable.RawCombinedOutputNative("-t", "nat", "-C", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain) 73 if err == nil { 74 iptable.RawCombinedOutputNative("-t", "nat", "-F", postroutingchain) 75 } else { 76 iptable.RawCombinedOutputNative("-t", "nat", "-N", postroutingchain) 77 iptable.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain) 78 } 79 80 for _, rule := range rules { 81 if iptable.RawCombinedOutputNative(rule...) != nil { 82 logrus.Errorf("set up rule failed, %v", rule) 83 } 84 } 85 } 86 87 func (r *resolver) setupIPTable() error { 88 if r.err != nil { 89 return r.err 90 } 91 laddr := r.conn.LocalAddr().String() 92 ltcpaddr := r.tcpListen.Addr().String() 93 94 cmd := &exec.Cmd{ 95 Path: reexec.Self(), 96 Args: append([]string{"setup-resolver"}, r.resolverKey, laddr, ltcpaddr), 97 Stdout: os.Stdout, 98 Stderr: os.Stderr, 99 } 100 if err := cmd.Run(); err != nil { 101 return fmt.Errorf("reexec failed: %v", err) 102 } 103 return nil 104 }