dotcloud/docker

View on GitHub
libnetwork/resolver_unix.go

Summary

Maintainability
B
6 hrs
Test Coverage
//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
}