resolver_unix.go 3.0 KB

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