resolver_unix.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // +build !windows
  2. package libnetwork
  3. import (
  4. "fmt"
  5. "net"
  6. "os"
  7. "os/exec"
  8. "runtime"
  9. log "github.com/Sirupsen/logrus"
  10. "github.com/docker/docker/pkg/reexec"
  11. "github.com/docker/libnetwork/iptables"
  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. log.Error("invalid number of arguments..")
  28. os.Exit(1)
  29. }
  30. _, 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. log.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. log.Errorf("setting into container net ns %v failed, %v", os.Args[1], err)
  47. os.Exit(3)
  48. }
  49. // insert outputChain and postroutingchain
  50. err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "OUTPUT", "-d", resolverIP, "-j", outputChain)
  51. if err == nil {
  52. iptables.RawCombinedOutputNative("-t", "nat", "-F", outputChain)
  53. } else {
  54. iptables.RawCombinedOutputNative("-t", "nat", "-N", outputChain)
  55. iptables.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain)
  56. }
  57. err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
  58. if err == nil {
  59. iptables.RawCombinedOutputNative("-t", "nat", "-F", postroutingchain)
  60. } else {
  61. iptables.RawCombinedOutputNative("-t", "nat", "-N", postroutingchain)
  62. iptables.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
  63. }
  64. for _, rule := range rules {
  65. if iptables.RawCombinedOutputNative(rule...) != nil {
  66. log.Errorf("setting up rule failed, %v", rule)
  67. }
  68. }
  69. }
  70. func (r *resolver) setupIPTable() error {
  71. if r.err != nil {
  72. return r.err
  73. }
  74. laddr := r.conn.LocalAddr().String()
  75. ltcpaddr := r.tcpListen.Addr().String()
  76. cmd := &exec.Cmd{
  77. Path: reexec.Self(),
  78. Args: append([]string{"setup-resolver"}, r.sb.Key(), laddr, ltcpaddr),
  79. Stdout: os.Stdout,
  80. Stderr: os.Stderr,
  81. }
  82. if err := cmd.Run(); err != nil {
  83. return fmt.Errorf("reexec failed: %v", err)
  84. }
  85. return nil
  86. }