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