mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
|
package iptables
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"os/exec"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type Action string
|
||
|
|
||
|
const (
|
||
|
Add Action = "-A"
|
||
|
Delete Action = "-D"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
ErrIptablesNotFound = errors.New("Iptables not found")
|
||
|
nat = []string{"-t", "nat"}
|
||
|
)
|
||
|
|
||
|
type Chain struct {
|
||
|
Name string
|
||
|
Bridge string
|
||
|
}
|
||
|
|
||
|
func NewChain(name, bridge string) (*Chain, error) {
|
||
|
if err := Raw("-t", "nat", "-N", name); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
chain := &Chain{
|
||
|
Name: name,
|
||
|
Bridge: bridge,
|
||
|
}
|
||
|
|
||
|
if err := chain.Prerouting(Add, "-m", "addrtype", "--dst-type", "LOCAL"); err != nil {
|
||
|
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 {
|
||
|
return nil, fmt.Errorf("Failed to inject docker in OUTPUT chain: %s", err)
|
||
|
}
|
||
|
return chain, nil
|
||
|
}
|
||
|
|
||
|
func RemoveExistingChain(name string) error {
|
||
|
chain := &Chain{
|
||
|
Name: name,
|
||
|
}
|
||
|
return chain.Remove()
|
||
|
}
|
||
|
|
||
|
func (c *Chain) Forward(action Action, ip net.IP, port int, proto, dest_addr string, dest_port int) error {
|
||
|
return Raw("-t", "nat", fmt.Sprint(action), c.Name,
|
||
|
"-p", proto,
|
||
|
"-d", ip.String(),
|
||
|
"--dport", strconv.Itoa(port),
|
||
|
"!", "-i", c.Bridge,
|
||
|
"-j", "DNAT",
|
||
|
"--to-destination", net.JoinHostPort(dest_addr, strconv.Itoa(dest_port)))
|
||
|
}
|
||
|
|
||
|
func (c *Chain) Prerouting(action Action, args ...string) error {
|
||
|
a := append(nat, fmt.Sprint(action), "PREROUTING")
|
||
|
if len(args) > 0 {
|
||
|
a = append(a, args...)
|
||
|
}
|
||
|
return Raw(append(a, "-j", c.Name)...)
|
||
|
}
|
||
|
|
||
|
func (c *Chain) Output(action Action, args ...string) error {
|
||
|
a := append(nat, fmt.Sprint(action), "OUTPUT")
|
||
|
if len(args) > 0 {
|
||
|
a = append(a, args...)
|
||
|
}
|
||
|
return Raw(append(a, "-j", c.Name)...)
|
||
|
}
|
||
|
|
||
|
func (c *Chain) Remove() error {
|
||
|
// Ignore errors - This could mean the chains were never set up
|
||
|
c.Prerouting(Delete, "-m", "addrtype", "--dst-type", "LOCAL")
|
||
|
c.Output(Delete, "-m", "addrtype", "--dst-type", "LOCAL", "!", "--dst", "127.0.0.0/8")
|
||
|
c.Output(Delete, "-m", "addrtype", "--dst-type", "LOCAL") // Created in versions <= 0.1.6
|
||
|
|
||
|
c.Prerouting(Delete)
|
||
|
c.Output(Delete)
|
||
|
|
||
|
Raw("-t", "nat", "-F", c.Name)
|
||
|
Raw("-t", "nat", "-X", c.Name)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func Raw(args ...string) error {
|
||
|
path, err := exec.LookPath("iptables")
|
||
|
if err != nil {
|
||
|
return ErrIptablesNotFound
|
||
|
}
|
||
|
if err := exec.Command(path, args...).Run(); err != nil {
|
||
|
return fmt.Errorf("iptables failed: iptables %v", strings.Join(args, " "))
|
||
|
}
|
||
|
return nil
|
||
|
|
||
|
}
|