mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Move per-container forward rules to DOCKER chain
Docker-DCO-1.1-Signed-off-by: Ian Bishop <ianbishop@pace7.com> (github: porjo)
This commit is contained in:
parent
0874f9ab77
commit
cc89b30d35
4 changed files with 109 additions and 32 deletions
|
@ -6,6 +6,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
|
@ -501,35 +502,48 @@ func AllocatePort(job *engine.Job) engine.Status {
|
||||||
func LinkContainers(job *engine.Job) engine.Status {
|
func LinkContainers(job *engine.Job) engine.Status {
|
||||||
var (
|
var (
|
||||||
action = job.Args[0]
|
action = job.Args[0]
|
||||||
|
nfAction iptables.Action
|
||||||
childIP = job.Getenv("ChildIP")
|
childIP = job.Getenv("ChildIP")
|
||||||
parentIP = job.Getenv("ParentIP")
|
parentIP = job.Getenv("ParentIP")
|
||||||
ignoreErrors = job.GetenvBool("IgnoreErrors")
|
ignoreErrors = job.GetenvBool("IgnoreErrors")
|
||||||
ports = job.GetenvList("Ports")
|
ports = job.GetenvList("Ports")
|
||||||
|
chain = iptables.Chain{}
|
||||||
)
|
)
|
||||||
for _, value := range ports {
|
split := func(p string) (string, string) {
|
||||||
port := nat.Port(value)
|
parts := strings.Split(p, "/")
|
||||||
if output, err := iptables.Raw(action, "FORWARD",
|
return parts[0], parts[1]
|
||||||
"-i", bridgeIface, "-o", bridgeIface,
|
|
||||||
"-p", port.Proto(),
|
|
||||||
"-s", parentIP,
|
|
||||||
"--dport", strconv.Itoa(port.Int()),
|
|
||||||
"-d", childIP,
|
|
||||||
"-j", "ACCEPT"); !ignoreErrors && err != nil {
|
|
||||||
return job.Error(err)
|
|
||||||
} else if len(output) != 0 {
|
|
||||||
return job.Errorf("Error toggle iptables forward: %s", output)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if output, err := iptables.Raw(action, "FORWARD",
|
switch action {
|
||||||
"-i", bridgeIface, "-o", bridgeIface,
|
case "-A":
|
||||||
"-p", port.Proto(),
|
nfAction = iptables.Append
|
||||||
"-s", childIP,
|
case "-I":
|
||||||
"--sport", strconv.Itoa(port.Int()),
|
nfAction = iptables.Insert
|
||||||
"-d", parentIP,
|
case "-D":
|
||||||
"-j", "ACCEPT"); !ignoreErrors && err != nil {
|
nfAction = iptables.Delete
|
||||||
|
default:
|
||||||
|
return job.Errorf("Invalid action '%s' specified", action)
|
||||||
|
}
|
||||||
|
|
||||||
|
ip1 := net.ParseIP(parentIP)
|
||||||
|
if ip1 == nil {
|
||||||
|
return job.Errorf("parent IP '%s' is invalid", parentIP)
|
||||||
|
}
|
||||||
|
ip2 := net.ParseIP(childIP)
|
||||||
|
if ip2 == nil {
|
||||||
|
return job.Errorf("child IP '%s' is invalid", childIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.Name = "DOCKER"
|
||||||
|
chain.Bridge = bridgeIface
|
||||||
|
for _, p := range ports {
|
||||||
|
portStr, proto := split(p)
|
||||||
|
port, err := strconv.Atoi(portStr)
|
||||||
|
if !ignoreErrors && err != nil {
|
||||||
|
return job.Errorf("port '%s' is invalid", portStr)
|
||||||
|
}
|
||||||
|
if err := chain.Link(nfAction, ip1, ip2, port, proto); !ignoreErrors && err != nil {
|
||||||
return job.Error(err)
|
return job.Error(err)
|
||||||
} else if len(output) != 0 {
|
|
||||||
return job.Errorf("Error toggle iptables forward: %s", output)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return engine.StatusOK
|
return engine.StatusOK
|
||||||
|
|
|
@ -93,7 +93,7 @@ func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err er
|
||||||
}
|
}
|
||||||
|
|
||||||
containerIP, containerPort := getIPAndPort(m.container)
|
containerIP, containerPort := getIPAndPort(m.container)
|
||||||
if err := forward(iptables.Add, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
|
if err := forward(iptables.Append, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,8 @@ func (l *Link) getDefaultPort() *nat.Port {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Link) Enable() error {
|
func (l *Link) Enable() error {
|
||||||
if err := l.toggle("-I", false); err != nil {
|
// -A == iptables append flag
|
||||||
|
if err := l.toggle("-A", false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
l.IsEnabled = true
|
l.IsEnabled = true
|
||||||
|
@ -148,6 +149,7 @@ func (l *Link) Enable() error {
|
||||||
func (l *Link) Disable() {
|
func (l *Link) Disable() {
|
||||||
// We do not care about errors here because the link may not
|
// We do not care about errors here because the link may not
|
||||||
// exist in iptables
|
// exist in iptables
|
||||||
|
// -D == iptables delete flag
|
||||||
l.toggle("-D", true)
|
l.toggle("-D", true)
|
||||||
|
|
||||||
l.IsEnabled = false
|
l.IsEnabled = false
|
||||||
|
|
|
@ -15,8 +15,9 @@ import (
|
||||||
type Action string
|
type Action string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Add Action = "-A"
|
Append Action = "-A"
|
||||||
Delete Action = "-D"
|
Delete Action = "-D"
|
||||||
|
Insert Action = "-I"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -54,10 +55,10 @@ func NewChain(name, bridge string) (*Chain, error) {
|
||||||
Bridge: bridge,
|
Bridge: bridge,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := chain.Prerouting(Add, "-m", "addrtype", "--dst-type", "LOCAL"); err != nil {
|
if err := chain.Prerouting(Append, "-m", "addrtype", "--dst-type", "LOCAL"); err != nil {
|
||||||
return nil, fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
|
return nil, fmt.Errorf("Failed to inject docker in PREROUTING chain: %s", err)
|
||||||
}
|
}
|
||||||
if err := chain.Output(Add, "-m", "addrtype", "--dst-type", "LOCAL", "!", "--dst", "127.0.0.0/8"); err != nil {
|
if err := chain.Output(Append, "-m", "addrtype", "--dst-type", "LOCAL", "!", "--dst", "127.0.0.0/8"); err != nil {
|
||||||
return nil, fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
|
return nil, fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
|
||||||
}
|
}
|
||||||
return chain, nil
|
return chain, nil
|
||||||
|
@ -78,7 +79,7 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, dest_addr str
|
||||||
// value" by both iptables and ip6tables.
|
// value" by both iptables and ip6tables.
|
||||||
daddr = "0/0"
|
daddr = "0/0"
|
||||||
}
|
}
|
||||||
if output, err := Raw("-t", "nat", fmt.Sprint(action), c.Name,
|
if output, err := Raw("-t", "nat", string(action), c.Name,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
"-d", daddr,
|
"-d", daddr,
|
||||||
"--dport", strconv.Itoa(port),
|
"--dport", strconv.Itoa(port),
|
||||||
|
@ -90,11 +91,13 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, dest_addr str
|
||||||
return &ChainError{Chain: "FORWARD", Output: output}
|
return &ChainError{Chain: "FORWARD", Output: output}
|
||||||
}
|
}
|
||||||
|
|
||||||
fAction := action
|
if action != Delete {
|
||||||
if fAction == Add {
|
if err := c.createForwardChain(); err != nil {
|
||||||
fAction = "-I"
|
return err
|
||||||
}
|
}
|
||||||
if output, err := Raw(string(fAction), "FORWARD",
|
}
|
||||||
|
|
||||||
|
if output, err := Raw(string(action), c.Name,
|
||||||
"!", "-i", c.Bridge,
|
"!", "-i", c.Bridge,
|
||||||
"-o", c.Bridge,
|
"-o", c.Bridge,
|
||||||
"-p", proto,
|
"-p", proto,
|
||||||
|
@ -109,6 +112,39 @@ func (c *Chain) Forward(action Action, ip net.IP, port int, proto, dest_addr str
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Chain) Link(action Action, ip1, ip2 net.IP, port int, proto string) error {
|
||||||
|
if action != Delete {
|
||||||
|
if err := c.createForwardChain(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if output, err := Raw(string(action), c.Name,
|
||||||
|
"-i", c.Bridge, "-o", c.Bridge,
|
||||||
|
"-p", proto,
|
||||||
|
"-s", ip1.String(),
|
||||||
|
"--dport", strconv.Itoa(port),
|
||||||
|
"-d", ip2.String(),
|
||||||
|
"-j", "ACCEPT"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(output) != 0 {
|
||||||
|
return fmt.Errorf("Error toggle iptables forward: %s", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
if output, err := Raw(string(action), c.Name,
|
||||||
|
"-i", c.Bridge, "-o", c.Bridge,
|
||||||
|
"-p", proto,
|
||||||
|
"-s", ip2.String(),
|
||||||
|
"--dport", strconv.Itoa(port),
|
||||||
|
"-d", ip1.String(),
|
||||||
|
"-j", "ACCEPT"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(output) != 0 {
|
||||||
|
return fmt.Errorf("Error toggle iptables forward: %s", output)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Chain) Prerouting(action Action, args ...string) error {
|
func (c *Chain) Prerouting(action Action, args ...string) error {
|
||||||
a := append(nat, fmt.Sprint(action), "PREROUTING")
|
a := append(nat, fmt.Sprint(action), "PREROUTING")
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
|
@ -199,3 +235,28 @@ func Raw(args ...string) ([]byte, error) {
|
||||||
|
|
||||||
return output, err
|
return output, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Chain) createForwardChain() error {
|
||||||
|
// Add chain if doesn't exist
|
||||||
|
if _, err := Raw("-n", "-L", c.Name); err != nil {
|
||||||
|
output, err := Raw("-N", c.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(output) != 0 {
|
||||||
|
return fmt.Errorf("Error iptables forward: %s", output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add linking rule if it doesn't exist
|
||||||
|
if !Exists("FORWARD",
|
||||||
|
"-o", c.Bridge,
|
||||||
|
"-j", c.Name) {
|
||||||
|
if output2, err := Raw(string(Insert), "FORWARD",
|
||||||
|
"-o", c.Bridge,
|
||||||
|
"-j", c.Name); err != nil {
|
||||||
|
return err
|
||||||
|
} else if len(output2) != 0 {
|
||||||
|
return fmt.Errorf("Error iptables forward: %s", output2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue