mirror of
https://github.com/qdm12/gluetun.git
synced 2026-08-11 14:52:56 +02:00
RunUserPostRules uses nft cli
This commit is contained in:
+1
-1
@@ -243,7 +243,7 @@ RUN apk add --no-cache --update -l wget && \
|
|||||||
apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.17/main" openvpn\~2.5 && \
|
apk add --no-cache --update -X "https://dl-cdn.alpinelinux.org/alpine/v3.17/main" openvpn\~2.5 && \
|
||||||
mv /usr/sbin/openvpn /usr/sbin/openvpn2.5 && \
|
mv /usr/sbin/openvpn /usr/sbin/openvpn2.5 && \
|
||||||
apk del openvpn && \
|
apk del openvpn && \
|
||||||
apk add --no-cache --update openvpn ca-certificates iptables iptables-legacy tzdata && \
|
apk add --no-cache --update openvpn ca-certificates nftables iptables iptables-legacy tzdata && \
|
||||||
mv /usr/sbin/openvpn /usr/sbin/openvpn2.6 && \
|
mv /usr/sbin/openvpn /usr/sbin/openvpn2.6 && \
|
||||||
rm -rf /var/cache/apk/* /etc/openvpn/*.sh /usr/lib/openvpn/plugins/openvpn-plugin-down-root.so && \
|
rm -rf /var/cache/apk/* /etc/openvpn/*.sh /usr/lib/openvpn/plugins/openvpn-plugin-down-root.so && \
|
||||||
deluser openvpn && \
|
deluser openvpn && \
|
||||||
|
|||||||
@@ -12,13 +12,6 @@ import (
|
|||||||
"github.com/google/nftables"
|
"github.com/google/nftables"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
iptablesCommand = "iptables-nft"
|
|
||||||
iptablesFallbackCmd = "iptables"
|
|
||||||
ip6tablesCommand = "ip6tables-nft"
|
|
||||||
ip6tablesFallbackCmd = "ip6tables"
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsSupported() bool {
|
func IsSupported() bool {
|
||||||
conn, err := nftables.New()
|
conn, err := nftables.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -44,31 +37,9 @@ func (f *Firewall) Version(ctx context.Context) (string, error) {
|
|||||||
return words[0], nil
|
return words[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// findIptablesCommand finds the available iptables-nft or iptables command.
|
// RunUserPostRules reads and executes custom nft commands from a file.
|
||||||
func findIptablesCommand() (string, error) {
|
// Only lines starting with "nft" are executed. Lines starting with iptables
|
||||||
if path, err := exec.LookPath(iptablesCommand); err == nil {
|
// commands are rejected with an error.
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
if path, err := exec.LookPath(iptablesFallbackCmd); err == nil {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("iptables command not found: %s or %s", iptablesCommand, iptablesFallbackCmd) //nolint:err113
|
|
||||||
}
|
|
||||||
|
|
||||||
// findIP6tablesCommand finds the available ip6tables-nft or ip6tables command.
|
|
||||||
func findIP6tablesCommand() (string, error) {
|
|
||||||
if path, err := exec.LookPath(ip6tablesCommand); err == nil {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
if path, err := exec.LookPath(ip6tablesFallbackCmd); err == nil {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("ip6tables command not found: %s or %s", ip6tablesCommand, ip6tablesFallbackCmd) //nolint:err113
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunUserPostRules reads and executes custom iptables-style rules from a file.
|
|
||||||
// Since iptables-nft is nftables under the hood, we delegate to it for rule
|
|
||||||
// parsing compatibility with user-written iptables rules.
|
|
||||||
func (f *Firewall) RunUserPostRules(ctx context.Context, filepath string) error {
|
func (f *Firewall) RunUserPostRules(ctx context.Context, filepath string) error {
|
||||||
file, err := os.OpenFile(filepath, os.O_RDONLY, 0)
|
file, err := os.OpenFile(filepath, os.O_RDONLY, 0)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
@@ -86,61 +57,41 @@ func (f *Firewall) RunUserPostRules(ctx context.Context, filepath string) error
|
|||||||
}
|
}
|
||||||
lines := strings.Split(string(content), "\n")
|
lines := strings.Split(string(content), "\n")
|
||||||
|
|
||||||
iptablesCmd, err := findIptablesCommand()
|
|
||||||
if err != nil {
|
|
||||||
f.logger.Warnf("iptables-nft not available, skipping user post-rules for IPv4")
|
|
||||||
}
|
|
||||||
ip6tablesCmd, err := findIP6tablesCommand()
|
|
||||||
if err != nil {
|
|
||||||
f.logger.Warnf("ip6tables-nft not available, IPv6 user post-rules will fail")
|
|
||||||
}
|
|
||||||
|
|
||||||
for lineNum, line := range lines {
|
for lineNum, line := range lines {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
if line == "" || strings.HasPrefix(line, "#") {
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdName string
|
// Only allow nft commands
|
||||||
var ruleArgs string
|
if !strings.HasPrefix(line, "nft") {
|
||||||
switch {
|
f.logger.Warnf("line %d: skipping unrecognized command (expected nft): %s", lineNum+1, line)
|
||||||
case strings.HasPrefix(line, "iptables "):
|
|
||||||
cmdName = iptablesCmd
|
|
||||||
ruleArgs = strings.TrimPrefix(line, "iptables ")
|
|
||||||
case strings.HasPrefix(line, "iptables-nft "):
|
|
||||||
cmdName = iptablesCmd
|
|
||||||
ruleArgs = strings.TrimPrefix(line, "iptables-nft ")
|
|
||||||
case strings.HasPrefix(line, "iptables-legacy "):
|
|
||||||
cmdName = iptablesCmd
|
|
||||||
ruleArgs = strings.TrimPrefix(line, "iptables-legacy ")
|
|
||||||
case strings.HasPrefix(line, "ip6tables "):
|
|
||||||
cmdName = ip6tablesCmd
|
|
||||||
ruleArgs = strings.TrimPrefix(line, "ip6tables ")
|
|
||||||
case strings.HasPrefix(line, "ip6tables-nft "):
|
|
||||||
cmdName = ip6tablesCmd
|
|
||||||
ruleArgs = strings.TrimPrefix(line, "ip6tables-nft ")
|
|
||||||
case strings.HasPrefix(line, "ip6tables-legacy "):
|
|
||||||
cmdName = ip6tablesCmd
|
|
||||||
ruleArgs = strings.TrimPrefix(line, "ip6tables-legacy ")
|
|
||||||
default:
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmdName == "" {
|
// Ensure we're matching "nft" as a complete command prefix (not "nftables", "nftrace", etc.)
|
||||||
|
if len(line) > 3 && line[3] != ' ' {
|
||||||
|
f.logger.Warnf("line %d: skipping unrecognized command (expected nft): %s", lineNum+1, line)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
args := strings.Fields(ruleArgs)
|
// Extract nft arguments
|
||||||
|
nftArgs := strings.TrimSpace(line[3:]) // Trim "nft" and leading space
|
||||||
|
if nftArgs == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
args := strings.Fields(nftArgs)
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, cmdName, args...)
|
cmd := exec.CommandContext(ctx, "nft", args...)
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
outputStr := strings.TrimSpace(string(output))
|
outputStr := strings.TrimSpace(string(output))
|
||||||
return fmt.Errorf("running user rule on line %d (%s %s): %w: %s",
|
return fmt.Errorf("running user rule on line %d (nft %s): %w: %s",
|
||||||
lineNum+1, cmdName, ruleArgs, err, outputStr)
|
lineNum+1, nftArgs, err, outputStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user