github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/linux_container/iptables_manager/filter.go (about)

     1  package iptables_manager
     2  
     3  import (
     4  	"net"
     5  
     6  	"os/exec"
     7  
     8  	"fmt"
     9  
    10  	"bytes"
    11  	"io/ioutil"
    12  
    13  	"github.com/cloudfoundry-incubator/garden-linux/sysconfig"
    14  	"github.com/cloudfoundry/gunk/command_runner"
    15  	"github.com/pivotal-golang/lager"
    16  )
    17  
    18  type filterChain struct {
    19  	cfg    *sysconfig.IPTablesFilterConfig
    20  	runner command_runner.CommandRunner
    21  	logger lager.Logger
    22  }
    23  
    24  func NewFilterChain(cfg *sysconfig.IPTablesFilterConfig, runner command_runner.CommandRunner, logger lager.Logger) *filterChain {
    25  	return &filterChain{
    26  		cfg:    cfg,
    27  		runner: runner,
    28  		logger: logger,
    29  	}
    30  }
    31  
    32  func (mgr *filterChain) Setup(containerID, bridgeName string, ip net.IP, network *net.IPNet) error {
    33  	instanceChain := mgr.cfg.InstancePrefix + containerID
    34  
    35  	commands := []*exec.Cmd{
    36  		// Create filter instance chain
    37  		exec.Command("iptables", "--wait", "-N", instanceChain),
    38  		// Allow intra-subnet traffic (Linux ethernet bridging goes through ip stack)
    39  		exec.Command("iptables", "--wait", "-A", instanceChain, "-s", network.String(), "-d", network.String(), "-j", "ACCEPT"),
    40  		// Otherwise, use the default filter chain
    41  		exec.Command("iptables", "--wait", "-A", instanceChain, "--goto", mgr.cfg.DefaultChain),
    42  		// Bind filter instance chain to filter forward chain
    43  		exec.Command("iptables", "--wait", "-I", mgr.cfg.ForwardChain, "2", "--in-interface", bridgeName, "--source", ip.String(), "--goto", instanceChain),
    44  	}
    45  
    46  	for _, cmd := range commands {
    47  		buffer := &bytes.Buffer{}
    48  		cmd.Stderr = buffer
    49  		logger := mgr.logger.Session("setup", lager.Data{"cmd": cmd})
    50  		logger.Debug("starting")
    51  		if err := mgr.runner.Run(cmd); err != nil {
    52  			stderr, _ := ioutil.ReadAll(buffer)
    53  			logger.Error("failed", err, lager.Data{"stderr": string(stderr)})
    54  			return fmt.Errorf("iptables_manager: filter: %s", err)
    55  		}
    56  		logger.Debug("ended")
    57  	}
    58  
    59  	return nil
    60  }
    61  
    62  func (mgr *filterChain) Teardown(containerID string) error {
    63  	instanceChain := mgr.cfg.InstancePrefix + containerID
    64  
    65  	commands := []*exec.Cmd{
    66  		// Prune forward chain
    67  		exec.Command("sh", "-c", fmt.Sprintf(
    68  			`iptables --wait -S %s 2> /dev/null | grep "\-g %s\b" | sed -e "s/-A/-D/" | xargs --no-run-if-empty --max-lines=1 iptables --wait`,
    69  			mgr.cfg.ForwardChain, instanceChain,
    70  		)),
    71  		// Flush instance chain
    72  		exec.Command("sh", "-c", fmt.Sprintf("iptables --wait -F %s 2> /dev/null || true", instanceChain)),
    73  		// Delete instance chain
    74  		exec.Command("sh", "-c", fmt.Sprintf("iptables --wait -X %s 2> /dev/null || true", instanceChain)),
    75  	}
    76  
    77  	for _, cmd := range commands {
    78  		buffer := &bytes.Buffer{}
    79  		cmd.Stderr = buffer
    80  		logger := mgr.logger.Session("teardown", lager.Data{"cmd": cmd})
    81  		logger.Debug("starting")
    82  		if err := mgr.runner.Run(cmd); err != nil {
    83  			stderr, _ := ioutil.ReadAll(buffer)
    84  			logger.Error("failed", err, lager.Data{"stderr": string(stderr)})
    85  			return fmt.Errorf("iptables_manager: filter: %s", err)
    86  		}
    87  		logger.Debug("ended")
    88  	}
    89  
    90  	return nil
    91  }