//go:build !windows package libnetwork import ( "fmt" "net" "github.com/docker/docker/libnetwork/iptables" ) const ( // output chain used for docker embedded DNS resolver outputChain = "DOCKER_OUTPUT" // postrouting chain used for docker embedded DNS resolver postroutingChain = "DOCKER_POSTROUTING" ) func (r *Resolver) setupIPTable() error { if r.err != nil { return r.err } laddr := r.conn.LocalAddr().String() ltcpaddr := r.tcpListen.Addr().String() resolverIP, ipPort, _ := net.SplitHostPort(laddr) _, tcpPort, _ := net.SplitHostPort(ltcpaddr) rules := [][]string{ {"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", laddr}, {"-t", "nat", "-I", postroutingChain, "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort}, {"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", ltcpaddr}, {"-t", "nat", "-I", postroutingChain, "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort}, } var setupErr error err := r.backend.ExecFunc(func() { // TODO IPv6 support iptable := iptables.GetIptable(iptables.IPv4) // insert outputChain and postroutingchain if iptable.ExistsNative("nat", "OUTPUT", "-d", resolverIP, "-j", outputChain) { if err := iptable.RawCombinedOutputNative("-t", "nat", "-F", outputChain); err != nil { setupErr = err return } } else { if err := iptable.RawCombinedOutputNative("-t", "nat", "-N", outputChain); err != nil { setupErr = err return } if err := iptable.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain); err != nil { setupErr = err return } } if iptable.ExistsNative("nat", "POSTROUTING", "-d", resolverIP, "-j", postroutingChain) { if err := iptable.RawCombinedOutputNative("-t", "nat", "-F", postroutingChain); err != nil { setupErr = err return } } else { if err := iptable.RawCombinedOutputNative("-t", "nat", "-N", postroutingChain); err != nil { setupErr = err return } if err := iptable.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingChain); err != nil { setupErr = err return } } for _, rule := range rules { if iptable.RawCombinedOutputNative(rule...) != nil { setupErr = fmt.Errorf("set up rule failed, %v", rule) return } } }) if err != nil { return err } return setupErr }