Bring in changes from https://github.com/moby/libnetwork/pull/2572 to moby
Signed-off-by: Arko Dasgupta <arko.dasgupta@docker.com>
| ... | ... |
@@ -3,7 +3,7 @@ |
| 3 | 3 |
# LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When |
| 4 | 4 |
# updating the binary version, consider updating github.com/docker/libnetwork |
| 5 | 5 |
# in vendor.conf accordingly |
| 6 |
-: "${LIBNETWORK_COMMIT:=d0951081b35fa4216fc4f0064bf065beeb55a74b}"
|
|
| 6 |
+: "${LIBNETWORK_COMMIT:=d511c60c5c23e6753631244f271a1ec6097254a5}"
|
|
| 7 | 7 |
|
| 8 | 8 |
install_proxy() {
|
| 9 | 9 |
case "$1" in |
| ... | ... |
@@ -40,7 +40,7 @@ github.com/grpc-ecosystem/go-grpc-middleware 3c51f7f332123e8be5a157c0802a |
| 40 | 40 |
# libnetwork |
| 41 | 41 |
|
| 42 | 42 |
# When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly |
| 43 |
-github.com/docker/libnetwork d0951081b35fa4216fc4f0064bf065beeb55a74b |
|
| 43 |
+github.com/docker/libnetwork d511c60c5c23e6753631244f271a1ec6097254a5 |
|
| 44 | 44 |
github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f |
| 45 | 45 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 46 | 46 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -57,6 +57,7 @@ type iptablesCleanFuncs []iptableCleanFunc |
| 57 | 57 |
type configuration struct {
|
| 58 | 58 |
EnableIPForwarding bool |
| 59 | 59 |
EnableIPTables bool |
| 60 |
+ EnableIP6Tables bool |
|
| 60 | 61 |
EnableUserlandProxy bool |
| 61 | 62 |
UserlandProxyPath string |
| 62 | 63 |
} |
| ... | ... |
@@ -133,22 +134,27 @@ type bridgeNetwork struct {
|
| 133 | 133 |
config *networkConfiguration |
| 134 | 134 |
endpoints map[string]*bridgeEndpoint // key: endpoint id |
| 135 | 135 |
portMapper *portmapper.PortMapper |
| 136 |
+ portMapperV6 *portmapper.PortMapper |
|
| 136 | 137 |
driver *driver // The network's driver |
| 137 | 138 |
iptCleanFuncs iptablesCleanFuncs |
| 138 | 139 |
sync.Mutex |
| 139 | 140 |
} |
| 140 | 141 |
|
| 141 | 142 |
type driver struct {
|
| 142 |
- config *configuration |
|
| 143 |
- network *bridgeNetwork |
|
| 144 |
- natChain *iptables.ChainInfo |
|
| 145 |
- filterChain *iptables.ChainInfo |
|
| 146 |
- isolationChain1 *iptables.ChainInfo |
|
| 147 |
- isolationChain2 *iptables.ChainInfo |
|
| 148 |
- networks map[string]*bridgeNetwork |
|
| 149 |
- store datastore.DataStore |
|
| 150 |
- nlh *netlink.Handle |
|
| 151 |
- configNetwork sync.Mutex |
|
| 143 |
+ config *configuration |
|
| 144 |
+ network *bridgeNetwork |
|
| 145 |
+ natChain *iptables.ChainInfo |
|
| 146 |
+ filterChain *iptables.ChainInfo |
|
| 147 |
+ isolationChain1 *iptables.ChainInfo |
|
| 148 |
+ isolationChain2 *iptables.ChainInfo |
|
| 149 |
+ natChainV6 *iptables.ChainInfo |
|
| 150 |
+ filterChainV6 *iptables.ChainInfo |
|
| 151 |
+ isolationChain1V6 *iptables.ChainInfo |
|
| 152 |
+ isolationChain2V6 *iptables.ChainInfo |
|
| 153 |
+ networks map[string]*bridgeNetwork |
|
| 154 |
+ store datastore.DataStore |
|
| 155 |
+ nlh *netlink.Handle |
|
| 156 |
+ configNetwork sync.Mutex |
|
| 152 | 157 |
sync.Mutex |
| 153 | 158 |
} |
| 154 | 159 |
|
| ... | ... |
@@ -277,7 +283,7 @@ func (n *bridgeNetwork) registerIptCleanFunc(clean iptableCleanFunc) {
|
| 277 | 277 |
n.iptCleanFuncs = append(n.iptCleanFuncs, clean) |
| 278 | 278 |
} |
| 279 | 279 |
|
| 280 |
-func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
|
| 280 |
+func (n *bridgeNetwork) getDriverChains(version iptables.IPVersion) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
|
| 281 | 281 |
n.Lock() |
| 282 | 282 |
defer n.Unlock() |
| 283 | 283 |
|
| ... | ... |
@@ -285,6 +291,10 @@ func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainI |
| 285 | 285 |
return nil, nil, nil, nil, types.BadRequestErrorf("no driver found")
|
| 286 | 286 |
} |
| 287 | 287 |
|
| 288 |
+ if version == iptables.IPv6 {
|
|
| 289 |
+ return n.driver.natChainV6, n.driver.filterChainV6, n.driver.isolationChain1V6, n.driver.isolationChain2V6, nil |
|
| 290 |
+ } |
|
| 291 |
+ |
|
| 288 | 292 |
return n.driver.natChain, n.driver.filterChain, n.driver.isolationChain1, n.driver.isolationChain2, nil |
| 289 | 293 |
} |
| 290 | 294 |
|
| ... | ... |
@@ -323,17 +333,31 @@ func (n *bridgeNetwork) isolateNetwork(others []*bridgeNetwork, enable bool) err |
| 323 | 323 |
} |
| 324 | 324 |
|
| 325 | 325 |
// Install the rules to isolate this network against each of the other networks |
| 326 |
- return setINC(thisConfig.BridgeName, enable) |
|
| 326 |
+ if n.driver.config.EnableIP6Tables {
|
|
| 327 |
+ err := setINC(iptables.IPv6, thisConfig.BridgeName, enable) |
|
| 328 |
+ if err != nil {
|
|
| 329 |
+ return err |
|
| 330 |
+ } |
|
| 331 |
+ } |
|
| 332 |
+ |
|
| 333 |
+ if n.driver.config.EnableIPTables {
|
|
| 334 |
+ return setINC(iptables.IPv4, thisConfig.BridgeName, enable) |
|
| 335 |
+ } |
|
| 336 |
+ return nil |
|
| 327 | 337 |
} |
| 328 | 338 |
|
| 329 | 339 |
func (d *driver) configure(option map[string]interface{}) error {
|
| 330 | 340 |
var ( |
| 331 |
- config *configuration |
|
| 332 |
- err error |
|
| 333 |
- natChain *iptables.ChainInfo |
|
| 334 |
- filterChain *iptables.ChainInfo |
|
| 335 |
- isolationChain1 *iptables.ChainInfo |
|
| 336 |
- isolationChain2 *iptables.ChainInfo |
|
| 341 |
+ config *configuration |
|
| 342 |
+ err error |
|
| 343 |
+ natChain *iptables.ChainInfo |
|
| 344 |
+ filterChain *iptables.ChainInfo |
|
| 345 |
+ isolationChain1 *iptables.ChainInfo |
|
| 346 |
+ isolationChain2 *iptables.ChainInfo |
|
| 347 |
+ natChainV6 *iptables.ChainInfo |
|
| 348 |
+ filterChainV6 *iptables.ChainInfo |
|
| 349 |
+ isolationChain1V6 *iptables.ChainInfo |
|
| 350 |
+ isolationChain2V6 *iptables.ChainInfo |
|
| 337 | 351 |
) |
| 338 | 352 |
|
| 339 | 353 |
genericData, ok := option[netlabel.GenericData] |
| ... | ... |
@@ -354,23 +378,46 @@ func (d *driver) configure(option map[string]interface{}) error {
|
| 354 | 354 |
return &ErrInvalidDriverConfig{}
|
| 355 | 355 |
} |
| 356 | 356 |
|
| 357 |
- if config.EnableIPTables {
|
|
| 357 |
+ if config.EnableIPTables || config.EnableIP6Tables {
|
|
| 358 | 358 |
if _, err := os.Stat("/proc/sys/net/bridge"); err != nil {
|
| 359 | 359 |
if out, err := exec.Command("modprobe", "-va", "bridge", "br_netfilter").CombinedOutput(); err != nil {
|
| 360 | 360 |
logrus.Warnf("Running modprobe bridge br_netfilter failed with message: %s, error: %v", out, err)
|
| 361 | 361 |
} |
| 362 | 362 |
} |
| 363 |
- removeIPChains() |
|
| 364 |
- natChain, filterChain, isolationChain1, isolationChain2, err = setupIPChains(config) |
|
| 363 |
+ } |
|
| 364 |
+ |
|
| 365 |
+ if config.EnableIPTables {
|
|
| 366 |
+ removeIPChains(iptables.IPv4) |
|
| 367 |
+ |
|
| 368 |
+ natChain, filterChain, isolationChain1, isolationChain2, err = setupIPChains(config, iptables.IPv4) |
|
| 369 |
+ if err != nil {
|
|
| 370 |
+ return err |
|
| 371 |
+ } |
|
| 372 |
+ |
|
| 373 |
+ // Make sure on firewall reload, first thing being re-played is chains creation |
|
| 374 |
+ iptables.OnReloaded(func() {
|
|
| 375 |
+ logrus.Debugf("Recreating iptables chains on firewall reload")
|
|
| 376 |
+ setupIPChains(config, iptables.IPv4) |
|
| 377 |
+ }) |
|
| 378 |
+ } |
|
| 379 |
+ |
|
| 380 |
+ if config.EnableIP6Tables {
|
|
| 381 |
+ removeIPChains(iptables.IPv6) |
|
| 382 |
+ |
|
| 383 |
+ natChainV6, filterChainV6, isolationChain1V6, isolationChain2V6, err = setupIPChains(config, iptables.IPv6) |
|
| 365 | 384 |
if err != nil {
|
| 366 | 385 |
return err |
| 367 | 386 |
} |
| 387 |
+ |
|
| 368 | 388 |
// Make sure on firewall reload, first thing being re-played is chains creation |
| 369 |
- iptables.OnReloaded(func() { logrus.Debugf("Recreating iptables chains on firewall reload"); setupIPChains(config) })
|
|
| 389 |
+ iptables.OnReloaded(func() {
|
|
| 390 |
+ logrus.Debugf("Recreating ip6tables chains on firewall reload")
|
|
| 391 |
+ setupIPChains(config, iptables.IPv6) |
|
| 392 |
+ }) |
|
| 370 | 393 |
} |
| 371 | 394 |
|
| 372 | 395 |
if config.EnableIPForwarding {
|
| 373 |
- err = setupIPForwarding(config.EnableIPTables) |
|
| 396 |
+ err = setupIPForwarding(config.EnableIPTables, config.EnableIP6Tables) |
|
| 374 | 397 |
if err != nil {
|
| 375 | 398 |
logrus.Warn(err) |
| 376 | 399 |
return err |
| ... | ... |
@@ -382,6 +429,10 @@ func (d *driver) configure(option map[string]interface{}) error {
|
| 382 | 382 |
d.filterChain = filterChain |
| 383 | 383 |
d.isolationChain1 = isolationChain1 |
| 384 | 384 |
d.isolationChain2 = isolationChain2 |
| 385 |
+ d.natChainV6 = natChainV6 |
|
| 386 |
+ d.filterChainV6 = filterChainV6 |
|
| 387 |
+ d.isolationChain1V6 = isolationChain1V6 |
|
| 388 |
+ d.isolationChain2V6 = isolationChain2V6 |
|
| 385 | 389 |
d.config = config |
| 386 | 390 |
d.Unlock() |
| 387 | 391 |
|
| ... | ... |
@@ -644,12 +695,13 @@ func (d *driver) createNetwork(config *networkConfiguration) (err error) {
|
| 644 | 644 |
|
| 645 | 645 |
// Create and set network handler in driver |
| 646 | 646 |
network := &bridgeNetwork{
|
| 647 |
- id: config.ID, |
|
| 648 |
- endpoints: make(map[string]*bridgeEndpoint), |
|
| 649 |
- config: config, |
|
| 650 |
- portMapper: portmapper.New(d.config.UserlandProxyPath), |
|
| 651 |
- bridge: bridgeIface, |
|
| 652 |
- driver: d, |
|
| 647 |
+ id: config.ID, |
|
| 648 |
+ endpoints: make(map[string]*bridgeEndpoint), |
|
| 649 |
+ config: config, |
|
| 650 |
+ portMapper: portmapper.New(d.config.UserlandProxyPath), |
|
| 651 |
+ portMapperV6: portmapper.New(d.config.UserlandProxyPath), |
|
| 652 |
+ bridge: bridgeIface, |
|
| 653 |
+ driver: d, |
|
| 653 | 654 |
} |
| 654 | 655 |
|
| 655 | 656 |
d.Lock() |
| ... | ... |
@@ -724,11 +776,16 @@ func (d *driver) createNetwork(config *networkConfiguration) (err error) {
|
| 724 | 724 |
{!d.config.EnableUserlandProxy, setupLoopbackAddressesRouting},
|
| 725 | 725 |
|
| 726 | 726 |
// Setup IPTables. |
| 727 |
- {d.config.EnableIPTables, network.setupIPTables},
|
|
| 727 |
+ {d.config.EnableIPTables, network.setupIP4Tables},
|
|
| 728 |
+ |
|
| 729 |
+ // Setup IP6Tables. |
|
| 730 |
+ {d.config.EnableIP6Tables, network.setupIP6Tables},
|
|
| 728 | 731 |
|
| 729 | 732 |
//We want to track firewalld configuration so that |
| 730 | 733 |
//if it is started/reloaded, the rules can be applied correctly |
| 731 | 734 |
{d.config.EnableIPTables, network.setupFirewalld},
|
| 735 |
+ // same for IPv6 |
|
| 736 |
+ {d.config.EnableIP6Tables, network.setupFirewalld6},
|
|
| 732 | 737 |
|
| 733 | 738 |
// Setup DefaultGatewayIPv4 |
| 734 | 739 |
{config.DefaultGatewayIPv4 != nil, setupGatewayIPv4},
|
| ... | ... |
@@ -12,7 +12,8 @@ import ( |
| 12 | 12 |
) |
| 13 | 13 |
|
| 14 | 14 |
var ( |
| 15 |
- defaultBindingIP = net.IPv4(0, 0, 0, 0) |
|
| 15 |
+ defaultBindingIP = net.IPv4(0, 0, 0, 0) |
|
| 16 |
+ defaultBindingIPV6 = net.ParseIP("::")
|
|
| 16 | 17 |
) |
| 17 | 18 |
|
| 18 | 19 |
func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
| ... | ... |
@@ -25,7 +26,25 @@ func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, reqDefBindIP net.IP, u |
| 25 | 25 |
defHostIP = reqDefBindIP |
| 26 | 26 |
} |
| 27 | 27 |
|
| 28 |
- return n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled) |
|
| 28 |
+ // IPv4 port binding including user land proxy |
|
| 29 |
+ pb, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled) |
|
| 30 |
+ if err != nil {
|
|
| 31 |
+ return nil, err |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ // IPv6 port binding excluding user land proxy |
|
| 35 |
+ if n.driver.config.EnableIP6Tables && ep.addrv6 != nil {
|
|
| 36 |
+ // TODO IPv6 custom default binding IP |
|
| 37 |
+ pbv6, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addrv6.IP, defaultBindingIPV6, false) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ // ensure we clear the previous allocated IPv4 ports |
|
| 40 |
+ n.releasePortsInternal(pb) |
|
| 41 |
+ return nil, err |
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ pb = append(pb, pbv6...) |
|
| 45 |
+ } |
|
| 46 |
+ return pb, nil |
|
| 29 | 47 |
} |
| 30 | 48 |
|
| 31 | 49 |
func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
| ... | ... |
@@ -69,9 +88,15 @@ func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHos |
| 69 | 69 |
return err |
| 70 | 70 |
} |
| 71 | 71 |
|
| 72 |
+ portmapper := n.portMapper |
|
| 73 |
+ |
|
| 74 |
+ if containerIP.To4() == nil {
|
|
| 75 |
+ portmapper = n.portMapperV6 |
|
| 76 |
+ } |
|
| 77 |
+ |
|
| 72 | 78 |
// Try up to maxAllocatePortAttempts times to get a port that's not already allocated. |
| 73 | 79 |
for i := 0; i < maxAllocatePortAttempts; i++ {
|
| 74 |
- if host, err = n.portMapper.MapRange(container, bnd.HostIP, int(bnd.HostPort), int(bnd.HostPortEnd), ulPxyEnabled); err == nil {
|
|
| 80 |
+ if host, err = portmapper.MapRange(container, bnd.HostIP, int(bnd.HostPort), int(bnd.HostPortEnd), ulPxyEnabled); err == nil {
|
|
| 75 | 81 |
break |
| 76 | 82 |
} |
| 77 | 83 |
// There is no point in immediately retrying to map an explicitly chosen port. |
| ... | ... |
@@ -128,5 +153,12 @@ func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
|
| 128 | 128 |
if err != nil {
|
| 129 | 129 |
return err |
| 130 | 130 |
} |
| 131 |
- return n.portMapper.Unmap(host) |
|
| 131 |
+ |
|
| 132 |
+ portmapper := n.portMapper |
|
| 133 |
+ |
|
| 134 |
+ if bnd.HostIP.To4() == nil {
|
|
| 135 |
+ portmapper = n.portMapperV6 |
|
| 136 |
+ } |
|
| 137 |
+ |
|
| 138 |
+ return portmapper.Unmap(host) |
|
| 132 | 139 |
} |
| ... | ... |
@@ -13,8 +13,23 @@ func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeIn |
| 13 | 13 |
return IPTableCfgError(config.BridgeName) |
| 14 | 14 |
} |
| 15 | 15 |
|
| 16 |
- iptables.OnReloaded(func() { n.setupIPTables(config, i) })
|
|
| 16 |
+ iptables.OnReloaded(func() { n.setupIP4Tables(config, i) })
|
|
| 17 | 17 |
iptables.OnReloaded(n.portMapper.ReMapAll) |
| 18 |
+ return nil |
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+func (n *bridgeNetwork) setupFirewalld6(config *networkConfiguration, i *bridgeInterface) error {
|
|
| 22 |
+ d := n.driver |
|
| 23 |
+ d.Lock() |
|
| 24 |
+ driverConfig := d.config |
|
| 25 |
+ d.Unlock() |
|
| 26 |
+ |
|
| 27 |
+ // Sanity check. |
|
| 28 |
+ if !driverConfig.EnableIP6Tables {
|
|
| 29 |
+ return IPTableCfgError(config.BridgeName) |
|
| 30 |
+ } |
|
| 18 | 31 |
|
| 32 |
+ iptables.OnReloaded(func() { n.setupIP6Tables(config, i) })
|
|
| 33 |
+ iptables.OnReloaded(n.portMapperV6.ReMapAll) |
|
| 19 | 34 |
return nil |
| 20 | 35 |
} |
| ... | ... |
@@ -21,7 +21,7 @@ func configureIPForwarding(enable bool) error {
|
| 21 | 21 |
return ioutil.WriteFile(ipv4ForwardConf, []byte{val, '\n'}, ipv4ForwardConfPerm)
|
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 |
-func setupIPForwarding(enableIPTables bool) error {
|
|
| 24 |
+func setupIPForwarding(enableIPTables bool, enableIP6Tables bool) error {
|
|
| 25 | 25 |
// Get current IPv4 forward setup |
| 26 | 26 |
ipv4ForwardData, err := ioutil.ReadFile(ipv4ForwardConf) |
| 27 | 27 |
if err != nil {
|
| ... | ... |
@@ -36,21 +36,36 @@ func setupIPForwarding(enableIPTables bool) error {
|
| 36 | 36 |
} |
| 37 | 37 |
// When enabling ip_forward set the default policy on forward chain to |
| 38 | 38 |
// drop only if the daemon option iptables is not set to false. |
| 39 |
- if !enableIPTables {
|
|
| 40 |
- return nil |
|
| 41 |
- } |
|
| 42 |
- if err := iptables.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
|
| 43 |
- if err := configureIPForwarding(false); err != nil {
|
|
| 44 |
- logrus.Errorf("Disabling IP forwarding failed, %v", err)
|
|
| 39 |
+ if enableIPTables {
|
|
| 40 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 41 |
+ if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
|
| 42 |
+ if err := configureIPForwarding(false); err != nil {
|
|
| 43 |
+ logrus.Errorf("Disabling IP forwarding failed, %v", err)
|
|
| 44 |
+ } |
|
| 45 |
+ return err |
|
| 45 | 46 |
} |
| 46 |
- return err |
|
| 47 |
+ iptables.OnReloaded(func() {
|
|
| 48 |
+ logrus.Debug("Setting the default DROP policy on firewall reload")
|
|
| 49 |
+ if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
|
| 50 |
+ logrus.Warnf("Setting the default DROP policy on firewall reload failed, %v", err)
|
|
| 51 |
+ } |
|
| 52 |
+ }) |
|
| 53 |
+ } |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ // add only iptables rules - forwarding is handled by setupIPv6Forwarding in setup_ipv6 |
|
| 57 |
+ if enableIP6Tables {
|
|
| 58 |
+ iptable := iptables.GetIptable(iptables.IPv6) |
|
| 59 |
+ if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
|
| 60 |
+ logrus.Warnf("Setting the default DROP policy on firewall reload failed, %v", err)
|
|
| 47 | 61 |
} |
| 48 | 62 |
iptables.OnReloaded(func() {
|
| 49 | 63 |
logrus.Debug("Setting the default DROP policy on firewall reload")
|
| 50 |
- if err := iptables.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
|
| 64 |
+ if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
|
| 51 | 65 |
logrus.Warnf("Setting the default DROP policy on firewall reload failed, %v", err)
|
| 52 | 66 |
} |
| 53 | 67 |
}) |
| 54 | 68 |
} |
| 69 |
+ |
|
| 55 | 70 |
return nil |
| 56 | 71 |
} |
| ... | ... |
@@ -26,7 +26,7 @@ const ( |
| 26 | 26 |
IsolationChain2 = "DOCKER-ISOLATION-STAGE-2" |
| 27 | 27 |
) |
| 28 | 28 |
|
| 29 |
-func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
|
| 29 |
+func setupIPChains(config *configuration, version iptables.IPVersion) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
|
| 30 | 30 |
// Sanity check. |
| 31 | 31 |
if config.EnableIPTables == false {
|
| 32 | 32 |
return nil, nil, nil, nil, errors.New("cannot create new chains, EnableIPTable is disabled")
|
| ... | ... |
@@ -34,129 +34,157 @@ func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainI |
| 34 | 34 |
|
| 35 | 35 |
hairpinMode := !config.EnableUserlandProxy |
| 36 | 36 |
|
| 37 |
- natChain, err := iptables.NewChain(DockerChain, iptables.Nat, hairpinMode) |
|
| 37 |
+ iptable := iptables.GetIptable(version) |
|
| 38 |
+ |
|
| 39 |
+ natChain, err := iptable.NewChain(DockerChain, iptables.Nat, hairpinMode) |
|
| 38 | 40 |
if err != nil {
|
| 39 | 41 |
return nil, nil, nil, nil, fmt.Errorf("failed to create NAT chain %s: %v", DockerChain, err)
|
| 40 | 42 |
} |
| 41 | 43 |
defer func() {
|
| 42 | 44 |
if err != nil {
|
| 43 |
- if err := iptables.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
|
|
| 45 |
+ if err := iptable.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
|
|
| 44 | 46 |
logrus.Warnf("failed on removing iptables NAT chain %s on cleanup: %v", DockerChain, err)
|
| 45 | 47 |
} |
| 46 | 48 |
} |
| 47 | 49 |
}() |
| 48 | 50 |
|
| 49 |
- filterChain, err := iptables.NewChain(DockerChain, iptables.Filter, false) |
|
| 51 |
+ filterChain, err := iptable.NewChain(DockerChain, iptables.Filter, false) |
|
| 50 | 52 |
if err != nil {
|
| 51 | 53 |
return nil, nil, nil, nil, fmt.Errorf("failed to create FILTER chain %s: %v", DockerChain, err)
|
| 52 | 54 |
} |
| 53 | 55 |
defer func() {
|
| 54 | 56 |
if err != nil {
|
| 55 |
- if err := iptables.RemoveExistingChain(DockerChain, iptables.Filter); err != nil {
|
|
| 57 |
+ if err := iptable.RemoveExistingChain(DockerChain, iptables.Filter); err != nil {
|
|
| 56 | 58 |
logrus.Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", DockerChain, err)
|
| 57 | 59 |
} |
| 58 | 60 |
} |
| 59 | 61 |
}() |
| 60 | 62 |
|
| 61 |
- isolationChain1, err := iptables.NewChain(IsolationChain1, iptables.Filter, false) |
|
| 63 |
+ isolationChain1, err := iptable.NewChain(IsolationChain1, iptables.Filter, false) |
|
| 62 | 64 |
if err != nil {
|
| 63 | 65 |
return nil, nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err)
|
| 64 | 66 |
} |
| 65 | 67 |
defer func() {
|
| 66 | 68 |
if err != nil {
|
| 67 |
- if err := iptables.RemoveExistingChain(IsolationChain1, iptables.Filter); err != nil {
|
|
| 69 |
+ if err := iptable.RemoveExistingChain(IsolationChain1, iptables.Filter); err != nil {
|
|
| 68 | 70 |
logrus.Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", IsolationChain1, err)
|
| 69 | 71 |
} |
| 70 | 72 |
} |
| 71 | 73 |
}() |
| 72 | 74 |
|
| 73 |
- isolationChain2, err := iptables.NewChain(IsolationChain2, iptables.Filter, false) |
|
| 75 |
+ isolationChain2, err := iptable.NewChain(IsolationChain2, iptables.Filter, false) |
|
| 74 | 76 |
if err != nil {
|
| 75 | 77 |
return nil, nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err)
|
| 76 | 78 |
} |
| 77 | 79 |
defer func() {
|
| 78 | 80 |
if err != nil {
|
| 79 |
- if err := iptables.RemoveExistingChain(IsolationChain2, iptables.Filter); err != nil {
|
|
| 81 |
+ if err := iptable.RemoveExistingChain(IsolationChain2, iptables.Filter); err != nil {
|
|
| 80 | 82 |
logrus.Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", IsolationChain2, err)
|
| 81 | 83 |
} |
| 82 | 84 |
} |
| 83 | 85 |
}() |
| 84 | 86 |
|
| 85 |
- if err := iptables.AddReturnRule(IsolationChain1); err != nil {
|
|
| 87 |
+ if err := iptable.AddReturnRule(IsolationChain1); err != nil {
|
|
| 86 | 88 |
return nil, nil, nil, nil, err |
| 87 | 89 |
} |
| 88 | 90 |
|
| 89 |
- if err := iptables.AddReturnRule(IsolationChain2); err != nil {
|
|
| 91 |
+ if err := iptable.AddReturnRule(IsolationChain2); err != nil {
|
|
| 90 | 92 |
return nil, nil, nil, nil, err |
| 91 | 93 |
} |
| 92 | 94 |
|
| 93 | 95 |
return natChain, filterChain, isolationChain1, isolationChain2, nil |
| 94 | 96 |
} |
| 95 | 97 |
|
| 96 |
-func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
|
|
| 97 |
- var err error |
|
| 98 |
- |
|
| 98 |
+func (n *bridgeNetwork) setupIP4Tables(config *networkConfiguration, i *bridgeInterface) error {
|
|
| 99 | 99 |
d := n.driver |
| 100 | 100 |
d.Lock() |
| 101 | 101 |
driverConfig := d.config |
| 102 | 102 |
d.Unlock() |
| 103 | 103 |
|
| 104 | 104 |
// Sanity check. |
| 105 |
- if driverConfig.EnableIPTables == false {
|
|
| 105 |
+ if !driverConfig.EnableIPTables {
|
|
| 106 | 106 |
return errors.New("Cannot program chains, EnableIPTable is disabled")
|
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 |
- // Pickup this configuration option from driver |
|
| 110 |
- hairpinMode := !driverConfig.EnableUserlandProxy |
|
| 111 |
- |
|
| 112 | 109 |
maskedAddrv4 := &net.IPNet{
|
| 113 | 110 |
IP: i.bridgeIPv4.IP.Mask(i.bridgeIPv4.Mask), |
| 114 | 111 |
Mask: i.bridgeIPv4.Mask, |
| 115 | 112 |
} |
| 113 |
+ return n.setupIPTables(iptables.IPv4, maskedAddrv4, config, i) |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+func (n *bridgeNetwork) setupIP6Tables(config *networkConfiguration, i *bridgeInterface) error {
|
|
| 117 |
+ d := n.driver |
|
| 118 |
+ d.Lock() |
|
| 119 |
+ driverConfig := d.config |
|
| 120 |
+ d.Unlock() |
|
| 121 |
+ |
|
| 122 |
+ // Sanity check. |
|
| 123 |
+ if !driverConfig.EnableIP6Tables {
|
|
| 124 |
+ return errors.New("Cannot program chains, EnableIP6Tables is disabled")
|
|
| 125 |
+ } |
|
| 126 |
+ |
|
| 127 |
+ maskedAddrv6 := &net.IPNet{
|
|
| 128 |
+ IP: i.bridgeIPv6.IP.Mask(i.bridgeIPv6.Mask), |
|
| 129 |
+ Mask: i.bridgeIPv6.Mask, |
|
| 130 |
+ } |
|
| 131 |
+ |
|
| 132 |
+ return n.setupIPTables(iptables.IPv6, maskedAddrv6, config, i) |
|
| 133 |
+} |
|
| 134 |
+ |
|
| 135 |
+func (n *bridgeNetwork) setupIPTables(ipVersion iptables.IPVersion, maskedAddr *net.IPNet, config *networkConfiguration, i *bridgeInterface) error {
|
|
| 136 |
+ var err error |
|
| 137 |
+ |
|
| 138 |
+ d := n.driver |
|
| 139 |
+ d.Lock() |
|
| 140 |
+ driverConfig := d.config |
|
| 141 |
+ d.Unlock() |
|
| 142 |
+ |
|
| 143 |
+ // Pickup this configuration option from driver |
|
| 144 |
+ hairpinMode := !driverConfig.EnableUserlandProxy |
|
| 145 |
+ |
|
| 146 |
+ iptable := iptables.GetIptable(ipVersion) |
|
| 147 |
+ |
|
| 116 | 148 |
if config.Internal {
|
| 117 |
- if err = setupInternalNetworkRules(config.BridgeName, maskedAddrv4, config.EnableICC, true); err != nil {
|
|
| 149 |
+ if err = setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, true); err != nil {
|
|
| 118 | 150 |
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
| 119 | 151 |
} |
| 120 | 152 |
n.registerIptCleanFunc(func() error {
|
| 121 |
- return setupInternalNetworkRules(config.BridgeName, maskedAddrv4, config.EnableICC, false) |
|
| 153 |
+ return setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, false) |
|
| 122 | 154 |
}) |
| 123 | 155 |
} else {
|
| 124 |
- if err = setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
|
|
| 156 |
+ if err = setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
|
|
| 125 | 157 |
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
| 126 | 158 |
} |
| 127 | 159 |
n.registerIptCleanFunc(func() error {
|
| 128 |
- return setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false) |
|
| 160 |
+ return setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false) |
|
| 129 | 161 |
}) |
| 130 |
- natChain, filterChain, _, _, err := n.getDriverChains() |
|
| 162 |
+ natChain, filterChain, _, _, err := n.getDriverChains(ipVersion) |
|
| 131 | 163 |
if err != nil {
|
| 132 | 164 |
return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
|
| 133 | 165 |
} |
| 134 | 166 |
|
| 135 |
- err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode, true) |
|
| 167 |
+ err = iptable.ProgramChain(natChain, config.BridgeName, hairpinMode, true) |
|
| 136 | 168 |
if err != nil {
|
| 137 | 169 |
return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
|
| 138 | 170 |
} |
| 139 | 171 |
|
| 140 |
- err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, true) |
|
| 172 |
+ err = iptable.ProgramChain(filterChain, config.BridgeName, hairpinMode, true) |
|
| 141 | 173 |
if err != nil {
|
| 142 | 174 |
return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
|
| 143 | 175 |
} |
| 144 | 176 |
|
| 145 | 177 |
n.registerIptCleanFunc(func() error {
|
| 146 |
- return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false) |
|
| 178 |
+ return iptable.ProgramChain(filterChain, config.BridgeName, hairpinMode, false) |
|
| 147 | 179 |
}) |
| 148 | 180 |
|
| 149 | 181 |
n.portMapper.SetIptablesChain(natChain, n.getNetworkBridgeName()) |
| 150 | 182 |
} |
| 151 | 183 |
|
| 152 | 184 |
d.Lock() |
| 153 |
- err = iptables.EnsureJumpRule("FORWARD", IsolationChain1)
|
|
| 185 |
+ err = iptable.EnsureJumpRule("FORWARD", IsolationChain1)
|
|
| 154 | 186 |
d.Unlock() |
| 155 |
- if err != nil {
|
|
| 156 |
- return err |
|
| 157 |
- } |
|
| 158 |
- |
|
| 159 |
- return nil |
|
| 187 |
+ return err |
|
| 160 | 188 |
} |
| 161 | 189 |
|
| 162 | 190 |
type iptRule struct {
|
| ... | ... |
@@ -166,7 +194,7 @@ type iptRule struct {
|
| 166 | 166 |
args []string |
| 167 | 167 |
} |
| 168 | 168 |
|
| 169 |
-func setupIPTablesInternal(hostIP net.IP, bridgeIface string, addr net.Addr, icc, ipmasq, hairpin, enable bool) error {
|
|
| 169 |
+func setupIPTablesInternal(hostIP net.IP, bridgeIface string, addr *net.IPNet, icc, ipmasq, hairpin, enable bool) error {
|
|
| 170 | 170 |
|
| 171 | 171 |
var ( |
| 172 | 172 |
address = addr.String() |
| ... | ... |
@@ -189,41 +217,50 @@ func setupIPTablesInternal(hostIP net.IP, bridgeIface string, addr net.Addr, icc |
| 189 | 189 |
natRule := iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: natArgs}
|
| 190 | 190 |
hpNatRule := iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: hpNatArgs}
|
| 191 | 191 |
|
| 192 |
+ ipVersion := iptables.IPv4 |
|
| 193 |
+ |
|
| 194 |
+ if addr.IP.To4() == nil {
|
|
| 195 |
+ ipVersion = iptables.IPv6 |
|
| 196 |
+ } |
|
| 197 |
+ |
|
| 192 | 198 |
// Set NAT. |
| 193 | 199 |
if ipmasq {
|
| 194 |
- if err := programChainRule(natRule, "NAT", enable); err != nil {
|
|
| 200 |
+ if err := programChainRule(ipVersion, natRule, "NAT", enable); err != nil {
|
|
| 195 | 201 |
return err |
| 196 | 202 |
} |
| 197 | 203 |
} |
| 198 | 204 |
|
| 199 | 205 |
if ipmasq && !hairpin {
|
| 200 |
- if err := programChainRule(skipDNAT, "SKIP DNAT", enable); err != nil {
|
|
| 206 |
+ if err := programChainRule(ipVersion, skipDNAT, "SKIP DNAT", enable); err != nil {
|
|
| 201 | 207 |
return err |
| 202 | 208 |
} |
| 203 | 209 |
} |
| 204 | 210 |
|
| 205 | 211 |
// In hairpin mode, masquerade traffic from localhost |
| 206 | 212 |
if hairpin {
|
| 207 |
- if err := programChainRule(hpNatRule, "MASQ LOCAL HOST", enable); err != nil {
|
|
| 213 |
+ if err := programChainRule(ipVersion, hpNatRule, "MASQ LOCAL HOST", enable); err != nil {
|
|
| 208 | 214 |
return err |
| 209 | 215 |
} |
| 210 | 216 |
} |
| 211 | 217 |
|
| 212 | 218 |
// Set Inter Container Communication. |
| 213 |
- if err := setIcc(bridgeIface, icc, enable); err != nil {
|
|
| 219 |
+ if err := setIcc(ipVersion, bridgeIface, icc, enable); err != nil {
|
|
| 214 | 220 |
return err |
| 215 | 221 |
} |
| 216 | 222 |
|
| 217 | 223 |
// Set Accept on all non-intercontainer outgoing packets. |
| 218 |
- return programChainRule(outRule, "ACCEPT NON_ICC OUTGOING", enable) |
|
| 224 |
+ return programChainRule(ipVersion, outRule, "ACCEPT NON_ICC OUTGOING", enable) |
|
| 219 | 225 |
} |
| 220 | 226 |
|
| 221 |
-func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
|
|
| 227 |
+func programChainRule(version iptables.IPVersion, rule iptRule, ruleDescr string, insert bool) error {
|
|
| 228 |
+ |
|
| 229 |
+ iptable := iptables.GetIptable(version) |
|
| 230 |
+ |
|
| 222 | 231 |
var ( |
| 223 | 232 |
prefix []string |
| 224 | 233 |
operation string |
| 225 | 234 |
condition bool |
| 226 |
- doesExist = iptables.Exists(rule.table, rule.chain, rule.args...) |
|
| 235 |
+ doesExist = iptable.Exists(rule.table, rule.chain, rule.args...) |
|
| 227 | 236 |
) |
| 228 | 237 |
|
| 229 | 238 |
if insert {
|
| ... | ... |
@@ -240,7 +277,7 @@ func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
|
| 240 | 240 |
} |
| 241 | 241 |
|
| 242 | 242 |
if condition {
|
| 243 |
- if err := iptables.RawCombinedOutput(append(prefix, rule.args...)...); err != nil {
|
|
| 243 |
+ if err := iptable.RawCombinedOutput(append(prefix, rule.args...)...); err != nil {
|
|
| 244 | 244 |
return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
|
| 245 | 245 |
} |
| 246 | 246 |
} |
| ... | ... |
@@ -248,7 +285,8 @@ func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
|
| 248 | 248 |
return nil |
| 249 | 249 |
} |
| 250 | 250 |
|
| 251 |
-func setIcc(bridgeIface string, iccEnable, insert bool) error {
|
|
| 251 |
+func setIcc(version iptables.IPVersion, bridgeIface string, iccEnable, insert bool) error {
|
|
| 252 |
+ iptable := iptables.GetIptable(version) |
|
| 252 | 253 |
var ( |
| 253 | 254 |
table = iptables.Filter |
| 254 | 255 |
chain = "FORWARD" |
| ... | ... |
@@ -259,18 +297,18 @@ func setIcc(bridgeIface string, iccEnable, insert bool) error {
|
| 259 | 259 |
|
| 260 | 260 |
if insert {
|
| 261 | 261 |
if !iccEnable {
|
| 262 |
- iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
|
| 262 |
+ iptable.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
|
| 263 | 263 |
|
| 264 |
- if !iptables.Exists(table, chain, dropArgs...) {
|
|
| 265 |
- if err := iptables.RawCombinedOutput(append([]string{"-A", chain}, dropArgs...)...); err != nil {
|
|
| 264 |
+ if !iptable.Exists(table, chain, dropArgs...) {
|
|
| 265 |
+ if err := iptable.RawCombinedOutput(append([]string{"-A", chain}, dropArgs...)...); err != nil {
|
|
| 266 | 266 |
return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
|
| 267 | 267 |
} |
| 268 | 268 |
} |
| 269 | 269 |
} else {
|
| 270 |
- iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
|
| 270 |
+ iptable.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
|
| 271 | 271 |
|
| 272 |
- if !iptables.Exists(table, chain, acceptArgs...) {
|
|
| 273 |
- if err := iptables.RawCombinedOutput(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
|
|
| 272 |
+ if !iptable.Exists(table, chain, acceptArgs...) {
|
|
| 273 |
+ if err := iptable.RawCombinedOutput(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
|
|
| 274 | 274 |
return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
|
| 275 | 275 |
} |
| 276 | 276 |
} |
| ... | ... |
@@ -278,12 +316,12 @@ func setIcc(bridgeIface string, iccEnable, insert bool) error {
|
| 278 | 278 |
} else {
|
| 279 | 279 |
// Remove any ICC rule. |
| 280 | 280 |
if !iccEnable {
|
| 281 |
- if iptables.Exists(table, chain, dropArgs...) {
|
|
| 282 |
- iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
|
| 281 |
+ if iptable.Exists(table, chain, dropArgs...) {
|
|
| 282 |
+ iptable.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
|
| 283 | 283 |
} |
| 284 | 284 |
} else {
|
| 285 |
- if iptables.Exists(table, chain, acceptArgs...) {
|
|
| 286 |
- iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
|
| 285 |
+ if iptable.Exists(table, chain, acceptArgs...) {
|
|
| 286 |
+ iptable.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
|
| 287 | 287 |
} |
| 288 | 288 |
} |
| 289 | 289 |
} |
| ... | ... |
@@ -292,7 +330,8 @@ func setIcc(bridgeIface string, iccEnable, insert bool) error {
|
| 292 | 292 |
} |
| 293 | 293 |
|
| 294 | 294 |
// Control Inter Network Communication. Install[Remove] only if it is [not] present. |
| 295 |
-func setINC(iface string, enable bool) error {
|
|
| 295 |
+func setINC(version iptables.IPVersion, iface string, enable bool) error {
|
|
| 296 |
+ iptable := iptables.GetIptable(version) |
|
| 296 | 297 |
var ( |
| 297 | 298 |
action = iptables.Insert |
| 298 | 299 |
actionMsg = "add" |
| ... | ... |
@@ -309,12 +348,12 @@ func setINC(iface string, enable bool) error {
|
| 309 | 309 |
} |
| 310 | 310 |
|
| 311 | 311 |
for i, chain := range chains {
|
| 312 |
- if err := iptables.ProgramRule(iptables.Filter, chain, action, rules[i]); err != nil {
|
|
| 312 |
+ if err := iptable.ProgramRule(iptables.Filter, chain, action, rules[i]); err != nil {
|
|
| 313 | 313 |
msg := fmt.Sprintf("unable to %s inter-network communication rule: %v", actionMsg, err)
|
| 314 | 314 |
if enable {
|
| 315 | 315 |
if i == 1 {
|
| 316 | 316 |
// Rollback the rule installed on first chain |
| 317 |
- if err2 := iptables.ProgramRule(iptables.Filter, chains[0], iptables.Delete, rules[0]); err2 != nil {
|
|
| 317 |
+ if err2 := iptable.ProgramRule(iptables.Filter, chains[0], iptables.Delete, rules[0]); err2 != nil {
|
|
| 318 | 318 |
logrus.Warnf("Failed to rollback iptables rule after failure (%v): %v", err, err2)
|
| 319 | 319 |
} |
| 320 | 320 |
} |
| ... | ... |
@@ -330,37 +369,47 @@ func setINC(iface string, enable bool) error {
|
| 330 | 330 |
// Obsolete chain from previous docker versions |
| 331 | 331 |
const oldIsolationChain = "DOCKER-ISOLATION" |
| 332 | 332 |
|
| 333 |
-func removeIPChains() {
|
|
| 333 |
+func removeIPChains(version iptables.IPVersion) {
|
|
| 334 |
+ ipt := iptables.IPTable{Version: version}
|
|
| 335 |
+ |
|
| 334 | 336 |
// Remove obsolete rules from default chains |
| 335 |
- iptables.ProgramRule(iptables.Filter, "FORWARD", iptables.Delete, []string{"-j", oldIsolationChain})
|
|
| 337 |
+ ipt.ProgramRule(iptables.Filter, "FORWARD", iptables.Delete, []string{"-j", oldIsolationChain})
|
|
| 336 | 338 |
|
| 337 | 339 |
// Remove chains |
| 338 | 340 |
for _, chainInfo := range []iptables.ChainInfo{
|
| 339 |
- {Name: DockerChain, Table: iptables.Nat},
|
|
| 340 |
- {Name: DockerChain, Table: iptables.Filter},
|
|
| 341 |
- {Name: IsolationChain1, Table: iptables.Filter},
|
|
| 342 |
- {Name: IsolationChain2, Table: iptables.Filter},
|
|
| 343 |
- {Name: oldIsolationChain, Table: iptables.Filter},
|
|
| 341 |
+ {Name: DockerChain, Table: iptables.Nat, IPTable: ipt},
|
|
| 342 |
+ {Name: DockerChain, Table: iptables.Filter, IPTable: ipt},
|
|
| 343 |
+ {Name: IsolationChain1, Table: iptables.Filter, IPTable: ipt},
|
|
| 344 |
+ {Name: IsolationChain2, Table: iptables.Filter, IPTable: ipt},
|
|
| 345 |
+ {Name: oldIsolationChain, Table: iptables.Filter, IPTable: ipt},
|
|
| 344 | 346 |
} {
|
| 347 |
+ |
|
| 345 | 348 |
if err := chainInfo.Remove(); err != nil {
|
| 346 | 349 |
logrus.Warnf("Failed to remove existing iptables entries in table %s chain %s : %v", chainInfo.Table, chainInfo.Name, err)
|
| 347 | 350 |
} |
| 348 | 351 |
} |
| 349 | 352 |
} |
| 350 | 353 |
|
| 351 |
-func setupInternalNetworkRules(bridgeIface string, addr net.Addr, icc, insert bool) error {
|
|
| 354 |
+func setupInternalNetworkRules(bridgeIface string, addr *net.IPNet, icc, insert bool) error {
|
|
| 352 | 355 |
var ( |
| 353 | 356 |
inDropRule = iptRule{table: iptables.Filter, chain: IsolationChain1, args: []string{"-i", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}}
|
| 354 | 357 |
outDropRule = iptRule{table: iptables.Filter, chain: IsolationChain1, args: []string{"-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}}
|
| 355 | 358 |
) |
| 356 |
- if err := programChainRule(inDropRule, "DROP INCOMING", insert); err != nil {
|
|
| 359 |
+ |
|
| 360 |
+ version := iptables.IPv4 |
|
| 361 |
+ |
|
| 362 |
+ if addr.IP.To4() == nil {
|
|
| 363 |
+ version = iptables.IPv6 |
|
| 364 |
+ } |
|
| 365 |
+ |
|
| 366 |
+ if err := programChainRule(version, inDropRule, "DROP INCOMING", insert); err != nil {
|
|
| 357 | 367 |
return err |
| 358 | 368 |
} |
| 359 |
- if err := programChainRule(outDropRule, "DROP OUTGOING", insert); err != nil {
|
|
| 369 |
+ if err := programChainRule(version, outDropRule, "DROP OUTGOING", insert); err != nil {
|
|
| 360 | 370 |
return err |
| 361 | 371 |
} |
| 362 | 372 |
// Set Inter Container Communication. |
| 363 |
- return setIcc(bridgeIface, icc, insert) |
|
| 373 |
+ return setIcc(version, bridgeIface, icc, insert) |
|
| 364 | 374 |
} |
| 365 | 375 |
|
| 366 | 376 |
func clearEndpointConnections(nlh *netlink.Handle, ep *bridgeEndpoint) {
|
| ... | ... |
@@ -210,7 +210,10 @@ func programMangle(vni uint32, add bool) (err error) {
|
| 210 | 210 |
action = "install" |
| 211 | 211 |
) |
| 212 | 212 |
|
| 213 |
- if add == iptables.Exists(iptables.Mangle, chain, rule...) {
|
|
| 213 |
+ // TODO IPv6 support |
|
| 214 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 215 |
+ |
|
| 216 |
+ if add == iptable.Exists(iptables.Mangle, chain, rule...) {
|
|
| 214 | 217 |
return |
| 215 | 218 |
} |
| 216 | 219 |
|
| ... | ... |
@@ -219,7 +222,7 @@ func programMangle(vni uint32, add bool) (err error) {
|
| 219 | 219 |
action = "remove" |
| 220 | 220 |
} |
| 221 | 221 |
|
| 222 |
- if err = iptables.RawCombinedOutput(append([]string{"-t", string(iptables.Mangle), a, chain}, rule...)...); err != nil {
|
|
| 222 |
+ if err = iptable.RawCombinedOutput(append([]string{"-t", string(iptables.Mangle), a, chain}, rule...)...); err != nil {
|
|
| 223 | 223 |
logrus.Warnf("could not %s mangle rule: %v", action, err)
|
| 224 | 224 |
} |
| 225 | 225 |
|
| ... | ... |
@@ -239,16 +242,19 @@ func programInput(vni uint32, add bool) (err error) {
|
| 239 | 239 |
msg = "add" |
| 240 | 240 |
) |
| 241 | 241 |
|
| 242 |
+ // TODO IPv6 support |
|
| 243 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 244 |
+ |
|
| 242 | 245 |
if !add {
|
| 243 | 246 |
action = iptables.Delete |
| 244 | 247 |
msg = "remove" |
| 245 | 248 |
} |
| 246 | 249 |
|
| 247 |
- if err := iptables.ProgramRule(iptables.Filter, chain, action, accept); err != nil {
|
|
| 250 |
+ if err := iptable.ProgramRule(iptables.Filter, chain, action, accept); err != nil {
|
|
| 248 | 251 |
logrus.Errorf("could not %s input rule: %v. Please do it manually.", msg, err)
|
| 249 | 252 |
} |
| 250 | 253 |
|
| 251 |
- if err := iptables.ProgramRule(iptables.Filter, chain, action, block); err != nil {
|
|
| 254 |
+ if err := iptable.ProgramRule(iptables.Filter, chain, action, block); err != nil {
|
|
| 252 | 255 |
logrus.Errorf("could not %s input rule: %v. Please do it manually.", msg, err)
|
| 253 | 256 |
} |
| 254 | 257 |
|
| ... | ... |
@@ -20,7 +20,9 @@ func filterWait() func() {
|
| 20 | 20 |
} |
| 21 | 21 |
|
| 22 | 22 |
func chainExists(cname string) bool {
|
| 23 |
- if _, err := iptables.Raw("-L", cname); err != nil {
|
|
| 23 |
+ // TODO IPv6 support |
|
| 24 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 25 |
+ if _, err := iptable.Raw("-L", cname); err != nil {
|
|
| 24 | 26 |
return false |
| 25 | 27 |
} |
| 26 | 28 |
|
| ... | ... |
@@ -28,22 +30,26 @@ func chainExists(cname string) bool {
|
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 | 30 |
func setupGlobalChain() {
|
| 31 |
+ // TODO IPv6 support |
|
| 32 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 31 | 33 |
// Because of an ungraceful shutdown, chain could already be present |
| 32 | 34 |
if !chainExists(globalChain) {
|
| 33 |
- if err := iptables.RawCombinedOutput("-N", globalChain); err != nil {
|
|
| 35 |
+ if err := iptable.RawCombinedOutput("-N", globalChain); err != nil {
|
|
| 34 | 36 |
logrus.Errorf("could not create global overlay chain: %v", err)
|
| 35 | 37 |
return |
| 36 | 38 |
} |
| 37 | 39 |
} |
| 38 | 40 |
|
| 39 |
- if !iptables.Exists(iptables.Filter, globalChain, "-j", "RETURN") {
|
|
| 40 |
- if err := iptables.RawCombinedOutput("-A", globalChain, "-j", "RETURN"); err != nil {
|
|
| 41 |
+ if !iptable.Exists(iptables.Filter, globalChain, "-j", "RETURN") {
|
|
| 42 |
+ if err := iptable.RawCombinedOutput("-A", globalChain, "-j", "RETURN"); err != nil {
|
|
| 41 | 43 |
logrus.Errorf("could not install default return chain in the overlay global chain: %v", err)
|
| 42 | 44 |
} |
| 43 | 45 |
} |
| 44 | 46 |
} |
| 45 | 47 |
|
| 46 | 48 |
func setNetworkChain(cname string, remove bool) error {
|
| 49 |
+ // TODO IPv6 support |
|
| 50 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 47 | 51 |
// Initialize the onetime global overlay chain |
| 48 | 52 |
filterOnce.Do(setupGlobalChain) |
| 49 | 53 |
|
| ... | ... |
@@ -52,21 +58,21 @@ func setNetworkChain(cname string, remove bool) error {
|
| 52 | 52 |
opt := "-N" |
| 53 | 53 |
// In case of remove, make sure to flush the rules in the chain |
| 54 | 54 |
if remove && exists {
|
| 55 |
- if err := iptables.RawCombinedOutput("-F", cname); err != nil {
|
|
| 55 |
+ if err := iptable.RawCombinedOutput("-F", cname); err != nil {
|
|
| 56 | 56 |
return fmt.Errorf("failed to flush overlay network chain %s rules: %v", cname, err)
|
| 57 | 57 |
} |
| 58 | 58 |
opt = "-X" |
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
if (!remove && !exists) || (remove && exists) {
|
| 62 |
- if err := iptables.RawCombinedOutput(opt, cname); err != nil {
|
|
| 62 |
+ if err := iptable.RawCombinedOutput(opt, cname); err != nil {
|
|
| 63 | 63 |
return fmt.Errorf("failed network chain operation %q for chain %s: %v", opt, cname, err)
|
| 64 | 64 |
} |
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 | 67 |
if !remove {
|
| 68 |
- if !iptables.Exists(iptables.Filter, cname, "-j", "DROP") {
|
|
| 69 |
- if err := iptables.RawCombinedOutput("-A", cname, "-j", "DROP"); err != nil {
|
|
| 68 |
+ if !iptable.Exists(iptables.Filter, cname, "-j", "DROP") {
|
|
| 69 |
+ if err := iptable.RawCombinedOutput("-A", cname, "-j", "DROP"); err != nil {
|
|
| 70 | 70 |
return fmt.Errorf("failed adding default drop rule to overlay network chain %s: %v", cname, err)
|
| 71 | 71 |
} |
| 72 | 72 |
} |
| ... | ... |
@@ -92,37 +98,39 @@ func setFilters(cname, brName string, remove bool) error {
|
| 92 | 92 |
if remove {
|
| 93 | 93 |
opt = "-D" |
| 94 | 94 |
} |
| 95 |
+ // TODO IPv6 support |
|
| 96 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 95 | 97 |
|
| 96 | 98 |
// Every time we set filters for a new subnet make sure to move the global overlay hook to the top of the both the OUTPUT and forward chains |
| 97 | 99 |
if !remove {
|
| 98 | 100 |
for _, chain := range []string{"OUTPUT", "FORWARD"} {
|
| 99 |
- exists := iptables.Exists(iptables.Filter, chain, "-j", globalChain) |
|
| 101 |
+ exists := iptable.Exists(iptables.Filter, chain, "-j", globalChain) |
|
| 100 | 102 |
if exists {
|
| 101 |
- if err := iptables.RawCombinedOutput("-D", chain, "-j", globalChain); err != nil {
|
|
| 103 |
+ if err := iptable.RawCombinedOutput("-D", chain, "-j", globalChain); err != nil {
|
|
| 102 | 104 |
return fmt.Errorf("failed to delete overlay hook in chain %s while moving the hook: %v", chain, err)
|
| 103 | 105 |
} |
| 104 | 106 |
} |
| 105 | 107 |
|
| 106 |
- if err := iptables.RawCombinedOutput("-I", chain, "-j", globalChain); err != nil {
|
|
| 108 |
+ if err := iptable.RawCombinedOutput("-I", chain, "-j", globalChain); err != nil {
|
|
| 107 | 109 |
return fmt.Errorf("failed to insert overlay hook in chain %s: %v", chain, err)
|
| 108 | 110 |
} |
| 109 | 111 |
} |
| 110 | 112 |
} |
| 111 | 113 |
|
| 112 | 114 |
// Insert/Delete the rule to jump to per-bridge chain |
| 113 |
- exists := iptables.Exists(iptables.Filter, globalChain, "-o", brName, "-j", cname) |
|
| 115 |
+ exists := iptable.Exists(iptables.Filter, globalChain, "-o", brName, "-j", cname) |
|
| 114 | 116 |
if (!remove && !exists) || (remove && exists) {
|
| 115 |
- if err := iptables.RawCombinedOutput(opt, globalChain, "-o", brName, "-j", cname); err != nil {
|
|
| 117 |
+ if err := iptable.RawCombinedOutput(opt, globalChain, "-o", brName, "-j", cname); err != nil {
|
|
| 116 | 118 |
return fmt.Errorf("failed to add per-bridge filter rule for bridge %s, network chain %s: %v", brName, cname, err)
|
| 117 | 119 |
} |
| 118 | 120 |
} |
| 119 | 121 |
|
| 120 |
- exists = iptables.Exists(iptables.Filter, cname, "-i", brName, "-j", "ACCEPT") |
|
| 122 |
+ exists = iptable.Exists(iptables.Filter, cname, "-i", brName, "-j", "ACCEPT") |
|
| 121 | 123 |
if (!remove && exists) || (remove && !exists) {
|
| 122 | 124 |
return nil |
| 123 | 125 |
} |
| 124 | 126 |
|
| 125 |
- if err := iptables.RawCombinedOutput(opt, cname, "-i", brName, "-j", "ACCEPT"); err != nil {
|
|
| 127 |
+ if err := iptable.RawCombinedOutput(opt, cname, "-i", brName, "-j", "ACCEPT"); err != nil {
|
|
| 126 | 128 |
return fmt.Errorf("failed to add overlay filter rile for network chain %s, bridge %s: %v", cname, brName, err)
|
| 127 | 129 |
} |
| 128 | 130 |
|
| ... | ... |
@@ -26,18 +26,20 @@ func arrangeUserFilterRule() {
|
| 26 | 26 |
if ctrl == nil || !ctrl.iptablesEnabled() {
|
| 27 | 27 |
return |
| 28 | 28 |
} |
| 29 |
- _, err := iptables.NewChain(userChain, iptables.Filter, false) |
|
| 29 |
+ // TODO IPv6 support |
|
| 30 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 31 |
+ _, err := iptable.NewChain(userChain, iptables.Filter, false) |
|
| 30 | 32 |
if err != nil {
|
| 31 | 33 |
logrus.Warnf("Failed to create %s chain: %v", userChain, err)
|
| 32 | 34 |
return |
| 33 | 35 |
} |
| 34 | 36 |
|
| 35 |
- if err = iptables.AddReturnRule(userChain); err != nil {
|
|
| 37 |
+ if err = iptable.AddReturnRule(userChain); err != nil {
|
|
| 36 | 38 |
logrus.Warnf("Failed to add the RETURN rule for %s: %v", userChain, err)
|
| 37 | 39 |
return |
| 38 | 40 |
} |
| 39 | 41 |
|
| 40 |
- err = iptables.EnsureJumpRule("FORWARD", userChain)
|
|
| 42 |
+ err = iptable.EnsureJumpRule("FORWARD", userChain)
|
|
| 41 | 43 |
if err != nil {
|
| 42 | 44 |
logrus.Warnf("Failed to ensure the jump rule for %s: %v", userChain, err)
|
| 43 | 45 |
} |
| ... | ... |
@@ -23,6 +23,9 @@ type Policy string |
| 23 | 23 |
// Table refers to Nat, Filter or Mangle. |
| 24 | 24 |
type Table string |
| 25 | 25 |
|
| 26 |
+// IPVersion refers to IP version, v4 or v6 |
|
| 27 |
+type IPVersion string |
|
| 28 |
+ |
|
| 26 | 29 |
const ( |
| 27 | 30 |
// Append appends the rule at the end of the chain. |
| 28 | 31 |
Append Action = "-A" |
| ... | ... |
@@ -40,10 +43,15 @@ const ( |
| 40 | 40 |
Drop Policy = "DROP" |
| 41 | 41 |
// Accept is the default iptables ACCEPT policy |
| 42 | 42 |
Accept Policy = "ACCEPT" |
| 43 |
+ // IPv4 is version 4 |
|
| 44 |
+ IPv4 IPVersion = "IPV4" |
|
| 45 |
+ // IPv6 is version 6 |
|
| 46 |
+ IPv6 IPVersion = "IPV6" |
|
| 43 | 47 |
) |
| 44 | 48 |
|
| 45 | 49 |
var ( |
| 46 | 50 |
iptablesPath string |
| 51 |
+ ip6tablesPath string |
|
| 47 | 52 |
supportsXlock = false |
| 48 | 53 |
supportsCOpt = false |
| 49 | 54 |
xLockWaitMsg = "Another app is currently holding the xtables lock" |
| ... | ... |
@@ -54,11 +62,17 @@ var ( |
| 54 | 54 |
initOnce sync.Once |
| 55 | 55 |
) |
| 56 | 56 |
|
| 57 |
+// IPTable defines struct with IPVersion |
|
| 58 |
+type IPTable struct {
|
|
| 59 |
+ Version IPVersion |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 57 | 62 |
// ChainInfo defines the iptables chain. |
| 58 | 63 |
type ChainInfo struct {
|
| 59 | 64 |
Name string |
| 60 | 65 |
Table Table |
| 61 | 66 |
HairpinMode bool |
| 67 |
+ IPTable IPTable |
|
| 62 | 68 |
} |
| 63 | 69 |
|
| 64 | 70 |
// ChainError is returned to represent errors during ip table operation. |
| ... | ... |
@@ -80,6 +94,11 @@ func probe() {
|
| 80 | 80 |
if out, err := exec.Command(path, "--wait", "-t", "nat", "-L", "-n").CombinedOutput(); err != nil {
|
| 81 | 81 |
logrus.Warnf("Running iptables --wait -t nat -L -n failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
|
| 82 | 82 |
} |
| 83 |
+ _, err = exec.LookPath("ip6tables")
|
|
| 84 |
+ if err != nil {
|
|
| 85 |
+ logrus.Warnf("Failed to find ip6tables: %v", err)
|
|
| 86 |
+ return |
|
| 87 |
+ } |
|
| 83 | 88 |
} |
| 84 | 89 |
|
| 85 | 90 |
func initFirewalld() {
|
| ... | ... |
@@ -94,6 +113,11 @@ func detectIptables() {
|
| 94 | 94 |
return |
| 95 | 95 |
} |
| 96 | 96 |
iptablesPath = path |
| 97 |
+ path, err = exec.LookPath("ip6tables")
|
|
| 98 |
+ if err != nil {
|
|
| 99 |
+ return |
|
| 100 |
+ } |
|
| 101 |
+ ip6tablesPath = path |
|
| 97 | 102 |
supportsXlock = exec.Command(iptablesPath, "--wait", "-L", "-n").Run() == nil |
| 98 | 103 |
mj, mn, mc, err := GetVersion() |
| 99 | 104 |
if err != nil {
|
| ... | ... |
@@ -118,20 +142,26 @@ func initCheck() error {
|
| 118 | 118 |
return nil |
| 119 | 119 |
} |
| 120 | 120 |
|
| 121 |
+// GetIptable returns an instance of IPTable with specified version |
|
| 122 |
+func GetIptable(version IPVersion) *IPTable {
|
|
| 123 |
+ return &IPTable{Version: version}
|
|
| 124 |
+} |
|
| 125 |
+ |
|
| 121 | 126 |
// NewChain adds a new chain to ip table. |
| 122 |
-func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
|
|
| 127 |
+func (iptable IPTable) NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
|
|
| 123 | 128 |
c := &ChainInfo{
|
| 124 | 129 |
Name: name, |
| 125 | 130 |
Table: table, |
| 126 | 131 |
HairpinMode: hairpinMode, |
| 132 |
+ IPTable: iptable, |
|
| 127 | 133 |
} |
| 128 | 134 |
if string(c.Table) == "" {
|
| 129 | 135 |
c.Table = Filter |
| 130 | 136 |
} |
| 131 | 137 |
|
| 132 | 138 |
// Add chain if it doesn't exist |
| 133 |
- if _, err := Raw("-t", string(c.Table), "-n", "-L", c.Name); err != nil {
|
|
| 134 |
- if output, err := Raw("-t", string(c.Table), "-N", c.Name); err != nil {
|
|
| 139 |
+ if _, err := iptable.Raw("-t", string(c.Table), "-n", "-L", c.Name); err != nil {
|
|
| 140 |
+ if output, err := iptable.Raw("-t", string(c.Table), "-N", c.Name); err != nil {
|
|
| 135 | 141 |
return nil, err |
| 136 | 142 |
} else if len(output) != 0 {
|
| 137 | 143 |
return nil, fmt.Errorf("Could not create %s/%s chain: %s", c.Table, c.Name, output)
|
| ... | ... |
@@ -140,8 +170,16 @@ func NewChain(name string, table Table, hairpinMode bool) (*ChainInfo, error) {
|
| 140 | 140 |
return c, nil |
| 141 | 141 |
} |
| 142 | 142 |
|
| 143 |
+// LoopbackByVersion returns loopback address by version |
|
| 144 |
+func (iptable IPTable) LoopbackByVersion() string {
|
|
| 145 |
+ if iptable.Version == IPv6 {
|
|
| 146 |
+ return "::1/128" |
|
| 147 |
+ } |
|
| 148 |
+ return "127.0.0.0/8" |
|
| 149 |
+} |
|
| 150 |
+ |
|
| 143 | 151 |
// ProgramChain is used to add rules to a chain |
| 144 |
-func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error {
|
|
| 152 |
+func (iptable IPTable) ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) error {
|
|
| 145 | 153 |
if c.Name == "" {
|
| 146 | 154 |
return errors.New("Could not program chain, missing chain name")
|
| 147 | 155 |
} |
| ... | ... |
@@ -165,11 +203,11 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err |
| 165 | 165 |
"-m", "addrtype", |
| 166 | 166 |
"--dst-type", "LOCAL", |
| 167 | 167 |
"-j", c.Name} |
| 168 |
- if !Exists(Nat, "PREROUTING", preroute...) && enable {
|
|
| 168 |
+ if !iptable.Exists(Nat, "PREROUTING", preroute...) && enable {
|
|
| 169 | 169 |
if err := c.Prerouting(Append, preroute...); err != nil {
|
| 170 | 170 |
return fmt.Errorf("Failed to inject %s in PREROUTING chain: %s", c.Name, err)
|
| 171 | 171 |
} |
| 172 |
- } else if Exists(Nat, "PREROUTING", preroute...) && !enable {
|
|
| 172 |
+ } else if iptable.Exists(Nat, "PREROUTING", preroute...) && !enable {
|
|
| 173 | 173 |
if err := c.Prerouting(Delete, preroute...); err != nil {
|
| 174 | 174 |
return fmt.Errorf("Failed to remove %s in PREROUTING chain: %s", c.Name, err)
|
| 175 | 175 |
} |
| ... | ... |
@@ -179,13 +217,13 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err |
| 179 | 179 |
"--dst-type", "LOCAL", |
| 180 | 180 |
"-j", c.Name} |
| 181 | 181 |
if !hairpinMode {
|
| 182 |
- output = append(output, "!", "--dst", "127.0.0.0/8") |
|
| 182 |
+ output = append(output, "!", "--dst", iptable.LoopbackByVersion()) |
|
| 183 | 183 |
} |
| 184 |
- if !Exists(Nat, "OUTPUT", output...) && enable {
|
|
| 184 |
+ if !iptable.Exists(Nat, "OUTPUT", output...) && enable {
|
|
| 185 | 185 |
if err := c.Output(Append, output...); err != nil {
|
| 186 | 186 |
return fmt.Errorf("Failed to inject %s in OUTPUT chain: %s", c.Name, err)
|
| 187 | 187 |
} |
| 188 |
- } else if Exists(Nat, "OUTPUT", output...) && !enable {
|
|
| 188 |
+ } else if iptable.Exists(Nat, "OUTPUT", output...) && !enable {
|
|
| 189 | 189 |
if err := c.Output(Delete, output...); err != nil {
|
| 190 | 190 |
return fmt.Errorf("Failed to inject %s in OUTPUT chain: %s", c.Name, err)
|
| 191 | 191 |
} |
| ... | ... |
@@ -198,16 +236,16 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err |
| 198 | 198 |
link := []string{
|
| 199 | 199 |
"-o", bridgeName, |
| 200 | 200 |
"-j", c.Name} |
| 201 |
- if !Exists(Filter, "FORWARD", link...) && enable {
|
|
| 201 |
+ if !iptable.Exists(Filter, "FORWARD", link...) && enable {
|
|
| 202 | 202 |
insert := append([]string{string(Insert), "FORWARD"}, link...)
|
| 203 |
- if output, err := Raw(insert...); err != nil {
|
|
| 203 |
+ if output, err := iptable.Raw(insert...); err != nil {
|
|
| 204 | 204 |
return err |
| 205 | 205 |
} else if len(output) != 0 {
|
| 206 | 206 |
return fmt.Errorf("Could not create linking rule to %s/%s: %s", c.Table, c.Name, output)
|
| 207 | 207 |
} |
| 208 |
- } else if Exists(Filter, "FORWARD", link...) && !enable {
|
|
| 208 |
+ } else if iptable.Exists(Filter, "FORWARD", link...) && !enable {
|
|
| 209 | 209 |
del := append([]string{string(Delete), "FORWARD"}, link...)
|
| 210 |
- if output, err := Raw(del...); err != nil {
|
|
| 210 |
+ if output, err := iptable.Raw(del...); err != nil {
|
|
| 211 | 211 |
return err |
| 212 | 212 |
} else if len(output) != 0 {
|
| 213 | 213 |
return fmt.Errorf("Could not delete linking rule from %s/%s: %s", c.Table, c.Name, output)
|
| ... | ... |
@@ -219,16 +257,16 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err |
| 219 | 219 |
"-m", "conntrack", |
| 220 | 220 |
"--ctstate", "RELATED,ESTABLISHED", |
| 221 | 221 |
"-j", "ACCEPT"} |
| 222 |
- if !Exists(Filter, "FORWARD", establish...) && enable {
|
|
| 222 |
+ if !iptable.Exists(Filter, "FORWARD", establish...) && enable {
|
|
| 223 | 223 |
insert := append([]string{string(Insert), "FORWARD"}, establish...)
|
| 224 |
- if output, err := Raw(insert...); err != nil {
|
|
| 224 |
+ if output, err := iptable.Raw(insert...); err != nil {
|
|
| 225 | 225 |
return err |
| 226 | 226 |
} else if len(output) != 0 {
|
| 227 | 227 |
return fmt.Errorf("Could not create establish rule to %s: %s", c.Table, output)
|
| 228 | 228 |
} |
| 229 |
- } else if Exists(Filter, "FORWARD", establish...) && !enable {
|
|
| 229 |
+ } else if iptable.Exists(Filter, "FORWARD", establish...) && !enable {
|
|
| 230 | 230 |
del := append([]string{string(Delete), "FORWARD"}, establish...)
|
| 231 |
- if output, err := Raw(del...); err != nil {
|
|
| 231 |
+ if output, err := iptable.Raw(del...); err != nil {
|
|
| 232 | 232 |
return err |
| 233 | 233 |
} else if len(output) != 0 {
|
| 234 | 234 |
return fmt.Errorf("Could not delete establish rule from %s: %s", c.Table, output)
|
| ... | ... |
@@ -239,10 +277,11 @@ func ProgramChain(c *ChainInfo, bridgeName string, hairpinMode, enable bool) err |
| 239 | 239 |
} |
| 240 | 240 |
|
| 241 | 241 |
// RemoveExistingChain removes existing chain from the table. |
| 242 |
-func RemoveExistingChain(name string, table Table) error {
|
|
| 242 |
+func (iptable IPTable) RemoveExistingChain(name string, table Table) error {
|
|
| 243 | 243 |
c := &ChainInfo{
|
| 244 |
- Name: name, |
|
| 245 |
- Table: table, |
|
| 244 |
+ Name: name, |
|
| 245 |
+ Table: table, |
|
| 246 |
+ IPTable: iptable, |
|
| 246 | 247 |
} |
| 247 | 248 |
if string(c.Table) == "" {
|
| 248 | 249 |
c.Table = Filter |
| ... | ... |
@@ -252,6 +291,8 @@ func RemoveExistingChain(name string, table Table) error {
|
| 252 | 252 |
|
| 253 | 253 |
// Forward adds forwarding rule to 'filter' table and corresponding nat rule to 'nat' table. |
| 254 | 254 |
func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr string, destPort int, bridgeName string) error {
|
| 255 |
+ |
|
| 256 |
+ iptable := GetIptable(c.IPTable.Version) |
|
| 255 | 257 |
daddr := ip.String() |
| 256 | 258 |
if ip.IsUnspecified() {
|
| 257 | 259 |
// iptables interprets "0.0.0.0" as "0.0.0.0/32", whereas we |
| ... | ... |
@@ -266,10 +307,11 @@ func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr |
| 266 | 266 |
"--dport", strconv.Itoa(port), |
| 267 | 267 |
"-j", "DNAT", |
| 268 | 268 |
"--to-destination", net.JoinHostPort(destAddr, strconv.Itoa(destPort))} |
| 269 |
+ |
|
| 269 | 270 |
if !c.HairpinMode {
|
| 270 | 271 |
args = append(args, "!", "-i", bridgeName) |
| 271 | 272 |
} |
| 272 |
- if err := ProgramRule(Nat, c.Name, action, args); err != nil {
|
|
| 273 |
+ if err := iptable.ProgramRule(Nat, c.Name, action, args); err != nil {
|
|
| 273 | 274 |
return err |
| 274 | 275 |
} |
| 275 | 276 |
|
| ... | ... |
@@ -281,7 +323,7 @@ func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr |
| 281 | 281 |
"--dport", strconv.Itoa(destPort), |
| 282 | 282 |
"-j", "ACCEPT", |
| 283 | 283 |
} |
| 284 |
- if err := ProgramRule(Filter, c.Name, action, args); err != nil {
|
|
| 284 |
+ if err := iptable.ProgramRule(Filter, c.Name, action, args); err != nil {
|
|
| 285 | 285 |
return err |
| 286 | 286 |
} |
| 287 | 287 |
|
| ... | ... |
@@ -293,7 +335,7 @@ func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr |
| 293 | 293 |
"-j", "MASQUERADE", |
| 294 | 294 |
} |
| 295 | 295 |
|
| 296 |
- if err := ProgramRule(Nat, "POSTROUTING", action, args); err != nil {
|
|
| 296 |
+ if err := iptable.ProgramRule(Nat, "POSTROUTING", action, args); err != nil {
|
|
| 297 | 297 |
return err |
| 298 | 298 |
} |
| 299 | 299 |
|
| ... | ... |
@@ -311,7 +353,7 @@ func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr |
| 311 | 311 |
"-j", "CHECKSUM", |
| 312 | 312 |
"--checksum-fill", |
| 313 | 313 |
} |
| 314 |
- if err := ProgramRule(Mangle, "POSTROUTING", action, args); err != nil {
|
|
| 314 |
+ if err := iptable.ProgramRule(Mangle, "POSTROUTING", action, args); err != nil {
|
|
| 315 | 315 |
return err |
| 316 | 316 |
} |
| 317 | 317 |
} |
| ... | ... |
@@ -322,6 +364,7 @@ func (c *ChainInfo) Forward(action Action, ip net.IP, port int, proto, destAddr |
| 322 | 322 |
// Link adds reciprocal ACCEPT rule for two supplied IP addresses. |
| 323 | 323 |
// Traffic is allowed from ip1 to ip2 and vice-versa |
| 324 | 324 |
func (c *ChainInfo) Link(action Action, ip1, ip2 net.IP, port int, proto string, bridgeName string) error {
|
| 325 |
+ iptable := GetIptable(c.IPTable.Version) |
|
| 325 | 326 |
// forward |
| 326 | 327 |
args := []string{
|
| 327 | 328 |
"-i", bridgeName, "-o", bridgeName, |
| ... | ... |
@@ -331,32 +374,34 @@ func (c *ChainInfo) Link(action Action, ip1, ip2 net.IP, port int, proto string, |
| 331 | 331 |
"--dport", strconv.Itoa(port), |
| 332 | 332 |
"-j", "ACCEPT", |
| 333 | 333 |
} |
| 334 |
- if err := ProgramRule(Filter, c.Name, action, args); err != nil {
|
|
| 334 |
+ |
|
| 335 |
+ if err := iptable.ProgramRule(Filter, c.Name, action, args); err != nil {
|
|
| 335 | 336 |
return err |
| 336 | 337 |
} |
| 337 | 338 |
// reverse |
| 338 | 339 |
args[7], args[9] = args[9], args[7] |
| 339 | 340 |
args[10] = "--sport" |
| 340 |
- return ProgramRule(Filter, c.Name, action, args) |
|
| 341 |
+ return iptable.ProgramRule(Filter, c.Name, action, args) |
|
| 341 | 342 |
} |
| 342 | 343 |
|
| 343 | 344 |
// ProgramRule adds the rule specified by args only if the |
| 344 | 345 |
// rule is not already present in the chain. Reciprocally, |
| 345 | 346 |
// it removes the rule only if present. |
| 346 |
-func ProgramRule(table Table, chain string, action Action, args []string) error {
|
|
| 347 |
- if Exists(table, chain, args...) != (action == Delete) {
|
|
| 347 |
+func (iptable IPTable) ProgramRule(table Table, chain string, action Action, args []string) error {
|
|
| 348 |
+ if iptable.Exists(table, chain, args...) != (action == Delete) {
|
|
| 348 | 349 |
return nil |
| 349 | 350 |
} |
| 350 |
- return RawCombinedOutput(append([]string{"-t", string(table), string(action), chain}, args...)...)
|
|
| 351 |
+ return iptable.RawCombinedOutput(append([]string{"-t", string(table), string(action), chain}, args...)...)
|
|
| 351 | 352 |
} |
| 352 | 353 |
|
| 353 | 354 |
// Prerouting adds linking rule to nat/PREROUTING chain. |
| 354 | 355 |
func (c *ChainInfo) Prerouting(action Action, args ...string) error {
|
| 356 |
+ iptable := GetIptable(c.IPTable.Version) |
|
| 355 | 357 |
a := []string{"-t", string(Nat), string(action), "PREROUTING"}
|
| 356 | 358 |
if len(args) > 0 {
|
| 357 | 359 |
a = append(a, args...) |
| 358 | 360 |
} |
| 359 |
- if output, err := Raw(a...); err != nil {
|
|
| 361 |
+ if output, err := iptable.Raw(a...); err != nil {
|
|
| 360 | 362 |
return err |
| 361 | 363 |
} else if len(output) != 0 {
|
| 362 | 364 |
return ChainError{Chain: "PREROUTING", Output: output}
|
| ... | ... |
@@ -366,11 +411,12 @@ func (c *ChainInfo) Prerouting(action Action, args ...string) error {
|
| 366 | 366 |
|
| 367 | 367 |
// Output adds linking rule to an OUTPUT chain. |
| 368 | 368 |
func (c *ChainInfo) Output(action Action, args ...string) error {
|
| 369 |
+ iptable := GetIptable(c.IPTable.Version) |
|
| 369 | 370 |
a := []string{"-t", string(c.Table), string(action), "OUTPUT"}
|
| 370 | 371 |
if len(args) > 0 {
|
| 371 | 372 |
a = append(a, args...) |
| 372 | 373 |
} |
| 373 |
- if output, err := Raw(a...); err != nil {
|
|
| 374 |
+ if output, err := iptable.Raw(a...); err != nil {
|
|
| 374 | 375 |
return err |
| 375 | 376 |
} else if len(output) != 0 {
|
| 376 | 377 |
return ChainError{Chain: "OUTPUT", Output: output}
|
| ... | ... |
@@ -380,35 +426,36 @@ func (c *ChainInfo) Output(action Action, args ...string) error {
|
| 380 | 380 |
|
| 381 | 381 |
// Remove removes the chain. |
| 382 | 382 |
func (c *ChainInfo) Remove() error {
|
| 383 |
+ iptable := GetIptable(c.IPTable.Version) |
|
| 383 | 384 |
// Ignore errors - This could mean the chains were never set up |
| 384 | 385 |
if c.Table == Nat {
|
| 385 | 386 |
c.Prerouting(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "-j", c.Name) |
| 386 |
- c.Output(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "!", "--dst", "127.0.0.0/8", "-j", c.Name) |
|
| 387 |
+ c.Output(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "!", "--dst", iptable.LoopbackByVersion(), "-j", c.Name) |
|
| 387 | 388 |
c.Output(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "-j", c.Name) // Created in versions <= 0.1.6 |
| 388 | 389 |
|
| 389 | 390 |
c.Prerouting(Delete) |
| 390 | 391 |
c.Output(Delete) |
| 391 | 392 |
} |
| 392 |
- Raw("-t", string(c.Table), "-F", c.Name)
|
|
| 393 |
- Raw("-t", string(c.Table), "-X", c.Name)
|
|
| 393 |
+ iptable.Raw("-t", string(c.Table), "-F", c.Name)
|
|
| 394 |
+ iptable.Raw("-t", string(c.Table), "-X", c.Name)
|
|
| 394 | 395 |
return nil |
| 395 | 396 |
} |
| 396 | 397 |
|
| 397 | 398 |
// Exists checks if a rule exists |
| 398 |
-func Exists(table Table, chain string, rule ...string) bool {
|
|
| 399 |
- return exists(false, table, chain, rule...) |
|
| 399 |
+func (iptable IPTable) Exists(table Table, chain string, rule ...string) bool {
|
|
| 400 |
+ return iptable.exists(false, table, chain, rule...) |
|
| 400 | 401 |
} |
| 401 | 402 |
|
| 402 | 403 |
// ExistsNative behaves as Exists with the difference it |
| 403 | 404 |
// will always invoke `iptables` binary. |
| 404 |
-func ExistsNative(table Table, chain string, rule ...string) bool {
|
|
| 405 |
- return exists(true, table, chain, rule...) |
|
| 405 |
+func (iptable IPTable) ExistsNative(table Table, chain string, rule ...string) bool {
|
|
| 406 |
+ return iptable.exists(true, table, chain, rule...) |
|
| 406 | 407 |
} |
| 407 | 408 |
|
| 408 |
-func exists(native bool, table Table, chain string, rule ...string) bool {
|
|
| 409 |
- f := Raw |
|
| 409 |
+func (iptable IPTable) exists(native bool, table Table, chain string, rule ...string) bool {
|
|
| 410 |
+ f := iptable.Raw |
|
| 410 | 411 |
if native {
|
| 411 |
- f = raw |
|
| 412 |
+ f = iptable.raw |
|
| 412 | 413 |
} |
| 413 | 414 |
|
| 414 | 415 |
if string(table) == "" {
|
| ... | ... |
@@ -429,12 +476,16 @@ func exists(native bool, table Table, chain string, rule ...string) bool {
|
| 429 | 429 |
|
| 430 | 430 |
// parse "iptables -S" for the rule (it checks rules in a specific chain |
| 431 | 431 |
// in a specific table and it is very unreliable) |
| 432 |
- return existsRaw(table, chain, rule...) |
|
| 432 |
+ return iptable.existsRaw(table, chain, rule...) |
|
| 433 | 433 |
} |
| 434 | 434 |
|
| 435 |
-func existsRaw(table Table, chain string, rule ...string) bool {
|
|
| 435 |
+func (iptable IPTable) existsRaw(table Table, chain string, rule ...string) bool {
|
|
| 436 |
+ path := iptablesPath |
|
| 437 |
+ if iptable.Version == IPv6 {
|
|
| 438 |
+ path = ip6tablesPath |
|
| 439 |
+ } |
|
| 436 | 440 |
ruleString := fmt.Sprintf("%s %s\n", chain, strings.Join(rule, " "))
|
| 437 |
- existingRules, _ := exec.Command(iptablesPath, "-t", string(table), "-S", chain).Output() |
|
| 441 |
+ existingRules, _ := exec.Command(path, "-t", string(table), "-S", chain).Output() |
|
| 438 | 442 |
|
| 439 | 443 |
return strings.Contains(string(existingRules), ruleString) |
| 440 | 444 |
} |
| ... | ... |
@@ -459,7 +510,7 @@ func filterOutput(start time.Time, output []byte, args ...string) []byte {
|
| 459 | 459 |
} |
| 460 | 460 |
|
| 461 | 461 |
// Raw calls 'iptables' system command, passing supplied arguments. |
| 462 |
-func Raw(args ...string) ([]byte, error) {
|
|
| 462 |
+func (iptable IPTable) Raw(args ...string) ([]byte, error) {
|
|
| 463 | 463 |
if firewalldRunning {
|
| 464 | 464 |
startTime := time.Now() |
| 465 | 465 |
output, err := Passthrough(Iptables, args...) |
| ... | ... |
@@ -467,10 +518,10 @@ func Raw(args ...string) ([]byte, error) {
|
| 467 | 467 |
return filterOutput(startTime, output, args...), err |
| 468 | 468 |
} |
| 469 | 469 |
} |
| 470 |
- return raw(args...) |
|
| 470 |
+ return iptable.raw(args...) |
|
| 471 | 471 |
} |
| 472 | 472 |
|
| 473 |
-func raw(args ...string) ([]byte, error) {
|
|
| 473 |
+func (iptable IPTable) raw(args ...string) ([]byte, error) {
|
|
| 474 | 474 |
if err := initCheck(); err != nil {
|
| 475 | 475 |
return nil, err |
| 476 | 476 |
} |
| ... | ... |
@@ -481,10 +532,15 @@ func raw(args ...string) ([]byte, error) {
|
| 481 | 481 |
defer bestEffortLock.Unlock() |
| 482 | 482 |
} |
| 483 | 483 |
|
| 484 |
- logrus.Debugf("%s, %v", iptablesPath, args)
|
|
| 484 |
+ path := iptablesPath |
|
| 485 |
+ if iptable.Version == IPv6 {
|
|
| 486 |
+ path = ip6tablesPath |
|
| 487 |
+ } |
|
| 488 |
+ |
|
| 489 |
+ logrus.Debugf("%s, %v", path, args)
|
|
| 485 | 490 |
|
| 486 | 491 |
startTime := time.Now() |
| 487 |
- output, err := exec.Command(iptablesPath, args...).CombinedOutput() |
|
| 492 |
+ output, err := exec.Command(path, args...).CombinedOutput() |
|
| 488 | 493 |
if err != nil {
|
| 489 | 494 |
return nil, fmt.Errorf("iptables failed: iptables %v: %s (%s)", strings.Join(args, " "), output, err)
|
| 490 | 495 |
} |
| ... | ... |
@@ -494,8 +550,8 @@ func raw(args ...string) ([]byte, error) {
|
| 494 | 494 |
|
| 495 | 495 |
// RawCombinedOutput internally calls the Raw function and returns a non nil |
| 496 | 496 |
// error if Raw returned a non nil error or a non empty output |
| 497 |
-func RawCombinedOutput(args ...string) error {
|
|
| 498 |
- if output, err := Raw(args...); err != nil || len(output) != 0 {
|
|
| 497 |
+func (iptable IPTable) RawCombinedOutput(args ...string) error {
|
|
| 498 |
+ if output, err := iptable.Raw(args...); err != nil || len(output) != 0 {
|
|
| 499 | 499 |
return fmt.Errorf("%s (%v)", string(output), err)
|
| 500 | 500 |
} |
| 501 | 501 |
return nil |
| ... | ... |
@@ -503,16 +559,16 @@ func RawCombinedOutput(args ...string) error {
|
| 503 | 503 |
|
| 504 | 504 |
// RawCombinedOutputNative behave as RawCombinedOutput with the difference it |
| 505 | 505 |
// will always invoke `iptables` binary |
| 506 |
-func RawCombinedOutputNative(args ...string) error {
|
|
| 507 |
- if output, err := raw(args...); err != nil || len(output) != 0 {
|
|
| 506 |
+func (iptable IPTable) RawCombinedOutputNative(args ...string) error {
|
|
| 507 |
+ if output, err := iptable.raw(args...); err != nil || len(output) != 0 {
|
|
| 508 | 508 |
return fmt.Errorf("%s (%v)", string(output), err)
|
| 509 | 509 |
} |
| 510 | 510 |
return nil |
| 511 | 511 |
} |
| 512 | 512 |
|
| 513 | 513 |
// ExistChain checks if a chain exists |
| 514 |
-func ExistChain(chain string, table Table) bool {
|
|
| 515 |
- if _, err := Raw("-t", string(table), "-nL", chain); err == nil {
|
|
| 514 |
+func (iptable IPTable) ExistChain(chain string, table Table) bool {
|
|
| 515 |
+ if _, err := iptable.Raw("-t", string(table), "-nL", chain); err == nil {
|
|
| 516 | 516 |
return true |
| 517 | 517 |
} |
| 518 | 518 |
return false |
| ... | ... |
@@ -528,8 +584,8 @@ func GetVersion() (major, minor, micro int, err error) {
|
| 528 | 528 |
} |
| 529 | 529 |
|
| 530 | 530 |
// SetDefaultPolicy sets the passed default policy for the table/chain |
| 531 |
-func SetDefaultPolicy(table Table, chain string, policy Policy) error {
|
|
| 532 |
- if err := RawCombinedOutput("-t", string(table), "-P", chain, string(policy)); err != nil {
|
|
| 531 |
+func (iptable IPTable) SetDefaultPolicy(table Table, chain string, policy Policy) error {
|
|
| 532 |
+ if err := iptable.RawCombinedOutput("-t", string(table), "-P", chain, string(policy)); err != nil {
|
|
| 533 | 533 |
return fmt.Errorf("setting default policy to %v in %v chain failed: %v", policy, chain, err)
|
| 534 | 534 |
} |
| 535 | 535 |
return nil |
| ... | ... |
@@ -549,17 +605,17 @@ func supportsCOption(mj, mn, mc int) bool {
|
| 549 | 549 |
} |
| 550 | 550 |
|
| 551 | 551 |
// AddReturnRule adds a return rule for the chain in the filter table |
| 552 |
-func AddReturnRule(chain string) error {
|
|
| 552 |
+func (iptable IPTable) AddReturnRule(chain string) error {
|
|
| 553 | 553 |
var ( |
| 554 | 554 |
table = Filter |
| 555 | 555 |
args = []string{"-j", "RETURN"}
|
| 556 | 556 |
) |
| 557 | 557 |
|
| 558 |
- if Exists(table, chain, args...) {
|
|
| 558 |
+ if iptable.Exists(table, chain, args...) {
|
|
| 559 | 559 |
return nil |
| 560 | 560 |
} |
| 561 | 561 |
|
| 562 |
- err := RawCombinedOutput(append([]string{"-A", chain}, args...)...)
|
|
| 562 |
+ err := iptable.RawCombinedOutput(append([]string{"-A", chain}, args...)...)
|
|
| 563 | 563 |
if err != nil {
|
| 564 | 564 |
return fmt.Errorf("unable to add return rule in %s chain: %s", chain, err.Error())
|
| 565 | 565 |
} |
| ... | ... |
@@ -568,20 +624,20 @@ func AddReturnRule(chain string) error {
|
| 568 | 568 |
} |
| 569 | 569 |
|
| 570 | 570 |
// EnsureJumpRule ensures the jump rule is on top |
| 571 |
-func EnsureJumpRule(fromChain, toChain string) error {
|
|
| 571 |
+func (iptable IPTable) EnsureJumpRule(fromChain, toChain string) error {
|
|
| 572 | 572 |
var ( |
| 573 | 573 |
table = Filter |
| 574 | 574 |
args = []string{"-j", toChain}
|
| 575 | 575 |
) |
| 576 | 576 |
|
| 577 |
- if Exists(table, fromChain, args...) {
|
|
| 578 |
- err := RawCombinedOutput(append([]string{"-D", fromChain}, args...)...)
|
|
| 577 |
+ if iptable.Exists(table, fromChain, args...) {
|
|
| 578 |
+ err := iptable.RawCombinedOutput(append([]string{"-D", fromChain}, args...)...)
|
|
| 579 | 579 |
if err != nil {
|
| 580 | 580 |
return fmt.Errorf("unable to remove jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
|
| 581 | 581 |
} |
| 582 | 582 |
} |
| 583 | 583 |
|
| 584 |
- err := RawCombinedOutput(append([]string{"-I", fromChain}, args...)...)
|
|
| 584 |
+ err := iptable.RawCombinedOutput(append([]string{"-I", fromChain}, args...)...)
|
|
| 585 | 585 |
if err != nil {
|
| 586 | 586 |
return fmt.Errorf("unable to insert jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
|
| 587 | 587 |
} |
| ... | ... |
@@ -151,7 +151,7 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, |
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 | 153 |
containerIP, containerPort := getIPAndPort(m.container) |
| 154 |
- if hostIP.To4() != nil {
|
|
| 154 |
+ if hostIP.To4() != nil || hostIP.To16() != nil {
|
|
| 155 | 155 |
if err := pm.AppendForwardingTableEntry(m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
|
| 156 | 156 |
return nil, err |
| 157 | 157 |
} |
| ... | ... |
@@ -160,7 +160,7 @@ func (pm *PortMapper) MapRange(container net.Addr, hostIP net.IP, hostPortStart, |
| 160 | 160 |
cleanup := func() error {
|
| 161 | 161 |
// need to undo the iptables rules before we return |
| 162 | 162 |
m.userlandProxy.Stop() |
| 163 |
- if hostIP.To4() != nil {
|
|
| 163 |
+ if hostIP.To4() != nil || hostIP.To16() != nil {
|
|
| 164 | 164 |
pm.DeleteForwardingTableEntry(m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort) |
| 165 | 165 |
if err := pm.Allocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
|
| 166 | 166 |
return err |
| ... | ... |
@@ -57,25 +57,28 @@ func reexecSetupResolver() {
|
| 57 | 57 |
os.Exit(3) |
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 |
+ // TODO IPv6 support |
|
| 61 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 62 |
+ |
|
| 60 | 63 |
// insert outputChain and postroutingchain |
| 61 |
- err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "OUTPUT", "-d", resolverIP, "-j", outputChain)
|
|
| 64 |
+ err = iptable.RawCombinedOutputNative("-t", "nat", "-C", "OUTPUT", "-d", resolverIP, "-j", outputChain)
|
|
| 62 | 65 |
if err == nil {
|
| 63 |
- iptables.RawCombinedOutputNative("-t", "nat", "-F", outputChain)
|
|
| 66 |
+ iptable.RawCombinedOutputNative("-t", "nat", "-F", outputChain)
|
|
| 64 | 67 |
} else {
|
| 65 |
- iptables.RawCombinedOutputNative("-t", "nat", "-N", outputChain)
|
|
| 66 |
- iptables.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain)
|
|
| 68 |
+ iptable.RawCombinedOutputNative("-t", "nat", "-N", outputChain)
|
|
| 69 |
+ iptable.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain)
|
|
| 67 | 70 |
} |
| 68 | 71 |
|
| 69 |
- err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
|
|
| 72 |
+ err = iptable.RawCombinedOutputNative("-t", "nat", "-C", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
|
|
| 70 | 73 |
if err == nil {
|
| 71 |
- iptables.RawCombinedOutputNative("-t", "nat", "-F", postroutingchain)
|
|
| 74 |
+ iptable.RawCombinedOutputNative("-t", "nat", "-F", postroutingchain)
|
|
| 72 | 75 |
} else {
|
| 73 |
- iptables.RawCombinedOutputNative("-t", "nat", "-N", postroutingchain)
|
|
| 74 |
- iptables.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
|
|
| 76 |
+ iptable.RawCombinedOutputNative("-t", "nat", "-N", postroutingchain)
|
|
| 77 |
+ iptable.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
|
|
| 75 | 78 |
} |
| 76 | 79 |
|
| 77 | 80 |
for _, rule := range rules {
|
| 78 |
- if iptables.RawCombinedOutputNative(rule...) != nil {
|
|
| 81 |
+ if iptable.RawCombinedOutputNative(rule...) != nil {
|
|
| 79 | 82 |
logrus.Errorf("set up rule failed, %v", rule)
|
| 80 | 83 |
} |
| 81 | 84 |
} |
| ... | ... |
@@ -302,6 +302,9 @@ func filterPortConfigs(ingressPorts []*PortConfig, isDelete bool) []*PortConfig |
| 302 | 302 |
} |
| 303 | 303 |
|
| 304 | 304 |
func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) error {
|
| 305 |
+ // TODO IPv6 support |
|
| 306 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 307 |
+ |
|
| 305 | 308 |
addDelOpt := "-I" |
| 306 | 309 |
rollbackAddDelOpt := "-D" |
| 307 | 310 |
if isDelete {
|
| ... | ... |
@@ -312,19 +315,19 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 312 | 312 |
ingressMu.Lock() |
| 313 | 313 |
defer ingressMu.Unlock() |
| 314 | 314 |
|
| 315 |
- chainExists := iptables.ExistChain(ingressChain, iptables.Nat) |
|
| 316 |
- filterChainExists := iptables.ExistChain(ingressChain, iptables.Filter) |
|
| 315 |
+ chainExists := iptable.ExistChain(ingressChain, iptables.Nat) |
|
| 316 |
+ filterChainExists := iptable.ExistChain(ingressChain, iptables.Filter) |
|
| 317 | 317 |
|
| 318 | 318 |
ingressOnce.Do(func() {
|
| 319 | 319 |
// Flush nat table and filter table ingress chain rules during init if it |
| 320 | 320 |
// exists. It might contain stale rules from previous life. |
| 321 | 321 |
if chainExists {
|
| 322 |
- if err := iptables.RawCombinedOutput("-t", "nat", "-F", ingressChain); err != nil {
|
|
| 322 |
+ if err := iptable.RawCombinedOutput("-t", "nat", "-F", ingressChain); err != nil {
|
|
| 323 | 323 |
logrus.Errorf("Could not flush nat table ingress chain rules during init: %v", err)
|
| 324 | 324 |
} |
| 325 | 325 |
} |
| 326 | 326 |
if filterChainExists {
|
| 327 |
- if err := iptables.RawCombinedOutput("-F", ingressChain); err != nil {
|
|
| 327 |
+ if err := iptable.RawCombinedOutput("-F", ingressChain); err != nil {
|
|
| 328 | 328 |
logrus.Errorf("Could not flush filter table ingress chain rules during init: %v", err)
|
| 329 | 329 |
} |
| 330 | 330 |
} |
| ... | ... |
@@ -332,38 +335,38 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 332 | 332 |
|
| 333 | 333 |
if !isDelete {
|
| 334 | 334 |
if !chainExists {
|
| 335 |
- if err := iptables.RawCombinedOutput("-t", "nat", "-N", ingressChain); err != nil {
|
|
| 335 |
+ if err := iptable.RawCombinedOutput("-t", "nat", "-N", ingressChain); err != nil {
|
|
| 336 | 336 |
return fmt.Errorf("failed to create ingress chain: %v", err)
|
| 337 | 337 |
} |
| 338 | 338 |
} |
| 339 | 339 |
if !filterChainExists {
|
| 340 |
- if err := iptables.RawCombinedOutput("-N", ingressChain); err != nil {
|
|
| 340 |
+ if err := iptable.RawCombinedOutput("-N", ingressChain); err != nil {
|
|
| 341 | 341 |
return fmt.Errorf("failed to create filter table ingress chain: %v", err)
|
| 342 | 342 |
} |
| 343 | 343 |
} |
| 344 | 344 |
|
| 345 |
- if !iptables.Exists(iptables.Nat, ingressChain, "-j", "RETURN") {
|
|
| 346 |
- if err := iptables.RawCombinedOutput("-t", "nat", "-A", ingressChain, "-j", "RETURN"); err != nil {
|
|
| 345 |
+ if !iptable.Exists(iptables.Nat, ingressChain, "-j", "RETURN") {
|
|
| 346 |
+ if err := iptable.RawCombinedOutput("-t", "nat", "-A", ingressChain, "-j", "RETURN"); err != nil {
|
|
| 347 | 347 |
return fmt.Errorf("failed to add return rule in nat table ingress chain: %v", err)
|
| 348 | 348 |
} |
| 349 | 349 |
} |
| 350 | 350 |
|
| 351 |
- if !iptables.Exists(iptables.Filter, ingressChain, "-j", "RETURN") {
|
|
| 352 |
- if err := iptables.RawCombinedOutput("-A", ingressChain, "-j", "RETURN"); err != nil {
|
|
| 351 |
+ if !iptable.Exists(iptables.Filter, ingressChain, "-j", "RETURN") {
|
|
| 352 |
+ if err := iptable.RawCombinedOutput("-A", ingressChain, "-j", "RETURN"); err != nil {
|
|
| 353 | 353 |
return fmt.Errorf("failed to add return rule to filter table ingress chain: %v", err)
|
| 354 | 354 |
} |
| 355 | 355 |
} |
| 356 | 356 |
|
| 357 | 357 |
for _, chain := range []string{"OUTPUT", "PREROUTING"} {
|
| 358 |
- if !iptables.Exists(iptables.Nat, chain, "-m", "addrtype", "--dst-type", "LOCAL", "-j", ingressChain) {
|
|
| 359 |
- if err := iptables.RawCombinedOutput("-t", "nat", "-I", chain, "-m", "addrtype", "--dst-type", "LOCAL", "-j", ingressChain); err != nil {
|
|
| 358 |
+ if !iptable.Exists(iptables.Nat, chain, "-m", "addrtype", "--dst-type", "LOCAL", "-j", ingressChain) {
|
|
| 359 |
+ if err := iptable.RawCombinedOutput("-t", "nat", "-I", chain, "-m", "addrtype", "--dst-type", "LOCAL", "-j", ingressChain); err != nil {
|
|
| 360 | 360 |
return fmt.Errorf("failed to add jump rule in %s to ingress chain: %v", chain, err)
|
| 361 | 361 |
} |
| 362 | 362 |
} |
| 363 | 363 |
} |
| 364 | 364 |
|
| 365 |
- if !iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
|
|
| 366 |
- if err := iptables.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 365 |
+ if !iptable.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
|
|
| 366 |
+ if err := iptable.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 367 | 367 |
return fmt.Errorf("failed to add jump rule to %s in filter table forward chain: %v", ingressChain, err)
|
| 368 | 368 |
} |
| 369 | 369 |
arrangeUserFilterRule() |
| ... | ... |
@@ -380,8 +383,8 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 380 | 380 |
} |
| 381 | 381 |
|
| 382 | 382 |
ruleArgs := strings.Fields(fmt.Sprintf("-m addrtype --src-type LOCAL -o %s -j MASQUERADE", oifName))
|
| 383 |
- if !iptables.Exists(iptables.Nat, "POSTROUTING", ruleArgs...) {
|
|
| 384 |
- if err := iptables.RawCombinedOutput(append([]string{"-t", "nat", "-I", "POSTROUTING"}, ruleArgs...)...); err != nil {
|
|
| 383 |
+ if !iptable.Exists(iptables.Nat, "POSTROUTING", ruleArgs...) {
|
|
| 384 |
+ if err := iptable.RawCombinedOutput(append([]string{"-t", "nat", "-I", "POSTROUTING"}, ruleArgs...)...); err != nil {
|
|
| 385 | 385 |
return fmt.Errorf("failed to add ingress localhost POSTROUTING rule for %s: %v", oifName, err)
|
| 386 | 386 |
} |
| 387 | 387 |
} |
| ... | ... |
@@ -395,7 +398,7 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 395 | 395 |
if portErr != nil && !isDelete {
|
| 396 | 396 |
filterPortConfigs(filteredPorts, !isDelete) |
| 397 | 397 |
for _, rule := range rollbackRules {
|
| 398 |
- if err := iptables.RawCombinedOutput(rule...); err != nil {
|
|
| 398 |
+ if err := iptable.RawCombinedOutput(rule...); err != nil {
|
|
| 399 | 399 |
logrus.Warnf("roll back rule failed, %v: %v", rule, err)
|
| 400 | 400 |
} |
| 401 | 401 |
} |
| ... | ... |
@@ -403,10 +406,10 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 403 | 403 |
}() |
| 404 | 404 |
|
| 405 | 405 |
for _, iPort := range filteredPorts {
|
| 406 |
- if iptables.ExistChain(ingressChain, iptables.Nat) {
|
|
| 406 |
+ if iptable.ExistChain(ingressChain, iptables.Nat) {
|
|
| 407 | 407 |
rule := strings.Fields(fmt.Sprintf("-t nat %s %s -p %s --dport %d -j DNAT --to-destination %s:%d",
|
| 408 | 408 |
addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, gwIP, iPort.PublishedPort)) |
| 409 |
- if portErr = iptables.RawCombinedOutput(rule...); portErr != nil {
|
|
| 409 |
+ if portErr = iptable.RawCombinedOutput(rule...); portErr != nil {
|
|
| 410 | 410 |
errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr)
|
| 411 | 411 |
if !isDelete {
|
| 412 | 412 |
return fmt.Errorf("%s", errStr)
|
| ... | ... |
@@ -423,7 +426,7 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 423 | 423 |
// 2) unmanaged containers on bridge networks |
| 424 | 424 |
rule := strings.Fields(fmt.Sprintf("%s %s -m state -p %s --sport %d --state ESTABLISHED,RELATED -j ACCEPT",
|
| 425 | 425 |
addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort)) |
| 426 |
- if portErr = iptables.RawCombinedOutput(rule...); portErr != nil {
|
|
| 426 |
+ if portErr = iptable.RawCombinedOutput(rule...); portErr != nil {
|
|
| 427 | 427 |
errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr)
|
| 428 | 428 |
if !isDelete {
|
| 429 | 429 |
return fmt.Errorf("%s", errStr)
|
| ... | ... |
@@ -436,7 +439,7 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 436 | 436 |
|
| 437 | 437 |
rule = strings.Fields(fmt.Sprintf("%s %s -p %s --dport %d -j ACCEPT",
|
| 438 | 438 |
addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort)) |
| 439 |
- if portErr = iptables.RawCombinedOutput(rule...); portErr != nil {
|
|
| 439 |
+ if portErr = iptable.RawCombinedOutput(rule...); portErr != nil {
|
|
| 440 | 440 |
errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr)
|
| 441 | 441 |
if !isDelete {
|
| 442 | 442 |
return fmt.Errorf("%s", errStr)
|
| ... | ... |
@@ -461,13 +464,15 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 461 | 461 |
// This chain has the rules to allow access to the published ports for swarm tasks |
| 462 | 462 |
// from local bridge networks and docker_gwbridge (ie:taks on other swarm networks) |
| 463 | 463 |
func arrangeIngressFilterRule() {
|
| 464 |
- if iptables.ExistChain(ingressChain, iptables.Filter) {
|
|
| 465 |
- if iptables.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
|
|
| 466 |
- if err := iptables.RawCombinedOutput("-D", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 464 |
+ // TODO IPv6 support |
|
| 465 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 466 |
+ if iptable.ExistChain(ingressChain, iptables.Filter) {
|
|
| 467 |
+ if iptable.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
|
|
| 468 |
+ if err := iptable.RawCombinedOutput("-D", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 467 | 469 |
logrus.Warnf("failed to delete jump rule to ingressChain in filter table: %v", err)
|
| 468 | 470 |
} |
| 469 | 471 |
} |
| 470 |
- if err := iptables.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 472 |
+ if err := iptable.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 471 | 473 |
logrus.Warnf("failed to add jump rule to ingressChain in filter table: %v", err)
|
| 472 | 474 |
} |
| 473 | 475 |
} |
| ... | ... |
@@ -606,6 +611,8 @@ func invokeFWMarker(path string, vip net.IP, fwMark uint32, ingressPorts []*Port |
| 606 | 606 |
|
| 607 | 607 |
// Firewall marker reexec function. |
| 608 | 608 |
func fwMarker() {
|
| 609 |
+ // TODO IPv6 support |
|
| 610 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 609 | 611 |
runtime.LockOSThread() |
| 610 | 612 |
defer runtime.UnlockOSThread() |
| 611 | 613 |
|
| ... | ... |
@@ -660,7 +667,7 @@ func fwMarker() {
|
| 660 | 660 |
} |
| 661 | 661 |
|
| 662 | 662 |
ruleParams := strings.Fields(fmt.Sprintf("-m ipvs --ipvs -d %s -j SNAT --to-source %s", subnet, eIP))
|
| 663 |
- if !iptables.Exists("nat", "POSTROUTING", ruleParams...) {
|
|
| 663 |
+ if !iptable.Exists("nat", "POSTROUTING", ruleParams...) {
|
|
| 664 | 664 |
rule := append(strings.Fields("-t nat -A POSTROUTING"), ruleParams...)
|
| 665 | 665 |
rules = append(rules, rule) |
| 666 | 666 |
|
| ... | ... |
@@ -676,7 +683,7 @@ func fwMarker() {
|
| 676 | 676 |
rules = append(rules, rule) |
| 677 | 677 |
|
| 678 | 678 |
for _, rule := range rules {
|
| 679 |
- if err := iptables.RawCombinedOutputNative(rule...); err != nil {
|
|
| 679 |
+ if err := iptable.RawCombinedOutputNative(rule...); err != nil {
|
|
| 680 | 680 |
logrus.Errorf("set up rule failed, %v: %v", rule, err)
|
| 681 | 681 |
os.Exit(8) |
| 682 | 682 |
} |
| ... | ... |
@@ -711,6 +718,8 @@ func addRedirectRules(path string, eIP *net.IPNet, ingressPorts []*PortConfig) e |
| 711 | 711 |
|
| 712 | 712 |
// Redirector reexec function. |
| 713 | 713 |
func redirector() {
|
| 714 |
+ // TODO IPv6 support |
|
| 715 |
+ iptable := iptables.GetIptable(iptables.IPv4) |
|
| 714 | 716 |
runtime.LockOSThread() |
| 715 | 717 |
defer runtime.UnlockOSThread() |
| 716 | 718 |
|
| ... | ... |
@@ -763,7 +772,7 @@ func redirector() {
|
| 763 | 763 |
} |
| 764 | 764 |
|
| 765 | 765 |
for _, rule := range rules {
|
| 766 |
- if err := iptables.RawCombinedOutputNative(rule...); err != nil {
|
|
| 766 |
+ if err := iptable.RawCombinedOutputNative(rule...); err != nil {
|
|
| 767 | 767 |
logrus.Errorf("set up rule failed, %v: %v", rule, err)
|
| 768 | 768 |
os.Exit(6) |
| 769 | 769 |
} |
| ... | ... |
@@ -779,15 +788,15 @@ func redirector() {
|
| 779 | 779 |
{"-d", eIP.String(), "-p", "udp", "-j", "DROP"},
|
| 780 | 780 |
{"-d", eIP.String(), "-p", "tcp", "-j", "DROP"},
|
| 781 | 781 |
} {
|
| 782 |
- if !iptables.ExistsNative(iptables.Filter, "INPUT", rule...) {
|
|
| 783 |
- if err := iptables.RawCombinedOutputNative(append([]string{"-A", "INPUT"}, rule...)...); err != nil {
|
|
| 782 |
+ if !iptable.ExistsNative(iptables.Filter, "INPUT", rule...) {
|
|
| 783 |
+ if err := iptable.RawCombinedOutputNative(append([]string{"-A", "INPUT"}, rule...)...); err != nil {
|
|
| 784 | 784 |
logrus.Errorf("set up rule failed, %v: %v", rule, err)
|
| 785 | 785 |
os.Exit(7) |
| 786 | 786 |
} |
| 787 | 787 |
} |
| 788 | 788 |
rule[0] = "-s" |
| 789 |
- if !iptables.ExistsNative(iptables.Filter, "OUTPUT", rule...) {
|
|
| 790 |
- if err := iptables.RawCombinedOutputNative(append([]string{"-A", "OUTPUT"}, rule...)...); err != nil {
|
|
| 789 |
+ if !iptable.ExistsNative(iptables.Filter, "OUTPUT", rule...) {
|
|
| 790 |
+ if err := iptable.RawCombinedOutputNative(append([]string{"-A", "OUTPUT"}, rule...)...); err != nil {
|
|
| 791 | 791 |
logrus.Errorf("set up rule failed, %v: %v", rule, err)
|
| 792 | 792 |
os.Exit(8) |
| 793 | 793 |
} |