mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Seperates the driver-specific and network-specific iptable operations
for the bridge driver. Moves two config options, namely EnableIPTables and EnableUserlandProxy from networks to the driver. Closes #242 Signed-off-by: Mohammad Banikazemi <MBanikazemi@gmail.com>
This commit is contained in:
parent
4cebc617d1
commit
12df37fdd0
15 changed files with 303 additions and 119 deletions
|
@ -1680,6 +1680,11 @@ func TestHttpHandlerUninit(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = c.ConfigureNetworkDriver(bridgeNetType, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
h := &httpHandler{c: c}
|
h := &httpHandler{c: c}
|
||||||
h.initRouter()
|
h.initRouter()
|
||||||
if h.r == nil {
|
if h.r == nil {
|
||||||
|
@ -1777,6 +1782,11 @@ func TestEndToEnd(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
err = c.ConfigureNetworkDriver(bridgeNetType, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
handleRequest := NewHTTPHandler(c)
|
handleRequest := NewHTTPHandler(c)
|
||||||
|
|
||||||
ops := options.Generic{
|
ops := options.Generic{
|
||||||
|
|
|
@ -41,6 +41,8 @@ var (
|
||||||
// configuration info for the "bridge" driver.
|
// configuration info for the "bridge" driver.
|
||||||
type configuration struct {
|
type configuration struct {
|
||||||
EnableIPForwarding bool
|
EnableIPForwarding bool
|
||||||
|
EnableIPTables bool
|
||||||
|
EnableUserlandProxy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// networkConfiguration for network specific configuration
|
// networkConfiguration for network specific configuration
|
||||||
|
@ -50,7 +52,6 @@ type networkConfiguration struct {
|
||||||
FixedCIDR *net.IPNet
|
FixedCIDR *net.IPNet
|
||||||
FixedCIDRv6 *net.IPNet
|
FixedCIDRv6 *net.IPNet
|
||||||
EnableIPv6 bool
|
EnableIPv6 bool
|
||||||
EnableIPTables bool
|
|
||||||
EnableIPMasquerade bool
|
EnableIPMasquerade bool
|
||||||
EnableICC bool
|
EnableICC bool
|
||||||
Mtu int
|
Mtu int
|
||||||
|
@ -58,7 +59,6 @@ type networkConfiguration struct {
|
||||||
DefaultGatewayIPv6 net.IP
|
DefaultGatewayIPv6 net.IP
|
||||||
DefaultBindingIP net.IP
|
DefaultBindingIP net.IP
|
||||||
AllowNonDefaultBridge bool
|
AllowNonDefaultBridge bool
|
||||||
EnableUserlandProxy bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endpointConfiguration represents the user specified configuration for the sandbox endpoint
|
// endpointConfiguration represents the user specified configuration for the sandbox endpoint
|
||||||
|
@ -91,12 +91,15 @@ type bridgeNetwork struct {
|
||||||
config *networkConfiguration
|
config *networkConfiguration
|
||||||
endpoints map[types.UUID]*bridgeEndpoint // key: endpoint id
|
endpoints map[types.UUID]*bridgeEndpoint // key: endpoint id
|
||||||
portMapper *portmapper.PortMapper
|
portMapper *portmapper.PortMapper
|
||||||
|
driver *driver // The network's driver
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type driver struct {
|
type driver struct {
|
||||||
config *configuration
|
config *configuration
|
||||||
network *bridgeNetwork
|
network *bridgeNetwork
|
||||||
|
natChain *iptables.ChainInfo
|
||||||
|
filterChain *iptables.ChainInfo
|
||||||
networks map[types.UUID]*bridgeNetwork
|
networks map[types.UUID]*bridgeNetwork
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
@ -223,16 +226,6 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i, ok := data["EnableIPTables"]; ok && i != nil {
|
|
||||||
if s, ok := i.(string); ok {
|
|
||||||
if c.EnableIPTables, err = strconv.ParseBool(s); err != nil {
|
|
||||||
return types.BadRequestErrorf("failed to parse EnableIPTables value: %s", err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("invalid type for EnableIPTables value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, ok := data["EnableIPMasquerade"]; ok && i != nil {
|
if i, ok := data["EnableIPMasquerade"]; ok && i != nil {
|
||||||
if s, ok := i.(string); ok {
|
if s, ok := i.(string); ok {
|
||||||
if c.EnableIPMasquerade, err = strconv.ParseBool(s); err != nil {
|
if c.EnableIPMasquerade, err = strconv.ParseBool(s); err != nil {
|
||||||
|
@ -334,6 +327,25 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||||
|
n.Lock()
|
||||||
|
defer n.Unlock()
|
||||||
|
|
||||||
|
if n.driver == nil {
|
||||||
|
return nil, nil, types.BadRequestErrorf("no driver found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return n.driver.natChain, n.driver.filterChain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *bridgeNetwork) getNetworkBridgeName() string {
|
||||||
|
n.Lock()
|
||||||
|
config := n.config
|
||||||
|
n.Unlock()
|
||||||
|
|
||||||
|
return config.BridgeName
|
||||||
|
}
|
||||||
|
|
||||||
func (n *bridgeNetwork) getEndpoint(eid types.UUID) (*bridgeEndpoint, error) {
|
func (n *bridgeNetwork) getEndpoint(eid types.UUID) (*bridgeEndpoint, error) {
|
||||||
n.Lock()
|
n.Lock()
|
||||||
defer n.Unlock()
|
defer n.Unlock()
|
||||||
|
@ -418,6 +430,7 @@ func (c *networkConfiguration) conflictsWithNetworks(id types.UUID, others []*br
|
||||||
|
|
||||||
func (d *driver) Config(option map[string]interface{}) error {
|
func (d *driver) Config(option map[string]interface{}) error {
|
||||||
var config *configuration
|
var config *configuration
|
||||||
|
var err error
|
||||||
|
|
||||||
d.Lock()
|
d.Lock()
|
||||||
defer d.Unlock()
|
defer d.Unlock()
|
||||||
|
@ -444,10 +457,19 @@ func (d *driver) Config(option map[string]interface{}) error {
|
||||||
d.config = config
|
d.config = config
|
||||||
} else {
|
} else {
|
||||||
config = &configuration{}
|
config = &configuration{}
|
||||||
|
d.config = config
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.EnableIPForwarding {
|
if config.EnableIPForwarding {
|
||||||
return setupIPForwarding()
|
err = setupIPForwarding()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.EnableIPTables {
|
||||||
|
d.natChain, d.filterChain, err = setupIPChains(config)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -480,7 +502,6 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
config = &networkConfiguration{
|
config = &networkConfiguration{
|
||||||
EnableICC: true,
|
EnableICC: true,
|
||||||
EnableIPTables: true,
|
|
||||||
EnableIPMasquerade: true,
|
EnableIPMasquerade: true,
|
||||||
}
|
}
|
||||||
err = config.fromMap(opt)
|
err = config.fromMap(opt)
|
||||||
|
@ -578,6 +599,7 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
|
||||||
endpoints: make(map[types.UUID]*bridgeEndpoint),
|
endpoints: make(map[types.UUID]*bridgeEndpoint),
|
||||||
config: config,
|
config: config,
|
||||||
portMapper: portmapper.New(),
|
portMapper: portmapper.New(),
|
||||||
|
driver: d,
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Lock()
|
d.Lock()
|
||||||
|
@ -660,14 +682,14 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
|
||||||
{enableIPv6Forwarding, setupIPv6Forwarding},
|
{enableIPv6Forwarding, setupIPv6Forwarding},
|
||||||
|
|
||||||
// Setup Loopback Adresses Routing
|
// Setup Loopback Adresses Routing
|
||||||
{!config.EnableUserlandProxy, setupLoopbackAdressesRouting},
|
{!d.config.EnableUserlandProxy, setupLoopbackAdressesRouting},
|
||||||
|
|
||||||
// Setup IPTables.
|
// Setup IPTables.
|
||||||
{config.EnableIPTables, network.setupIPTables},
|
{d.config.EnableIPTables, network.setupIPTables},
|
||||||
|
|
||||||
//We want to track firewalld configuration so that
|
//We want to track firewalld configuration so that
|
||||||
//if it is started/reloaded, the rules can be applied correctly
|
//if it is started/reloaded, the rules can be applied correctly
|
||||||
{config.EnableIPTables, network.setupFirewalld},
|
{d.config.EnableIPTables, network.setupFirewalld},
|
||||||
|
|
||||||
// Setup DefaultGatewayIPv4
|
// Setup DefaultGatewayIPv4
|
||||||
{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
|
{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
|
||||||
|
@ -676,10 +698,10 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
|
||||||
{config.DefaultGatewayIPv6 != nil, setupGatewayIPv6},
|
{config.DefaultGatewayIPv6 != nil, setupGatewayIPv6},
|
||||||
|
|
||||||
// Add inter-network communication rules.
|
// Add inter-network communication rules.
|
||||||
{config.EnableIPTables, setupNetworkIsolationRules},
|
{d.config.EnableIPTables, setupNetworkIsolationRules},
|
||||||
|
|
||||||
//Configure bridge networking filtering if ICC is off and IP tables are enabled
|
//Configure bridge networking filtering if ICC is off and IP tables are enabled
|
||||||
{!config.EnableICC && config.EnableIPTables, setupBridgeNetFiltering},
|
{!config.EnableICC && d.config.EnableIPTables, setupBridgeNetFiltering},
|
||||||
} {
|
} {
|
||||||
if step.Condition {
|
if step.Condition {
|
||||||
bridgeSetup.queueStep(step.Fn)
|
bridgeSetup.queueStep(step.Fn)
|
||||||
|
@ -838,6 +860,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||||
// Get the network handler and make sure it exists
|
// Get the network handler and make sure it exists
|
||||||
d.Lock()
|
d.Lock()
|
||||||
n, ok := d.networks[nid]
|
n, ok := d.networks[nid]
|
||||||
|
dconfig := d.config
|
||||||
d.Unlock()
|
d.Unlock()
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -950,7 +973,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||||
return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err)
|
return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.EnableUserlandProxy {
|
if !dconfig.EnableUserlandProxy {
|
||||||
err = setHairpinMode(host, true)
|
err = setHairpinMode(host, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1023,7 +1046,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Program any required port mapping and store them in the endpoint
|
// Program any required port mapping and store them in the endpoint
|
||||||
endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, config.EnableUserlandProxy)
|
endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ func TestCreateFullOptions(t *testing.T) {
|
||||||
|
|
||||||
config := &configuration{
|
config := &configuration{
|
||||||
EnableIPForwarding: true,
|
EnableIPForwarding: true,
|
||||||
|
EnableIPTables: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test this scenario: Default gw address does not belong to
|
// Test this scenario: Default gw address does not belong to
|
||||||
|
@ -37,7 +38,6 @@ func TestCreateFullOptions(t *testing.T) {
|
||||||
FixedCIDR: cnw,
|
FixedCIDR: cnw,
|
||||||
DefaultGatewayIPv4: gw,
|
DefaultGatewayIPv4: gw,
|
||||||
EnableIPv6: true,
|
EnableIPv6: true,
|
||||||
EnableIPTables: true,
|
|
||||||
}
|
}
|
||||||
_, netConfig.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
|
_, netConfig.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
|
@ -71,9 +71,13 @@ func TestCreate(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
config := &networkConfiguration{BridgeName: DefaultBridgeName}
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
genericOption[netlabel.GenericData] = config
|
genericOption[netlabel.GenericData] = netconfig
|
||||||
|
|
||||||
if err := d.CreateNetwork("dummy", genericOption); err != nil {
|
if err := d.CreateNetwork("dummy", genericOption); err != nil {
|
||||||
t.Fatalf("Failed to create bridge: %v", err)
|
t.Fatalf("Failed to create bridge: %v", err)
|
||||||
|
@ -100,9 +104,13 @@ func TestCreateFail(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
config := &networkConfiguration{BridgeName: "dummy0"}
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
netconfig := &networkConfiguration{BridgeName: "dummy0"}
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
genericOption[netlabel.GenericData] = config
|
genericOption[netlabel.GenericData] = netconfig
|
||||||
|
|
||||||
if err := d.CreateNetwork("dummy", genericOption); err == nil {
|
if err := d.CreateNetwork("dummy", genericOption); err == nil {
|
||||||
t.Fatal("Bridge creation was expected to fail")
|
t.Fatal("Bridge creation was expected to fail")
|
||||||
|
@ -114,20 +122,30 @@ func TestCreateMultipleNetworks(t *testing.T) {
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
dd, _ := d.(*driver)
|
dd, _ := d.(*driver)
|
||||||
|
|
||||||
config1 := &networkConfiguration{BridgeName: "net_test_1", AllowNonDefaultBridge: true, EnableIPTables: true}
|
config := &configuration{
|
||||||
|
EnableIPTables: true,
|
||||||
|
}
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
|
genericOption[netlabel.GenericData] = config
|
||||||
|
|
||||||
|
if err := d.Config(genericOption); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config1 := &networkConfiguration{BridgeName: "net_test_1", AllowNonDefaultBridge: true}
|
||||||
|
genericOption = make(map[string]interface{})
|
||||||
genericOption[netlabel.GenericData] = config1
|
genericOption[netlabel.GenericData] = config1
|
||||||
if err := d.CreateNetwork("1", genericOption); err != nil {
|
if err := d.CreateNetwork("1", genericOption); err != nil {
|
||||||
t.Fatalf("Failed to create bridge: %v", err)
|
t.Fatalf("Failed to create bridge: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config2 := &networkConfiguration{BridgeName: "net_test_2", AllowNonDefaultBridge: true, EnableIPTables: true}
|
config2 := &networkConfiguration{BridgeName: "net_test_2", AllowNonDefaultBridge: true}
|
||||||
genericOption[netlabel.GenericData] = config2
|
genericOption[netlabel.GenericData] = config2
|
||||||
if err := d.CreateNetwork("2", genericOption); err != nil {
|
if err := d.CreateNetwork("2", genericOption); err != nil {
|
||||||
t.Fatalf("Failed to create bridge: %v", err)
|
t.Fatalf("Failed to create bridge: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config3 := &networkConfiguration{BridgeName: "net_test_3", AllowNonDefaultBridge: true, EnableIPTables: true}
|
config3 := &networkConfiguration{BridgeName: "net_test_3", AllowNonDefaultBridge: true}
|
||||||
genericOption[netlabel.GenericData] = config3
|
genericOption[netlabel.GenericData] = config3
|
||||||
if err := d.CreateNetwork("3", genericOption); err != nil {
|
if err := d.CreateNetwork("3", genericOption); err != nil {
|
||||||
t.Fatalf("Failed to create bridge: %v", err)
|
t.Fatalf("Failed to create bridge: %v", err)
|
||||||
|
@ -136,7 +154,7 @@ func TestCreateMultipleNetworks(t *testing.T) {
|
||||||
// Verify the network isolation rules are installed, each network subnet should appear 4 times
|
// Verify the network isolation rules are installed, each network subnet should appear 4 times
|
||||||
verifyV4INCEntries(dd.networks, 4, t)
|
verifyV4INCEntries(dd.networks, 4, t)
|
||||||
|
|
||||||
config4 := &networkConfiguration{BridgeName: "net_test_4", AllowNonDefaultBridge: true, EnableIPTables: true}
|
config4 := &networkConfiguration{BridgeName: "net_test_4", AllowNonDefaultBridge: true}
|
||||||
genericOption[netlabel.GenericData] = config4
|
genericOption[netlabel.GenericData] = config4
|
||||||
if err := d.CreateNetwork("4", genericOption); err != nil {
|
if err := d.CreateNetwork("4", genericOption); err != nil {
|
||||||
t.Fatalf("Failed to create bridge: %v", err)
|
t.Fatalf("Failed to create bridge: %v", err)
|
||||||
|
@ -278,15 +296,24 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
dd, _ := d.(*driver)
|
dd, _ := d.(*driver)
|
||||||
|
|
||||||
config := &networkConfiguration{
|
config := &configuration{
|
||||||
BridgeName: DefaultBridgeName,
|
|
||||||
EnableIPTables: true,
|
EnableIPTables: true,
|
||||||
EnableICC: false,
|
|
||||||
EnableUserlandProxy: ulPxyEnabled,
|
EnableUserlandProxy: ulPxyEnabled,
|
||||||
}
|
}
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
genericOption[netlabel.GenericData] = config
|
genericOption[netlabel.GenericData] = config
|
||||||
|
|
||||||
|
if err := d.Config(genericOption); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
netconfig := &networkConfiguration{
|
||||||
|
BridgeName: DefaultBridgeName,
|
||||||
|
EnableICC: false,
|
||||||
|
}
|
||||||
|
genericOption = make(map[string]interface{})
|
||||||
|
genericOption[netlabel.GenericData] = netconfig
|
||||||
|
|
||||||
err := d.CreateNetwork("net1", genericOption)
|
err := d.CreateNetwork("net1", genericOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create bridge: %v", err)
|
t.Fatalf("Failed to create bridge: %v", err)
|
||||||
|
@ -339,9 +366,13 @@ func TestCreateLinkWithOptions(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
config := &networkConfiguration{BridgeName: DefaultBridgeName}
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||||
netOptions := make(map[string]interface{})
|
netOptions := make(map[string]interface{})
|
||||||
netOptions[netlabel.GenericData] = config
|
netOptions[netlabel.GenericData] = netconfig
|
||||||
|
|
||||||
err := d.CreateNetwork("net1", netOptions)
|
err := d.CreateNetwork("net1", netOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -395,14 +426,23 @@ func TestLinkContainers(t *testing.T) {
|
||||||
|
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
config := &networkConfiguration{
|
config := &configuration{
|
||||||
BridgeName: DefaultBridgeName,
|
|
||||||
EnableIPTables: true,
|
EnableIPTables: true,
|
||||||
EnableICC: false,
|
|
||||||
}
|
}
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
genericOption[netlabel.GenericData] = config
|
genericOption[netlabel.GenericData] = config
|
||||||
|
|
||||||
|
if err := d.Config(genericOption); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
netconfig := &networkConfiguration{
|
||||||
|
BridgeName: DefaultBridgeName,
|
||||||
|
EnableICC: false,
|
||||||
|
}
|
||||||
|
genericOption = make(map[string]interface{})
|
||||||
|
genericOption[netlabel.GenericData] = netconfig
|
||||||
|
|
||||||
err := d.CreateNetwork("net1", genericOption)
|
err := d.CreateNetwork("net1", genericOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create bridge: %v", err)
|
t.Fatalf("Failed to create bridge: %v", err)
|
||||||
|
@ -602,6 +642,10 @@ func TestSetDefaultGw(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
_, subnetv6, _ := net.ParseCIDR("2001:db8:ea9:9abc:b0c4::/80")
|
_, subnetv6, _ := net.ParseCIDR("2001:db8:ea9:9abc:b0c4::/80")
|
||||||
gw4 := bridgeNetworks[0].IP.To4()
|
gw4 := bridgeNetworks[0].IP.To4()
|
||||||
gw4[3] = 254
|
gw4[3] = 254
|
||||||
|
|
|
@ -74,9 +74,9 @@ func linkContainers(action, parentIP, childIP string, ports []types.TransportPor
|
||||||
return InvalidLinkIPAddrError(childIP)
|
return InvalidLinkIPAddrError(childIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
chain := iptables.Chain{Name: DockerChain, Bridge: bridge}
|
chain := iptables.ChainInfo{Name: DockerChain}
|
||||||
for _, port := range ports {
|
for _, port := range ports {
|
||||||
err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String())
|
err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String(), bridge)
|
||||||
if !ignoreErrors && err != nil {
|
if !ignoreErrors && err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,10 @@ func TestLinkCreate(t *testing.T) {
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
dr := d.(*driver)
|
dr := d.(*driver)
|
||||||
|
|
||||||
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
mtu := 1490
|
mtu := 1490
|
||||||
config := &networkConfiguration{
|
config := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName,
|
BridgeName: DefaultBridgeName,
|
||||||
|
@ -108,6 +112,10 @@ func TestLinkCreateTwo(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
config := &networkConfiguration{
|
config := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName,
|
BridgeName: DefaultBridgeName,
|
||||||
EnableIPv6: true}
|
EnableIPv6: true}
|
||||||
|
@ -140,6 +148,10 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
config := &networkConfiguration{
|
config := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName}
|
BridgeName: DefaultBridgeName}
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
|
@ -170,6 +182,10 @@ func TestLinkDelete(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
|
if err := d.Config(nil); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
config := &networkConfiguration{
|
config := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName,
|
BridgeName: DefaultBridgeName,
|
||||||
EnableIPv6: true}
|
EnableIPv6: true}
|
||||||
|
|
|
@ -21,6 +21,16 @@ func TestPortMappingConfig(t *testing.T) {
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
d := newDriver()
|
d := newDriver()
|
||||||
|
|
||||||
|
config := &configuration{
|
||||||
|
EnableIPTables: true,
|
||||||
|
}
|
||||||
|
genericOption := make(map[string]interface{})
|
||||||
|
genericOption[netlabel.GenericData] = config
|
||||||
|
|
||||||
|
if err := d.Config(genericOption); err != nil {
|
||||||
|
t.Fatalf("Failed to setup driver config: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
binding1 := types.PortBinding{Proto: types.UDP, Port: uint16(400), HostPort: uint16(54000)}
|
binding1 := types.PortBinding{Proto: types.UDP, Port: uint16(400), HostPort: uint16(54000)}
|
||||||
binding2 := types.PortBinding{Proto: types.TCP, Port: uint16(500), HostPort: uint16(65000)}
|
binding2 := types.PortBinding{Proto: types.TCP, Port: uint16(500), HostPort: uint16(65000)}
|
||||||
portBindings := []types.PortBinding{binding1, binding2}
|
portBindings := []types.PortBinding{binding1, binding2}
|
||||||
|
@ -30,7 +40,6 @@ func TestPortMappingConfig(t *testing.T) {
|
||||||
|
|
||||||
netConfig := &networkConfiguration{
|
netConfig := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName,
|
BridgeName: DefaultBridgeName,
|
||||||
EnableIPTables: true,
|
|
||||||
}
|
}
|
||||||
netOptions := make(map[string]interface{})
|
netOptions := make(map[string]interface{})
|
||||||
netOptions[netlabel.GenericData] = netConfig
|
netOptions[netlabel.GenericData] = netConfig
|
||||||
|
|
|
@ -3,8 +3,13 @@ package bridge
|
||||||
import "github.com/docker/libnetwork/iptables"
|
import "github.com/docker/libnetwork/iptables"
|
||||||
|
|
||||||
func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeInterface) error {
|
func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
|
d := n.driver
|
||||||
|
d.Lock()
|
||||||
|
driverConfig := d.config
|
||||||
|
d.Unlock()
|
||||||
|
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if config.EnableIPTables == false {
|
if driverConfig.EnableIPTables == false {
|
||||||
return IPTableCfgError(config.BridgeName)
|
return IPTableCfgError(config.BridgeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libnetwork/iptables"
|
"github.com/docker/libnetwork/iptables"
|
||||||
"github.com/docker/libnetwork/netutils"
|
"github.com/docker/libnetwork/netutils"
|
||||||
)
|
)
|
||||||
|
@ -13,14 +14,48 @@ const (
|
||||||
DockerChain = "DOCKER"
|
DockerChain = "DOCKER"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
|
func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if config.EnableIPTables == false {
|
if config.EnableIPTables == false {
|
||||||
return IPTableCfgError(config.BridgeName)
|
return nil, nil, fmt.Errorf("Cannot create new chains, EnableIPTable is disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
hairpinMode := !config.EnableUserlandProxy
|
hairpinMode := !config.EnableUserlandProxy
|
||||||
|
|
||||||
|
natChain, err := iptables.NewChain(DockerChain, iptables.Nat, hairpinMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("Failed to create NAT chain: %s", err.Error())
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
if err := iptables.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
|
||||||
|
logrus.Warnf("Failed on removing iptables NAT chain on cleanup: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
filterChain, err := iptables.NewChain(DockerChain, iptables.Filter, hairpinMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return natChain, filterChain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
|
d := n.driver
|
||||||
|
d.Lock()
|
||||||
|
driverConfig := d.config
|
||||||
|
d.Unlock()
|
||||||
|
|
||||||
|
// Sanity check.
|
||||||
|
if driverConfig.EnableIPTables == false {
|
||||||
|
return fmt.Errorf("Cannot program chains, EnableIPTable is disabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup this configuraton option from driver
|
||||||
|
hairpinMode := !driverConfig.EnableUserlandProxy
|
||||||
|
|
||||||
addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
|
addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
|
return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
|
||||||
|
@ -34,17 +69,22 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt
|
||||||
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = iptables.NewChain(DockerChain, config.BridgeName, iptables.Nat, hairpinMode)
|
natChain, filterChain, err := n.getDriverChains()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to create NAT chain: %s", err.Error())
|
return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
chain, err := iptables.NewChain(DockerChain, config.BridgeName, iptables.Filter, hairpinMode)
|
err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
|
return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
n.portMapper.SetIptablesChain(chain)
|
err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,26 +37,32 @@ func TestProgramIPTable(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetupIPTables(t *testing.T) {
|
func TestSetupIPChains(t *testing.T) {
|
||||||
// Create a test bridge with a basic bridge configuration (name + IPv4).
|
// Create a test bridge with a basic bridge configuration (name + IPv4).
|
||||||
defer netutils.SetupTestNetNS(t)()
|
defer netutils.SetupTestNetNS(t)()
|
||||||
|
|
||||||
|
driverconfig := &configuration{
|
||||||
|
EnableIPTables: true,
|
||||||
|
}
|
||||||
|
d := &driver{
|
||||||
|
config: driverconfig,
|
||||||
|
}
|
||||||
|
assertChainConfig(d, t)
|
||||||
|
|
||||||
config := getBasicTestConfig()
|
config := getBasicTestConfig()
|
||||||
br := &bridgeInterface{}
|
br := &bridgeInterface{}
|
||||||
|
|
||||||
createTestBridge(config, br, t)
|
createTestBridge(config, br, t)
|
||||||
|
|
||||||
// Modify iptables params in base configuration and apply them.
|
assertBridgeConfig(config, br, d, t)
|
||||||
config.EnableIPTables = true
|
|
||||||
assertBridgeConfig(config, br, t)
|
|
||||||
|
|
||||||
config.EnableIPMasquerade = true
|
config.EnableIPMasquerade = true
|
||||||
assertBridgeConfig(config, br, t)
|
assertBridgeConfig(config, br, d, t)
|
||||||
|
|
||||||
config.EnableICC = true
|
config.EnableICC = true
|
||||||
assertBridgeConfig(config, br, t)
|
assertBridgeConfig(config, br, d, t)
|
||||||
|
|
||||||
config.EnableIPMasquerade = false
|
config.EnableIPMasquerade = false
|
||||||
assertBridgeConfig(config, br, t)
|
assertBridgeConfig(config, br, d, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBasicTestConfig() *networkConfiguration {
|
func getBasicTestConfig() *networkConfiguration {
|
||||||
|
@ -94,9 +100,22 @@ func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert function which create chains.
|
||||||
|
func assertChainConfig(d *driver, t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
d.natChain, d.filterChain, err = setupIPChains(d.config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Assert function which pushes chains based on bridge config parameters.
|
// Assert function which pushes chains based on bridge config parameters.
|
||||||
func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, t *testing.T) {
|
func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, d *driver, t *testing.T) {
|
||||||
nw := bridgeNetwork{portMapper: portmapper.New()}
|
nw := bridgeNetwork{portMapper: portmapper.New(),
|
||||||
|
config: config}
|
||||||
|
nw.driver = d
|
||||||
|
|
||||||
// Attempt programming of ip tables.
|
// Attempt programming of ip tables.
|
||||||
err := nw.setupIPTables(config, br)
|
err := nw.setupIPTables(config, br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -17,9 +17,12 @@ func TestFirewalldInit(t *testing.T) {
|
||||||
|
|
||||||
func TestReloaded(t *testing.T) {
|
func TestReloaded(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
var fwdChain *Chain
|
var fwdChain *ChainInfo
|
||||||
|
|
||||||
fwdChain, err = NewChain("FWD", "lo", Filter, false)
|
fwdChain, err = NewChain("FWD", Filter, false)
|
||||||
|
bridgeName := "lo"
|
||||||
|
|
||||||
|
err = ProgramChain(fwdChain, bridgeName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -31,17 +34,17 @@ func TestReloaded(t *testing.T) {
|
||||||
port := 1234
|
port := 1234
|
||||||
proto := "tcp"
|
proto := "tcp"
|
||||||
|
|
||||||
err = fwdChain.Link(Append, ip1, ip2, port, proto)
|
err = fwdChain.Link(Append, ip1, ip2, port, proto, bridgeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else {
|
} else {
|
||||||
// to be re-called again later
|
// to be re-called again later
|
||||||
OnReloaded(func() { fwdChain.Link(Append, ip1, ip2, port, proto) })
|
OnReloaded(func() { fwdChain.Link(Append, ip1, ip2, port, proto, bridgeName) })
|
||||||
}
|
}
|
||||||
|
|
||||||
rule1 := []string{
|
rule1 := []string{
|
||||||
"-i", fwdChain.Bridge,
|
"-i", bridgeName,
|
||||||
"-o", fwdChain.Bridge,
|
"-o", bridgeName,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"-s", ip1.String(),
|
"-s", ip1.String(),
|
||||||
"-d", ip2.String(),
|
"-d", ip2.String(),
|
||||||
|
|
|
@ -42,10 +42,9 @@ var (
|
||||||
ErrIptablesNotFound = errors.New("Iptables not found")
|
ErrIptablesNotFound = errors.New("Iptables not found")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Chain defines the iptables chain.
|
// ChainInfo defines the iptables chain.
|
||||||
type Chain struct {
|
type ChainInfo struct {
|
||||||
Name string
|
Name string
|
||||||
Bridge string
|
|
||||||
Table Table
|
Table Table
|
||||||
HairpinMode bool
|
HairpinMode bool
|
||||||
}
|
}
|
||||||
|
@ -74,14 +73,12 @@ func initCheck() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChain adds a new chain to ip table.
|
// NewChain adds a new chain to ip table.
|
||||||
func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error) {
|
func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
|
||||||
c := &Chain{
|
c := &ChainInfo{
|
||||||
Name: name,
|
Name: name,
|
||||||
Bridge: bridge,
|
|
||||||
Table: table,
|
Table: table,
|
||||||
HairpinMode: hairpinMode,
|
HairpinMode: hairpinMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(c.Table) == "" {
|
if string(c.Table) == "" {
|
||||||
c.Table = Filter
|
c.Table = Filter
|
||||||
}
|
}
|
||||||
|
@ -94,8 +91,16 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
|
||||||
return nil, fmt.Errorf("Could not create %s/%s chain: %s", c.Table, c.Name, output)
|
return nil, fmt.Errorf("Could not create %s/%s chain: %s", c.Table, c.Name, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
switch table {
|
// ProgramChain is used to add rules to a chain
|
||||||
|
func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode bool) error {
|
||||||
|
if c.Name == "" {
|
||||||
|
return fmt.Errorf("Could not program chain, missing chain name.")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c.Table {
|
||||||
case Nat:
|
case Nat:
|
||||||
preroute := []string{
|
preroute := []string{
|
||||||
"-m", "addrtype",
|
"-m", "addrtype",
|
||||||
|
@ -103,7 +108,7 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
|
||||||
"-j", c.Name}
|
"-j", c.Name}
|
||||||
if !Exists(Nat, "PREROUTING", preroute...) {
|
if !Exists(Nat, "PREROUTING", preroute...) {
|
||||||
if err := c.Prerouting(Append, preroute...); err != nil {
|
if err := c.Prerouting(Append, preroute...); err != nil {
|
||||||
return nil, fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
|
return fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output := []string{
|
output := []string{
|
||||||
|
@ -115,28 +120,32 @@ func NewChain(name, bridge string, table Table, hairpinMode bool) (*Chain, error
|
||||||
}
|
}
|
||||||
if !Exists(Nat, "OUTPUT", output...) {
|
if !Exists(Nat, "OUTPUT", output...) {
|
||||||
if err := c.Output(Append, output...); err != nil {
|
if err := c.Output(Append, output...); err != nil {
|
||||||
return nil, fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
|
return fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case Filter:
|
case Filter:
|
||||||
|
if bridgeName == "" {
|
||||||
|
return fmt.Errorf("Could not program chain %s/%s, missing bridge name.",
|
||||||
|
c.Table, c.Name)
|
||||||
|
}
|
||||||
link := []string{
|
link := []string{
|
||||||
"-o", c.Bridge,
|
"-o", bridgeName,
|
||||||
"-j", c.Name}
|
"-j", c.Name}
|
||||||
if !Exists(Filter, "FORWARD", link...) {
|
if !Exists(Filter, "FORWARD", link...) {
|
||||||
insert := append([]string{string(Insert), "FORWARD"}, link...)
|
insert := append([]string{string(Insert), "FORWARD"}, link...)
|
||||||
if output, err := Raw(insert...); err != nil {
|
if output, err := Raw(insert...); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
} else if len(output) != 0 {
|
} else if len(output) != 0 {
|
||||||
return nil, fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
|
return fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveExistingChain removes existing chain from the table.
|
// RemoveExistingChain removes existing chain from the table.
|
||||||
func RemoveExistingChain(name string, table Table) error {
|
func RemoveExistingChain(name string, table Table) error {
|
||||||
c := &Chain{
|
c := &ChainInfo{
|
||||||
Name: name,
|
Name: name,
|
||||||
Table: table,
|
Table: table,
|
||||||
}
|
}
|
||||||
|
@ -147,7 +156,7 @@ func RemoveExistingChain(name string, table Table) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward adds forwarding rule to 'filter' table and corresponding nat rule to 'nat' table.
|
// Forward adds forwarding rule to 'filter' table and corresponding nat rule to 'nat' table.
|
||||||
func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int) error {
|
func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int, bridgeName string) error {
|
||||||
daddr := ip.String()
|
daddr := ip.String()
|
||||||
if ip.IsUnspecified() {
|
if ip.IsUnspecified() {
|
||||||
// iptables interprets "0.0.0.0" as "0.0.0.0/32", whereas we
|
// iptables interprets "0.0.0.0" as "0.0.0.0/32", whereas we
|
||||||
|
@ -162,7 +171,7 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
|
||||||
"-j", "DNAT",
|
"-j", "DNAT",
|
||||||
"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
|
"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))}
|
||||||
if !c.HairpinMode {
|
if !c.HairpinMode {
|
||||||
args = append(args, "!", "-i", c.Bridge)
|
args = append(args, "!", "-i", bridgeName)
|
||||||
}
|
}
|
||||||
if output, err := Raw(args...); err != nil {
|
if output, err := Raw(args...); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -171,8 +180,8 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
|
||||||
}
|
}
|
||||||
|
|
||||||
if output, err := Raw("-t", string(Filter), string(action), c.Name,
|
if output, err := Raw("-t", string(Filter), string(action), c.Name,
|
||||||
"!", "-i", c.Bridge,
|
"!", "-i", bridgeName,
|
||||||
"-o", c.Bridge,
|
"-o", bridgeName,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"-d", destAddr,
|
"-d", destAddr,
|
||||||
"--dport", strconv.Itoa(destPort),
|
"--dport", strconv.Itoa(destPort),
|
||||||
|
@ -198,9 +207,9 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, destAddr stri
|
||||||
|
|
||||||
// Link adds reciprocal ACCEPT rule for two supplied IP addresses.
|
// Link adds reciprocal ACCEPT rule for two supplied IP addresses.
|
||||||
// Traffic is allowed from ip1 to ip2 and vice-versa
|
// Traffic is allowed from ip1 to ip2 and vice-versa
|
||||||
func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) error {
|
func (c *ChainInfo) Link(action Action, ip1, ip2 net.IP, port int, proto string, bridgeName string) error {
|
||||||
if output, err := Raw("-t", string(Filter), string(action), c.Name,
|
if output, err := Raw("-t", string(Filter), string(action), c.Name,
|
||||||
"-i", c.Bridge, "-o", c.Bridge,
|
"-i", bridgeName, "-o", bridgeName,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"-s", ip1.String(),
|
"-s", ip1.String(),
|
||||||
"-d", ip2.String(),
|
"-d", ip2.String(),
|
||||||
|
@ -211,7 +220,7 @@ func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) err
|
||||||
return fmt.Errorf("Error iptables forward: %s", output)
|
return fmt.Errorf("Error iptables forward: %s", output)
|
||||||
}
|
}
|
||||||
if output, err := Raw("-t", string(Filter), string(action), c.Name,
|
if output, err := Raw("-t", string(Filter), string(action), c.Name,
|
||||||
"-i", c.Bridge, "-o", c.Bridge,
|
"-i", bridgeName, "-o", bridgeName,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"-s", ip2.String(),
|
"-s", ip2.String(),
|
||||||
"-d", ip1.String(),
|
"-d", ip1.String(),
|
||||||
|
@ -225,7 +234,7 @@ func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prerouting adds linking rule to nat/PREROUTING chain.
|
// Prerouting adds linking rule to nat/PREROUTING chain.
|
||||||
func (c *Chain) Prerouting(action Action, args ...string) error {
|
func (c *ChainInfo) Prerouting(action Action, args ...string) error {
|
||||||
a := []string{"-t", string(Nat), string(action), "PREROUTING"}
|
a := []string{"-t", string(Nat), string(action), "PREROUTING"}
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
a = append(a, args...)
|
a = append(a, args...)
|
||||||
|
@ -239,7 +248,7 @@ func (c *Chain) Prerouting(action Action, args ...string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output adds linking rule to an OUTPUT chain.
|
// Output adds linking rule to an OUTPUT chain.
|
||||||
func (c *Chain) Output(action Action, args ...string) error {
|
func (c *ChainInfo) Output(action Action, args ...string) error {
|
||||||
a := []string{"-t", string(c.Table), string(action), "OUTPUT"}
|
a := []string{"-t", string(c.Table), string(action), "OUTPUT"}
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
a = append(a, args...)
|
a = append(a, args...)
|
||||||
|
@ -253,7 +262,7 @@ func (c *Chain) Output(action Action, args ...string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the chain.
|
// Remove removes the chain.
|
||||||
func (c *Chain) Remove() error {
|
func (c *ChainInfo) Remove() error {
|
||||||
// Ignore errors - This could mean the chains were never set up
|
// Ignore errors - This could mean the chains were never set up
|
||||||
if c.Table == Nat {
|
if c.Table == Nat {
|
||||||
c.Prerouting(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "-j", c.Name)
|
c.Prerouting(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "-j", c.Name)
|
||||||
|
|
|
@ -13,18 +13,22 @@ import (
|
||||||
|
|
||||||
const chainName = "DOCKEREST"
|
const chainName = "DOCKEREST"
|
||||||
|
|
||||||
var natChain *Chain
|
var natChain *ChainInfo
|
||||||
var filterChain *Chain
|
var filterChain *ChainInfo
|
||||||
|
var bridgeName string
|
||||||
|
|
||||||
func TestNewChain(t *testing.T) {
|
func TestNewChain(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
natChain, err = NewChain(chainName, "lo", Nat, false)
|
bridgeName = "lo"
|
||||||
|
natChain, err = NewChain(chainName, Nat, false)
|
||||||
|
err = ProgramChain(natChain, bridgeName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
filterChain, err = NewChain(chainName, "lo", Filter, false)
|
filterChain, err = NewChain(chainName, Filter, false)
|
||||||
|
err = ProgramChain(filterChain, bridgeName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +41,8 @@ func TestForward(t *testing.T) {
|
||||||
dstPort := 4321
|
dstPort := 4321
|
||||||
proto := "tcp"
|
proto := "tcp"
|
||||||
|
|
||||||
err := natChain.Forward(Insert, ip, port, proto, dstAddr, dstPort)
|
bridgeName := "lo"
|
||||||
|
err := natChain.Forward(Insert, ip, port, proto, dstAddr, dstPort, bridgeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -48,7 +53,7 @@ func TestForward(t *testing.T) {
|
||||||
"--dport", strconv.Itoa(port),
|
"--dport", strconv.Itoa(port),
|
||||||
"-j", "DNAT",
|
"-j", "DNAT",
|
||||||
"--to-destination", dstAddr + ":" + strconv.Itoa(dstPort),
|
"--to-destination", dstAddr + ":" + strconv.Itoa(dstPort),
|
||||||
"!", "-i", natChain.Bridge,
|
"!", "-i", bridgeName,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Exists(natChain.Table, natChain.Name, dnatRule...) {
|
if !Exists(natChain.Table, natChain.Name, dnatRule...) {
|
||||||
|
@ -56,8 +61,8 @@ func TestForward(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
filterRule := []string{
|
filterRule := []string{
|
||||||
"!", "-i", filterChain.Bridge,
|
"!", "-i", bridgeName,
|
||||||
"-o", filterChain.Bridge,
|
"-o", bridgeName,
|
||||||
"-d", dstAddr,
|
"-d", dstAddr,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"--dport", strconv.Itoa(dstPort),
|
"--dport", strconv.Itoa(dstPort),
|
||||||
|
@ -84,19 +89,20 @@ func TestForward(t *testing.T) {
|
||||||
func TestLink(t *testing.T) {
|
func TestLink(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
bridgeName := "lo"
|
||||||
ip1 := net.ParseIP("192.168.1.1")
|
ip1 := net.ParseIP("192.168.1.1")
|
||||||
ip2 := net.ParseIP("192.168.1.2")
|
ip2 := net.ParseIP("192.168.1.2")
|
||||||
port := 1234
|
port := 1234
|
||||||
proto := "tcp"
|
proto := "tcp"
|
||||||
|
|
||||||
err = filterChain.Link(Append, ip1, ip2, port, proto)
|
err = filterChain.Link(Append, ip1, ip2, port, proto, bridgeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rule1 := []string{
|
rule1 := []string{
|
||||||
"-i", filterChain.Bridge,
|
"-i", bridgeName,
|
||||||
"-o", filterChain.Bridge,
|
"-o", bridgeName,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"-s", ip1.String(),
|
"-s", ip1.String(),
|
||||||
"-d", ip2.String(),
|
"-d", ip2.String(),
|
||||||
|
@ -108,8 +114,8 @@ func TestLink(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rule2 := []string{
|
rule2 := []string{
|
||||||
"-i", filterChain.Bridge,
|
"-i", bridgeName,
|
||||||
"-o", filterChain.Bridge,
|
"-o", bridgeName,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"-s", ip2.String(),
|
"-s", ip2.String(),
|
||||||
"-d", ip1.String(),
|
"-d", ip1.String(),
|
||||||
|
@ -192,7 +198,7 @@ func RunConcurrencyTest(t *testing.T, allowXlock bool) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := natChain.Forward(Append, ip, port, proto, dstAddr, dstPort)
|
err := natChain.Forward(Append, ip, port, proto, dstAddr, dstPort, "lo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -208,7 +214,7 @@ func TestCleanup(t *testing.T) {
|
||||||
// Cleanup filter/FORWARD first otherwise output of iptables-save is dirty
|
// Cleanup filter/FORWARD first otherwise output of iptables-save is dirty
|
||||||
link := []string{"-t", string(filterChain.Table),
|
link := []string{"-t", string(filterChain.Table),
|
||||||
string(Delete), "FORWARD",
|
string(Delete), "FORWARD",
|
||||||
"-o", filterChain.Bridge,
|
"-o", bridgeName,
|
||||||
"-j", filterChain.Name}
|
"-j", filterChain.Name}
|
||||||
if _, err = Raw(link...); err != nil {
|
if _, err = Raw(link...); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -251,10 +251,9 @@ func TestBridge(t *testing.T) {
|
||||||
"FixedCIDR": cidr,
|
"FixedCIDR": cidr,
|
||||||
"FixedCIDRv6": cidrv6,
|
"FixedCIDRv6": cidrv6,
|
||||||
"EnableIPv6": true,
|
"EnableIPv6": true,
|
||||||
"EnableIPTables": true,
|
|
||||||
"EnableIPMasquerade": true,
|
|
||||||
"EnableICC": true,
|
"EnableICC": true,
|
||||||
"AllowNonDefaultBridge": true,
|
"AllowNonDefaultBridge": true,
|
||||||
|
"EnableIPMasquerade": true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@ var (
|
||||||
|
|
||||||
// PortMapper manages the network address translation
|
// PortMapper manages the network address translation
|
||||||
type PortMapper struct {
|
type PortMapper struct {
|
||||||
chain *iptables.Chain
|
chain *iptables.ChainInfo
|
||||||
|
bridgeName string
|
||||||
|
|
||||||
// udp:ip:port
|
// udp:ip:port
|
||||||
currentMappings map[string]*mapping
|
currentMappings map[string]*mapping
|
||||||
|
@ -54,8 +55,9 @@ func NewWithPortAllocator(allocator *portallocator.PortAllocator) *PortMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetIptablesChain sets the specified chain into portmapper
|
// SetIptablesChain sets the specified chain into portmapper
|
||||||
func (pm *PortMapper) SetIptablesChain(c *iptables.Chain) {
|
func (pm *PortMapper) SetIptablesChain(c *iptables.ChainInfo, bridgeName string) {
|
||||||
pm.chain = c
|
pm.chain = c
|
||||||
|
pm.bridgeName = bridgeName
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map maps the specified container transport address to the host's network address and transport port
|
// Map maps the specified container transport address to the host's network address and transport port
|
||||||
|
@ -215,5 +217,5 @@ func (pm *PortMapper) forward(action iptables.Action, proto string, sourceIP net
|
||||||
if pm.chain == nil {
|
if pm.chain == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort)
|
return pm.chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort, pm.bridgeName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,15 @@ func init() {
|
||||||
func TestSetIptablesChain(t *testing.T) {
|
func TestSetIptablesChain(t *testing.T) {
|
||||||
pm := New()
|
pm := New()
|
||||||
|
|
||||||
c := &iptables.Chain{
|
c := &iptables.ChainInfo{
|
||||||
Name: "TEST",
|
Name: "TEST",
|
||||||
Bridge: "192.168.1.1",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if pm.chain != nil {
|
if pm.chain != nil {
|
||||||
t.Fatal("chain should be nil at init")
|
t.Fatal("chain should be nil at init")
|
||||||
}
|
}
|
||||||
|
|
||||||
pm.SetIptablesChain(c)
|
pm.SetIptablesChain(c, "lo")
|
||||||
if pm.chain == nil {
|
if pm.chain == nil {
|
||||||
t.Fatal("chain should not be nil after set")
|
t.Fatal("chain should not be nil after set")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue