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