resolver_unix.go 3.1 KB

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