func runIptables(iptablesCmd string, table Table, args ...string) ([]byte, error) {
	fullArgs := []string{
		"-w", iptablesWaitSeconds,
		"-W", iptablesWaitIntervalUseconds,
		"-t", string(table),
	}
	fullArgs = append(fullArgs, args...)
	cmd := exec.Command(iptablesCmd, fullArgs...)
	out, err := cmd.CombinedOutput()
	return out, err
}
Run iptables with lock
package iptables
import (
	"os/exec"
	"strings"
	"sync"
)
type Table string
const (
	iptablesCmdIPv4     = "iptables"
	iptablesCmdIPv6     = "ip6tables"
	iptablesSaveCmdIPv4 = "iptables-save"
	iptablesSaveCmdIPv6 = "ip6tables-save"
	iptablesWaitSeconds          = "5"
	iptablesWaitIntervalUseconds = "100000"
	iptablesErrNoRule   = "No chain/target/match by that name"
	iptablesErrNoTarget = "Couldn't load target"
	TableNAT    Table = "nat"
	TableFilter Table = "filter"
	TableRaw    Table = "raw"
)
var (
	lock = &sync.Mutex{}
)
func IsExistChainIPv4(table Table, chain string) bool {
	return isExistChain(iptablesCmdIPv4, table, chain)
}
func IsExistChainIPv6(table Table, chain string) bool {
	return isExistChain(iptablesCmdIPv6, table, chain)
}
func isExistChain(iptablesCmd string, table Table, chain string) bool {
	lock.Lock()
	defer lock.Unlock()
	_, err := runIptables(iptablesCmd, table, "-nL", chain)
	if err != nil {
		return false
	}
	return true
}
func CreateChainIPv4(table Table, chain string) (string, error) {
	return createChain(iptablesCmdIPv4, table, chain)
}
func CreateChainIPv6(table Table, chain string) (string, error) {
	return createChain(iptablesCmdIPv6, table, chain)
}
func createChain(iptablesCmd string, table Table, chain string) (string, error) {
	lock.Lock()
	defer lock.Unlock()
	out, err := runIptables(iptablesCmd, table, "-nL", chain)
	if err == nil {
		return string(out), nil
	}
	out, err = runIptables(iptablesCmd, table, "-N", chain)
	if err != nil {
		return string(out), err
	}
	return string(out), nil
}
func DeleteChainIPv4(table Table, chain string) (string, error) {
	return deleteChain(iptablesCmdIPv4, table, chain)
}
func DeleteChainIPv6(table Table, chain string) (string, error) {
	return deleteChain(iptablesCmdIPv6, table, chain)
}
func deleteChain(iptablesCmd string, table Table, chain string) (string, error) {
	lock.Lock()
	defer lock.Unlock()
	out, err := runIptables(iptablesCmd, table, "-nL", chain)
	if err != nil {
		return string(out), nil
	}
	out, err = runIptables(iptablesCmd, table, "-F", chain)
	if err != nil {
		return string(out), err
	}
	out, err = runIptables(iptablesCmd, table, "-X", chain)
	if err != nil {
		return string(out), err
	}
	return string(out), nil
}
func IsExistRuleIPv4(table Table, chain string, comment string, rule ...string) bool {
	return isExistRule(iptablesCmdIPv4, table, chain, comment, rule...)
}
func IsExistRuleIPv6(table Table, chain string, comment string, rule ...string) bool {
	return isExistRule(iptablesCmdIPv6, table, chain, comment, rule...)
}
func isExistRule(iptablesCmd string, table Table, chain string, comment string, rule ...string) bool {
	lock.Lock()
	defer lock.Unlock()
	args := []string{"-C", chain}
	if comment != "" {
		args = append(args, "-m", "comment", "--comment", comment)
	}
	_, err := runIptables(iptablesCmd, table, append(args, rule...)...)
	if err != nil {
		return false
	}
	return true
}
func GetRulesIPv4(table Table, chain string) ([]string, error) {
	return getRules(iptablesSaveCmdIPv4, table, chain)
}
func GetRulesIPv6(table Table, chain string) ([]string, error) {
	return getRules(iptablesSaveCmdIPv6, table, chain)
}
func getRules(iptablesSaveCmd string, table Table, chain string) ([]string, error) {
	lock.Lock()
	defer lock.Unlock()
	args := []string{"-t", string(table)}
	cmd := exec.Command(iptablesSaveCmd, args...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, err
	}
	var result []string
	for _, rule := range strings.Split(string(out), "\n") {
		if strings.HasPrefix(rule, "-A "+chain) {
			result = append(result, rule)
		}
	}
	return result, nil
}
func CreateRuleFirstIPv4(table Table, chain string, comment string, rule ...string) (string, error) {
	return createRuleFirst(iptablesCmdIPv4, table, chain, comment, rule...)
}
func CreateRuleFirstIPv6(table Table, chain string, comment string, rule ...string) (string, error) {
	return createRuleFirst(iptablesCmdIPv6, table, chain, comment, rule...)
}
func createRuleFirst(iptablesCmd string, table Table, chain string, comment string, rule ...string) (string, error) {
	lock.Lock()
	defer lock.Unlock()
	args := []string{}
	if comment != "" {
		args = append(args, "-m", "comment", "--comment", comment)
	}
	out, err := runIptables(iptablesCmd, table, append(append(args, "-C", chain), rule...)...)
	if err == nil {  
		return string(out), nil
	}
	out, err = runIptables(iptablesCmd, table, append(append(args, "-I", chain, "1"), rule...)...)
	if err != nil {
		return string(out), err
	}
	return string(out), nil
}
func CreateRuleLastIPv4(table Table, chain string, comment string, rule ...string) (string, error) {
	return createRuleLast(iptablesCmdIPv4, table, chain, comment, rule...)
}
func CreateRuleLastIPv6(table Table, chain string, comment string, rule ...string) (string, error) {
	return createRuleLast(iptablesCmdIPv6, table, chain, comment, rule...)
}
func createRuleLast(iptablesCmd string, table Table, chain string, comment string, rule ...string) (string, error) {
	lock.Lock()
	defer lock.Unlock()
	args := []string{}
	if comment != "" {
		args = append(args, "-m", "comment", "--comment", comment)
	}
	out, err := runIptables(iptablesCmd, table, append(append(args, "-C", chain), rule...)...)
	if err == nil {
		return string(out), nil
	}
	out, err = runIptables(iptablesCmd, table, append(append(args, "-A", chain), rule...)...)
	if err != nil {
		return string(out), err
	}
	return string(out), nil
}
func DeleteRuleIPv4(table Table, chain string, comment string, rule ...string) (string, error) {
	return deleteRule(iptablesCmdIPv4, table, chain, comment, rule...)
}
func DeleteRuleIPv6(table Table, chain string, comment string, rule ...string) (string, error) {
	return deleteRule(iptablesCmdIPv6, table, chain, comment, rule...)
}
func deleteRule(iptablesCmd string, table Table, chain string, comment string, rule ...string) (string, error) {
	lock.Lock()
	defer lock.Unlock()
	args := []string{}
	if comment != "" {
		args = append(args, "-m", "comment", "--comment", comment)
	}
	out, err := runIptables(iptablesCmd, table, append(append(args, "-C", chain), rule...)...)
	if err != nil {
		if strings.Contains(string(out), iptablesErrNoRule) {
			return string(out), nil
		} else if strings.Contains(string(out), iptablesErrNoTarget) {
			return string(out), nil
		}
		return string(out), err
	}
	out, err = runIptables(iptablesCmd, table, append(append(args, "-D", chain), rule...)...)
	if err != nil {
		return string(out), err
	}
	return string(out), nil
}
func DeleteRuleRawIPv4(table Table, rule ...string) (string, error) {
	return deleteRuleRaw(iptablesCmdIPv4, table, rule...)
}
func DeleteRuleRawIPv6(table Table, rule ...string) (string, error) {
	return deleteRuleRaw(iptablesCmdIPv6, table, rule...)
}
func deleteRuleRaw(iptablesCmd string, table Table, rule ...string) (string, error) {
	lock.Lock()
	defer lock.Unlock()
	out, err := runIptables(iptablesCmd, table, append([]string{"-C"}, rule...)...)
	if err != nil {
		if strings.Contains(string(out), iptablesErrNoRule) {
			return string(out), nil
		}
		return string(out), err
	}
	out, err = runIptables(iptablesCmd, table, append([]string{"-D"}, rule...)...)
	if err != nil {
		return string(out), err
	}
	return string(out), nil
}