1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/libnetwork/drivers/bridge/setup_ip_tables.go
Alessandro Boch 5d7b430801 Issue #33: Move portmapper and portallocator into libnetwork
- As they provide network translation functionalities,
  they should be part of libnetwork
- In driver/bridge/setup_ip_tables.go remove depenency
  on docker/daemon/networkdriver

Signed-off-by: Alessandro Boch <aboch@docker.com>
2015-04-09 11:05:02 -07:00

150 lines
4.2 KiB
Go

package bridge
import (
"fmt"
"net"
"github.com/docker/docker/pkg/iptables"
"github.com/docker/libnetwork"
"github.com/docker/libnetwork/portmapper"
)
// DockerChain: DOCKER iptable chain name
const (
DockerChain = "DOCKER"
)
func setupIPTables(i *bridgeInterface) error {
// Sanity check.
if i.Config.EnableIPTables == false {
return fmt.Errorf("Unexpected request to set IP tables for interface: %s", i.Config.BridgeName)
}
addrv4, _, err := libnetwork.GetIfaceAddr(i.Config.BridgeName)
if err != nil {
return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
}
if err = setupIPTablesInternal(i.Config.BridgeName, addrv4, i.Config.EnableICC, i.Config.EnableIPMasquerade, true); err != nil {
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
}
_, err = iptables.NewChain(DockerChain, i.Config.BridgeName, iptables.Nat)
if err != nil {
return fmt.Errorf("Failed to create NAT chain: %s", err.Error())
}
chain, err := iptables.NewChain(DockerChain, i.Config.BridgeName, iptables.Filter)
if err != nil {
return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
}
portmapper.SetIptablesChain(chain)
return nil
}
func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, enable bool) error {
var (
address = addr.String()
natRule = []string{"POSTROUTING", "-t", "nat", "-s", address, "!", "-o", bridgeIface, "-j", "MASQUERADE"}
outRule = []string{"FORWARD", "-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}
inRule = []string{"FORWARD", "-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}
)
// Set NAT.
if ipmasq {
if err := programChainRule(natRule, "NAT", enable); err != nil {
return err
}
}
// Set Inter Container Communication.
if err := setIcc(bridgeIface, icc, enable); err != nil {
return err
}
// Set Accept on all non-intercontainer outgoing packets.
if err := programChainRule(outRule, "ACCEPT NON_ICC OUTGOING", enable); err != nil {
return err
}
// Set Accept on incoming packets for existing connections.
if err := programChainRule(inRule, "ACCEPT INCOMING", enable); err != nil {
return err
}
return nil
}
func programChainRule(ruleArgs []string, ruleDescr string, insert bool) error {
var (
prefix []string
operation string
condition bool
)
if insert {
condition = !iptables.Exists(ruleArgs...)
prefix = []string{"-I"}
operation = "enable"
} else {
condition = iptables.Exists(ruleArgs...)
prefix = []string{"-D"}
operation = "disable"
}
if condition {
if output, err := iptables.Raw(append(prefix, ruleArgs...)...); err != nil {
return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
} else if len(output) != 0 {
return &iptables.ChainError{Chain: ruleDescr, Output: output}
}
}
return nil
}
func setIcc(bridgeIface string, iccEnable, insert bool) error {
var (
args = []string{"FORWARD", "-i", bridgeIface, "-o", bridgeIface, "-j"}
acceptArgs = append(args, "ACCEPT")
dropArgs = append(args, "DROP")
)
if insert {
if !iccEnable {
iptables.Raw(append([]string{"-D"}, acceptArgs...)...)
if !iptables.Exists(dropArgs...) {
if output, err := iptables.Raw(append([]string{"-I"}, dropArgs...)...); err != nil {
return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
} else if len(output) != 0 {
return fmt.Errorf("Error disabling intercontainer communication: %s", output)
}
}
} else {
iptables.Raw(append([]string{"-D"}, dropArgs...)...)
if !iptables.Exists(acceptArgs...) {
if output, err := iptables.Raw(append([]string{"-I"}, acceptArgs...)...); err != nil {
return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
} else if len(output) != 0 {
return fmt.Errorf("Error enabling intercontainer communication: %s", output)
}
}
}
} else {
// Remove any ICC rule.
if !iccEnable {
if iptables.Exists(dropArgs...) {
iptables.Raw(append([]string{"-D"}, dropArgs...)...)
}
} else {
if iptables.Exists(acceptArgs...) {
iptables.Raw(append([]string{"-D"}, acceptArgs...)...)
}
}
}
return nil
}