mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 16:00:51 +00:00
167 lines
5.2 KiB
Go
167 lines
5.2 KiB
Go
package iptables_helper
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/1Panel-dev/1Panel/agent/constant"
|
|
"github.com/1Panel-dev/1Panel/agent/global"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/firewall/filter"
|
|
"github.com/1Panel-dev/1Panel/agent/utils/firewall/lifecycle"
|
|
)
|
|
|
|
const (
|
|
InputChain = "INPUT"
|
|
BasicBeforeChain = constant.FirewallBasicBeforeChain
|
|
BasicChain = constant.FirewallBasicChain
|
|
BasicAfterChain = constant.FirewallBasicAfterChain
|
|
)
|
|
|
|
func BasicChains() []string {
|
|
return []string{BasicBeforeChain, BasicChain, BasicAfterChain}
|
|
}
|
|
|
|
const (
|
|
EstablishedRule = "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment \"ESTABLISHED Whitelist\""
|
|
IoRuleIn = "-i lo -j ACCEPT -m comment --comment \"Loopback Whitelist\""
|
|
DropAllTcp = "-p tcp -j DROP"
|
|
DropAllUdp = "-p udp -j DROP"
|
|
AllowSSH = "-p tcp --dport ssh -j ACCEPT"
|
|
)
|
|
|
|
const (
|
|
ACCEPT = "ACCEPT"
|
|
DROP = "DROP"
|
|
REJECT = "REJECT"
|
|
ANYWHERE = "anywhere"
|
|
)
|
|
|
|
const (
|
|
FilterTab = "filter"
|
|
NatTab = "nat"
|
|
)
|
|
|
|
func runTables(ctx context.Context, executable, tab string, ignoreExist1, withWait bool, ruleArgs ...string) (string, error) {
|
|
options := []cmd.Option{cmd.WithContext(ctx), cmd.WithTimeout(60 * time.Second)}
|
|
if ignoreExist1 {
|
|
options = append(options, cmd.WithIgnoreExist1())
|
|
}
|
|
cmdMgr := cmd.NewCommandMgr(options...)
|
|
args := []string{"-t", tab}
|
|
if withWait {
|
|
args = append(args, "-w")
|
|
}
|
|
args = append(args, ruleArgs...)
|
|
stdout, err := cmdMgr.RunWithOptionalSudoAndStdout(executable, args...)
|
|
if err != nil {
|
|
return stdout, fmt.Errorf("command=%s %s failed: %w", executable, strings.Join(args, " "), err)
|
|
}
|
|
return stdout, nil
|
|
}
|
|
|
|
func runIptables(ctx context.Context, tab string, ignoreExist1, withWait bool, ruleArgs ...string) (string, error) {
|
|
commands, err := lifecycle.ResolveIptablesCommands()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return runTables(ctx, commands.IPv4, tab, ignoreExist1, withWait, ruleArgs...)
|
|
}
|
|
|
|
func RunWithStd(tab string, args ...string) (string, error) {
|
|
return RunWithStdContext(context.Background(), tab, args...)
|
|
}
|
|
|
|
func RunWithStdContext(ctx context.Context, tab string, args ...string) (string, error) {
|
|
stdout, err := runIptables(ctx, tab, true, true, args...)
|
|
if err != nil {
|
|
global.LOG.Errorf("iptables command failed [table=%s, args=%s]: %v", tab, strings.Join(args, " "), err)
|
|
return stdout, err
|
|
}
|
|
return stdout, nil
|
|
}
|
|
|
|
func RunIPv6WithStd(tab string, args ...string) (string, error) {
|
|
return RunIPv6WithStdContext(context.Background(), tab, args...)
|
|
}
|
|
|
|
func RunIPv6WithStdContext(ctx context.Context, tab string, args ...string) (string, error) {
|
|
commands, executableErr := lifecycle.ResolveIptablesCommands()
|
|
if executableErr != nil {
|
|
return "", executableErr
|
|
}
|
|
if !commands.IPv6Available() {
|
|
return "", fmt.Errorf("%w: ip6tables/ip6tables-restore are not installed", filter.ErrFamilyUnavailable)
|
|
}
|
|
ignoreExist1 := len(args) == 0 || (args[0] != "-S" && args[0] != "-L" && args[0] != "-nL")
|
|
stdout, err := runTables(ctx, commands.IPv6, tab, ignoreExist1, true, args...)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "Address family not supported") || strings.Contains(err.Error(), "Protocol not supported") {
|
|
return stdout, fmt.Errorf("%w: %v", filter.ErrFamilyUnavailable, err)
|
|
}
|
|
global.LOG.Errorf("ip6tables command failed [table=%s, args=%s]: %v", tab, strings.Join(args, " "), err)
|
|
return stdout, err
|
|
}
|
|
return stdout, nil
|
|
}
|
|
|
|
func RunIPv6(tab string, args ...string) error {
|
|
_, err := RunIPv6WithStd(tab, args...)
|
|
return err
|
|
}
|
|
|
|
func CheckIPv6ChainExist(tab, chain string) (bool, error) {
|
|
stdout, err := RunIPv6WithStd(tab, "-S")
|
|
if err != nil {
|
|
return false, fmt.Errorf("check IPv6 chain %s from tab %s exist failed: %w", chain, tab, err)
|
|
}
|
|
for _, line := range strings.Split(stdout, "\n") {
|
|
if strings.TrimSpace(line) == "-N "+chain {
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
func Run(tab string, args ...string) error {
|
|
if _, err := RunWithStd(tab, args...); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func CheckChainExist(tab, chain string) (bool, error) {
|
|
stdout, err := RunWithStd(tab, "-S")
|
|
if err != nil {
|
|
global.LOG.Errorf("check chain %s from tab %s exist failed, err: %v", chain, tab, err)
|
|
return false, fmt.Errorf("check chain %s from tab %s exist failed, err: %v", chain, tab, err)
|
|
}
|
|
for _, line := range strings.Split(stdout, "\n") {
|
|
if strings.TrimSpace(line) == "-N "+chain {
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
func ReadTable(ctx context.Context, table string, ipv6 bool) (string, error) {
|
|
commands, err := lifecycle.ResolveIptablesCommands()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
executable := commands.IPv4
|
|
if ipv6 {
|
|
if !commands.IPv6Available() {
|
|
return "", fmt.Errorf("%w: ip6tables/ip6tables-restore are not installed", filter.ErrFamilyUnavailable)
|
|
}
|
|
executable = commands.IPv6
|
|
}
|
|
output, err := runTables(ctx, executable, table, false, true, "-S")
|
|
if err != nil && ipv6 && (strings.Contains(err.Error(), "Address family not supported") || strings.Contains(err.Error(), "Protocol not supported")) {
|
|
return output, fmt.Errorf("%w: %v", filter.ErrFamilyUnavailable, err)
|
|
}
|
|
return output, err
|
|
}
|