mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Refactor of docker PR #11405
Signed-off-by: Alec Benson <albenson@redhat.com>
This commit is contained in:
parent
4a8b4af8af
commit
90a410eb3d
3 changed files with 177 additions and 0 deletions
|
@ -669,6 +669,9 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
|
||||||
|
|
||||||
// Add inter-network communication rules.
|
// Add inter-network communication rules.
|
||||||
{config.EnableIPTables, setupNetworkIsolationRules},
|
{config.EnableIPTables, setupNetworkIsolationRules},
|
||||||
|
|
||||||
|
//Configure bridge networking filtering if ICC is off and IP tables are enabled
|
||||||
|
{!config.EnableICC && config.EnableIPTables, setupBridgeNetFiltering},
|
||||||
} {
|
} {
|
||||||
if step.Condition {
|
if step.Condition {
|
||||||
bridgeSetup.queueStep(step.Fn)
|
bridgeSetup.queueStep(step.Fn)
|
||||||
|
|
162
libnetwork/drivers/bridge/setup_bridgenetfiltering.go
Normal file
162
libnetwork/drivers/bridge/setup_bridgenetfiltering.go
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
package bridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enumeration type saying which versions of IP protocol to process.
|
||||||
|
type ipVersion int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ipvnone ipVersion = iota
|
||||||
|
ipv4
|
||||||
|
ipv6
|
||||||
|
ipvboth
|
||||||
|
)
|
||||||
|
|
||||||
|
//Gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
|
||||||
|
func getIPVersion(config *networkConfiguration) ipVersion {
|
||||||
|
ipVersion := ipv4
|
||||||
|
if config.FixedCIDRv6 != nil || config.EnableIPv6 {
|
||||||
|
ipVersion |= ipv6
|
||||||
|
}
|
||||||
|
return ipVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
|
err := checkBridgeNetFiltering(config, i)
|
||||||
|
if err != nil {
|
||||||
|
if ptherr, ok := err.(*os.PathError); ok {
|
||||||
|
if errno, ok := ptherr.Err.(syscall.Errno); ok && errno == syscall.ENOENT {
|
||||||
|
if isRunningInContainer() {
|
||||||
|
logrus.Warnf("running inside docker container, ignoring missing kernel params: %v", err)
|
||||||
|
err = nil
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("please ensure that br_netfilter kernel module is loaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot restrict inter-container communication: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Enable bridge net filtering if ip forwarding is enabled. See github issue #11404
|
||||||
|
func checkBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
|
ipVer := getIPVersion(config)
|
||||||
|
iface := config.BridgeName
|
||||||
|
doEnable := func(ipVer ipVersion) error {
|
||||||
|
var ipVerName string
|
||||||
|
if ipVer == ipv4 {
|
||||||
|
ipVerName = "IPv4"
|
||||||
|
} else {
|
||||||
|
ipVerName = "IPv6"
|
||||||
|
}
|
||||||
|
enabled, err := isPacketForwardingEnabled(ipVer, iface)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warnf("failed to check %s forwarding: %v", ipVerName, err)
|
||||||
|
} else if enabled {
|
||||||
|
enabled, err := getKernelBoolParam(getBridgeNFKernelParam(ipVer))
|
||||||
|
if err != nil || enabled {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return setKernelBoolParam(getBridgeNFKernelParam(ipVer), true)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ipVer {
|
||||||
|
case ipv4, ipv6:
|
||||||
|
return doEnable(ipVer)
|
||||||
|
case ipvboth:
|
||||||
|
v4err := doEnable(ipv4)
|
||||||
|
v6err := doEnable(ipv6)
|
||||||
|
if v4err == nil {
|
||||||
|
return v6err
|
||||||
|
}
|
||||||
|
return v4err
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get kernel param path saying whether IPv${ipVer} traffic is being forwarded
|
||||||
|
// on particular interface. Interface may be specified for IPv6 only. If
|
||||||
|
// `iface` is empty, `default` will be assumed, which represents default value
|
||||||
|
// for new interfaces.
|
||||||
|
func getForwardingKernelParam(ipVer ipVersion, iface string) string {
|
||||||
|
switch ipVer {
|
||||||
|
case ipv4:
|
||||||
|
return "/proc/sys/net/ipv4/ip_forward"
|
||||||
|
case ipv6:
|
||||||
|
if iface == "" {
|
||||||
|
iface = "default"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/forwarding", iface)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get kernel param path saying whether bridged IPv${ipVer} traffic shall be
|
||||||
|
// passed to ip${ipVer}tables' chains.
|
||||||
|
func getBridgeNFKernelParam(ipVer ipVersion) string {
|
||||||
|
switch ipVer {
|
||||||
|
case ipv4:
|
||||||
|
return "/proc/sys/net/bridge/bridge-nf-call-iptables"
|
||||||
|
case ipv6:
|
||||||
|
return "/proc/sys/net/bridge/bridge-nf-call-ip6tables"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Gets the value of the kernel parameters located at the given path
|
||||||
|
func getKernelBoolParam(path string) (bool, error) {
|
||||||
|
enabled := false
|
||||||
|
line, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(line) > 0 {
|
||||||
|
enabled = line[0] == '1'
|
||||||
|
}
|
||||||
|
return enabled, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sets the value of the kernel parameter located at the given path
|
||||||
|
func setKernelBoolParam(path string, on bool) error {
|
||||||
|
value := byte('0')
|
||||||
|
if on {
|
||||||
|
value = byte('1')
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(path, []byte{value, '\n'}, 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Checks to see if packet forwarding is enabled
|
||||||
|
func isPacketForwardingEnabled(ipVer ipVersion, iface string) (bool, error) {
|
||||||
|
switch ipVer {
|
||||||
|
case ipv4, ipv6:
|
||||||
|
return getKernelBoolParam(getForwardingKernelParam(ipVer, iface))
|
||||||
|
case ipvboth:
|
||||||
|
enabled, err := getKernelBoolParam(getForwardingKernelParam(ipv4, ""))
|
||||||
|
if err != nil || !enabled {
|
||||||
|
return enabled, err
|
||||||
|
}
|
||||||
|
return getKernelBoolParam(getForwardingKernelParam(ipv6, iface))
|
||||||
|
default:
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRunningInContainer() bool {
|
||||||
|
_, err := os.Stat("/.dockerinit")
|
||||||
|
return !os.IsNotExist(err)
|
||||||
|
}
|
12
libnetwork/drivers/bridge/setup_bridgenetfiltering_test.go
Normal file
12
libnetwork/drivers/bridge/setup_bridgenetfiltering_test.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package bridge
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestIPConstantValues(t *testing.T) {
|
||||||
|
if ipv4|ipv6 != ipvboth {
|
||||||
|
t.Fatalf("bitwise or of ipv4(%04b) and ipv6(%04b) must yield ipvboth(%04b)", ipv4, ipv6, ipvboth)
|
||||||
|
}
|
||||||
|
if ipvboth&(^(ipv4 | ipv6)) != ipvnone {
|
||||||
|
t.Fatalf("ipvboth(%04b) with unset ipv4(%04b) and ipv6(%04b) bits shall equal to ipvnone", ipvboth, ipv4, ipv6)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue