iptables/iptables.go (167 lines of code) (raw):

package iptables // This package contains wrapper functions to program iptables rules import ( "errors" "fmt" "github.com/Azure/azure-container-networking/cni/log" "github.com/Azure/azure-container-networking/platform" "go.uber.org/zap" ) var ( logger = log.CNILogger.With(zap.String("component", "cni-iptables")) errCouldNotValidateRuleExists = errors.New("could not validate iptable rule exists after insertion") ) // cni iptable chains const ( CNIInputChain = "AZURECNIINPUT" CNIOutputChain = "AZURECNIOUTPUT" ) // standard iptable chains const ( Input = "INPUT" Output = "OUTPUT" Forward = "FORWARD" Prerouting = "PREROUTING" Postrouting = "POSTROUTING" Swift = "SWIFT" Snat = "SNAT" Return = "RETURN" ) // Standard Table names const ( Filter = "filter" Nat = "nat" Mangle = "mangle" ) // target const ( Accept = "ACCEPT" Drop = "DROP" Masquerade = "MASQUERADE" ) // actions const ( Insert = "I" Append = "A" Delete = "D" ) // states const ( Established = "ESTABLISHED" Related = "RELATED" ) const ( iptables = "iptables" ip6tables = "ip6tables" lockTimeout = 60 ) const ( V4 = "4" V6 = "6" ) // known ports const ( DNSPort = 53 HTTPPort = 80 ) // known protocols const ( UDP = "udp" TCP = "tcp" ) var DisableIPTableLock bool type IPTableEntry struct { Version string Params string } type Client struct { pl platform.ExecClient } func NewClient() *Client { return &Client{ pl: platform.NewExecClient(logger), } } // Run iptables command func (c *Client) RunCmd(version, params string) error { var cmd string iptCmd := iptables if version == V6 { iptCmd = ip6tables } if DisableIPTableLock { cmd = fmt.Sprintf("%s %s", iptCmd, params) } else { cmd = fmt.Sprintf("%s -w %d %s", iptCmd, lockTimeout, params) } if _, err := c.pl.ExecuteRawCommand(cmd); err != nil { return err } return nil } // check if iptable chain alreay exists func (c *Client) ChainExists(version, tableName, chainName string) bool { params := fmt.Sprintf("-t %s -nL %s", tableName, chainName) if err := c.RunCmd(version, params); err != nil { return false } return true } func (c *Client) GetCreateChainCmd(version, tableName, chainName string) IPTableEntry { return IPTableEntry{ Version: version, Params: fmt.Sprintf("-t %s -N %s", tableName, chainName), } } // create new iptable chain under specified table name func (c *Client) CreateChain(version, tableName, chainName string) error { var err error if !c.ChainExists(version, tableName, chainName) { cmd := c.GetCreateChainCmd(version, tableName, chainName) err = c.RunCmd(version, cmd.Params) } else { logger.Info("Chain exists in table", zap.String("chainName", chainName), zap.String("tableName", tableName)) } return err } // check if iptable rule alreay exists func (c *Client) RuleExists(version, tableName, chainName, match, target string) bool { params := fmt.Sprintf("-t %s -C %s %s -j %s", tableName, chainName, match, target) if err := c.RunCmd(version, params); err != nil { return false } return true } func (c *Client) GetInsertIptableRuleCmd(version, tableName, chainName, match, target string) IPTableEntry { return IPTableEntry{ Version: version, Params: fmt.Sprintf("-t %s -I %s 1 %s -j %s", tableName, chainName, match, target), } } // Insert iptable rule at beginning of iptable chain func (c *Client) InsertIptableRule(version, tableName, chainName, match, target string) error { if c.RuleExists(version, tableName, chainName, match, target) { logger.Info("Rule already exists") return nil } cmd := c.GetInsertIptableRuleCmd(version, tableName, chainName, match, target) err := c.RunCmd(version, cmd.Params) if err != nil { return err } if !c.RuleExists(version, tableName, chainName, match, target) { return errCouldNotValidateRuleExists } return nil } func (c *Client) GetAppendIptableRuleCmd(version, tableName, chainName, match, target string) IPTableEntry { return IPTableEntry{ Version: version, Params: fmt.Sprintf("-t %s -A %s %s -j %s", tableName, chainName, match, target), } } // Append iptable rule at end of iptable chain func (c *Client) AppendIptableRule(version, tableName, chainName, match, target string) error { if c.RuleExists(version, tableName, chainName, match, target) { logger.Info("Rule already exists") return nil } cmd := c.GetAppendIptableRuleCmd(version, tableName, chainName, match, target) err := c.RunCmd(version, cmd.Params) if err != nil { return err } if !c.RuleExists(version, tableName, chainName, match, target) { return errCouldNotValidateRuleExists } return nil } // Delete matched iptable rule func (c *Client) DeleteIptableRule(version, tableName, chainName, match, target string) error { params := fmt.Sprintf("-t %s -D %s %s -j %s", tableName, chainName, match, target) return c.RunCmd(version, params) }