|
|
@@ -3,9 +3,12 @@ package firewall
|
|
|
import (
|
|
|
"bufio"
|
|
|
"bytes"
|
|
|
+ "encoding/json"
|
|
|
"fmt"
|
|
|
"hash/fnv"
|
|
|
+ "os"
|
|
|
"os/exec"
|
|
|
+ "sort"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
)
|
|
|
@@ -63,7 +66,8 @@ func ReadRuleCounters(filterRules []FilterRule, natRules []NATRule, mangleRules
|
|
|
endQuote := strings.Index(sub, "\"")
|
|
|
if endQuote != -1 {
|
|
|
ruleID := sub[:endQuote]
|
|
|
- counters[ruleID] = [2]uint64{pkts, bts}
|
|
|
+ existing := counters[ruleID]
|
|
|
+ counters[ruleID] = [2]uint64{existing[0] + pkts, existing[1] + bts}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -71,6 +75,69 @@ func ReadRuleCounters(filterRules []FilterRule, natRules []NATRule, mangleRules
|
|
|
return counters, nil
|
|
|
}
|
|
|
|
|
|
+// resolveInterfaceList resolves an interface list or role name (e.g. "WAN", "LAN") to interface names.
|
|
|
+func resolveInterfaceList(listName string) []string {
|
|
|
+ listName = strings.TrimSpace(listName)
|
|
|
+ if listName == "" {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ data, err := os.ReadFile("/etc/proxmox-router/metadata.json")
|
|
|
+ if err != nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ var meta struct {
|
|
|
+ Interfaces map[string]struct {
|
|
|
+ Role string `json:"role"`
|
|
|
+ } `json:"interfaces"`
|
|
|
+ }
|
|
|
+ if err := json.Unmarshal(data, &meta); err != nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ var matched []string
|
|
|
+ for ifaceName, info := range meta.Interfaces {
|
|
|
+ if strings.EqualFold(info.Role, listName) {
|
|
|
+ matched = append(matched, ifaceName)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sort.Strings(matched)
|
|
|
+ return matched
|
|
|
+}
|
|
|
+
|
|
|
+func getInterfaceCombinations(inIface, inList, outIface, outList string) [][2]string {
|
|
|
+ var inListResolved []string
|
|
|
+ if inIface != "" {
|
|
|
+ inListResolved = []string{inIface}
|
|
|
+ } else if inList != "" {
|
|
|
+ inListResolved = resolveInterfaceList(inList)
|
|
|
+ } else {
|
|
|
+ inListResolved = []string{""}
|
|
|
+ }
|
|
|
+
|
|
|
+ var outListResolved []string
|
|
|
+ if outIface != "" {
|
|
|
+ outListResolved = []string{outIface}
|
|
|
+ } else if outList != "" {
|
|
|
+ outListResolved = resolveInterfaceList(outList)
|
|
|
+ } else {
|
|
|
+ outListResolved = []string{""}
|
|
|
+ }
|
|
|
+
|
|
|
+ if inList != "" && inIface == "" && len(inListResolved) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ if outList != "" && outIface == "" && len(outListResolved) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ var combos [][2]string
|
|
|
+ for _, in := range inListResolved {
|
|
|
+ for _, out := range outListResolved {
|
|
|
+ combos = append(combos, [2]string{in, out})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return combos
|
|
|
+}
|
|
|
+
|
|
|
// BuildIPTablesRestore generates the atomic configuration for `iptables-restore`
|
|
|
func BuildIPTablesRestore(filterRules []FilterRule, natRules []NATRule, mangleRules []MangleRule) string {
|
|
|
var sb strings.Builder
|
|
|
@@ -106,9 +173,10 @@ func BuildIPTablesRestore(filterRules []FilterRule, natRules []NATRule, mangleRu
|
|
|
if r.Disabled {
|
|
|
continue
|
|
|
}
|
|
|
- ruleStr := buildMangleRuleLine(r)
|
|
|
- if ruleStr != "" {
|
|
|
- sb.WriteString(ruleStr + "\n")
|
|
|
+ for _, line := range buildMangleRuleLines(r) {
|
|
|
+ if line != "" {
|
|
|
+ sb.WriteString(line + "\n")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
sb.WriteString("COMMIT\n")
|
|
|
@@ -142,9 +210,10 @@ func BuildIPTablesRestore(filterRules []FilterRule, natRules []NATRule, mangleRu
|
|
|
if r.Disabled {
|
|
|
continue
|
|
|
}
|
|
|
- ruleStr := buildNATRuleLine(r)
|
|
|
- if ruleStr != "" {
|
|
|
- sb.WriteString(ruleStr + "\n")
|
|
|
+ for _, line := range buildNATRuleLines(r) {
|
|
|
+ if line != "" {
|
|
|
+ sb.WriteString(line + "\n")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
sb.WriteString("COMMIT\n")
|
|
|
@@ -177,9 +246,10 @@ func BuildIPTablesRestore(filterRules []FilterRule, natRules []NATRule, mangleRu
|
|
|
if r.Disabled {
|
|
|
continue
|
|
|
}
|
|
|
- ruleStr := buildFilterRuleLine(r)
|
|
|
- if ruleStr != "" {
|
|
|
- sb.WriteString(ruleStr + "\n")
|
|
|
+ for _, line := range buildFilterRuleLines(r) {
|
|
|
+ if line != "" {
|
|
|
+ sb.WriteString(line + "\n")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
sb.WriteString("COMMIT\n")
|
|
|
@@ -187,63 +257,80 @@ func BuildIPTablesRestore(filterRules []FilterRule, natRules []NATRule, mangleRu
|
|
|
return sb.String()
|
|
|
}
|
|
|
|
|
|
-func buildFilterRuleLine(r FilterRule) string {
|
|
|
+func buildFilterRuleLines(r FilterRule) []string {
|
|
|
+ combos := getInterfaceCombinations(r.InInterface, r.InInterfaceList, r.OutInterface, r.OutInterfaceList)
|
|
|
+ if len(combos) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
chain := strings.ToUpper(r.Chain)
|
|
|
if chain == "" {
|
|
|
chain = "FORWARD"
|
|
|
}
|
|
|
|
|
|
- var args []string
|
|
|
- args = append(args, fmt.Sprintf("-A %s", chain))
|
|
|
+ var lines []string
|
|
|
+ for _, combo := range combos {
|
|
|
+ inIface, outIface := combo[0], combo[1]
|
|
|
|
|
|
- // Match criteria
|
|
|
- args = appendMatchCriteria(args, r.SrcAddress, r.DstAddress, r.Protocol, r.SrcPort, r.DstPort, r.InInterface, r.OutInterface, r.ConnectionState, r.ConnectionMark, r.RoutingMark, r.SrcAddressList, r.DstAddressList, r.SrcGeoIP, r.DstGeoIP)
|
|
|
+ var args []string
|
|
|
+ args = append(args, fmt.Sprintf("-A %s", chain))
|
|
|
|
|
|
- // Comment ID for counters mapping & user comment
|
|
|
- args = append(args, fmt.Sprintf("-m comment --comment \"id:%s\"", r.ID))
|
|
|
+ // Match criteria
|
|
|
+ args = appendMatchCriteria(args, r.SrcAddress, r.DstAddress, r.Protocol, r.SrcPort, r.DstPort, inIface, outIface, r.ConnectionState, r.ConnectionMark, r.RoutingMark, r.SrcAddressList, r.DstAddressList, r.SrcGeoIP, r.DstGeoIP)
|
|
|
|
|
|
- // Action
|
|
|
- act := strings.ToLower(r.Action)
|
|
|
- switch act {
|
|
|
- case "accept":
|
|
|
- args = append(args, "-j ACCEPT")
|
|
|
- case "drop":
|
|
|
- args = append(args, "-j DROP")
|
|
|
- case "reject":
|
|
|
- args = append(args, "-j REJECT")
|
|
|
- if r.RejectWith != "" {
|
|
|
- args = append(args, fmt.Sprintf("--reject-with %s", r.RejectWith))
|
|
|
- }
|
|
|
- case "return":
|
|
|
- args = append(args, "-j RETURN")
|
|
|
- case "jump":
|
|
|
- if r.JumpTarget != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j %s", strings.ToUpper(r.JumpTarget)))
|
|
|
- }
|
|
|
- case "log":
|
|
|
- args = append(args, "-j LOG")
|
|
|
- if r.LogPrefix != "" {
|
|
|
- args = append(args, fmt.Sprintf("--log-prefix \"%s: \"", r.LogPrefix))
|
|
|
- }
|
|
|
- case "add-src-to-address-list":
|
|
|
- if r.AddressList != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j SET --add-set %s src", GetIPSetName(r.AddressList)))
|
|
|
- }
|
|
|
- case "add-dst-to-address-list":
|
|
|
- if r.AddressList != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j SET --add-set %s dst", GetIPSetName(r.AddressList)))
|
|
|
+ // Comment ID for counters mapping & user comment
|
|
|
+ args = append(args, fmt.Sprintf("-m comment --comment \"id:%s\"", r.ID))
|
|
|
+
|
|
|
+ // Action
|
|
|
+ act := strings.ToLower(r.Action)
|
|
|
+ switch act {
|
|
|
+ case "accept":
|
|
|
+ args = append(args, "-j ACCEPT")
|
|
|
+ case "drop":
|
|
|
+ args = append(args, "-j DROP")
|
|
|
+ case "reject":
|
|
|
+ args = append(args, "-j REJECT")
|
|
|
+ if r.RejectWith != "" {
|
|
|
+ args = append(args, fmt.Sprintf("--reject-with %s", r.RejectWith))
|
|
|
+ }
|
|
|
+ case "return":
|
|
|
+ args = append(args, "-j RETURN")
|
|
|
+ case "jump":
|
|
|
+ if r.JumpTarget != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j %s", strings.ToUpper(r.JumpTarget)))
|
|
|
+ }
|
|
|
+ case "log":
|
|
|
+ args = append(args, "-j LOG")
|
|
|
+ if r.LogPrefix != "" {
|
|
|
+ args = append(args, fmt.Sprintf("--log-prefix \"%s: \"", r.LogPrefix))
|
|
|
+ }
|
|
|
+ case "add-src-to-address-list":
|
|
|
+ if r.AddressList != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j SET --add-set %s src", GetIPSetName(r.AddressList)))
|
|
|
+ }
|
|
|
+ case "add-dst-to-address-list":
|
|
|
+ if r.AddressList != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j SET --add-set %s dst", GetIPSetName(r.AddressList)))
|
|
|
+ }
|
|
|
+ case "passthrough":
|
|
|
+ // in iptables, passthrough continues evaluation
|
|
|
+ continue
|
|
|
+ default:
|
|
|
+ args = append(args, "-j ACCEPT")
|
|
|
}
|
|
|
- case "passthrough":
|
|
|
- // in iptables, passthrough continues evaluation
|
|
|
- return ""
|
|
|
- default:
|
|
|
- args = append(args, "-j ACCEPT")
|
|
|
+
|
|
|
+ lines = append(lines, strings.Join(args, " "))
|
|
|
}
|
|
|
|
|
|
- return strings.Join(args, " ")
|
|
|
+ return lines
|
|
|
}
|
|
|
|
|
|
-func buildNATRuleLine(r NATRule) string {
|
|
|
+func buildNATRuleLines(r NATRule) []string {
|
|
|
+ combos := getInterfaceCombinations(r.InInterface, r.InInterfaceList, r.OutInterface, r.OutInterfaceList)
|
|
|
+ if len(combos) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
chain := strings.ToUpper(r.Chain)
|
|
|
if chain == "SRCNAT" {
|
|
|
chain = "POSTROUTING"
|
|
|
@@ -251,152 +338,171 @@ func buildNATRuleLine(r NATRule) string {
|
|
|
chain = "PREROUTING"
|
|
|
}
|
|
|
|
|
|
- var args []string
|
|
|
- args = append(args, fmt.Sprintf("-A %s", chain))
|
|
|
+ var lines []string
|
|
|
+ for _, combo := range combos {
|
|
|
+ inIface, outIface := combo[0], combo[1]
|
|
|
|
|
|
- args = appendMatchCriteria(args, r.SrcAddress, r.DstAddress, r.Protocol, r.SrcPort, r.DstPort, r.InInterface, r.OutInterface, nil, "", "", r.SrcAddressList, r.DstAddressList, r.SrcGeoIP, r.DstGeoIP)
|
|
|
- args = append(args, fmt.Sprintf("-m comment --comment \"id:%s\"", r.ID))
|
|
|
+ var args []string
|
|
|
+ args = append(args, fmt.Sprintf("-A %s", chain))
|
|
|
|
|
|
- act := strings.ToLower(r.Action)
|
|
|
- switch act {
|
|
|
- case "masquerade":
|
|
|
- args = append(args, "-j MASQUERADE")
|
|
|
- case "src-nat":
|
|
|
- if r.ToAddresses != "" {
|
|
|
- target := r.ToAddresses
|
|
|
- if r.ToPorts != "" {
|
|
|
- target = fmt.Sprintf("%s:%s", r.ToAddresses, r.ToPorts)
|
|
|
- }
|
|
|
- args = append(args, fmt.Sprintf("-j SNAT --to-source %s", target))
|
|
|
- } else {
|
|
|
+ args = appendMatchCriteria(args, r.SrcAddress, r.DstAddress, r.Protocol, r.SrcPort, r.DstPort, inIface, outIface, nil, "", "", r.SrcAddressList, r.DstAddressList, r.SrcGeoIP, r.DstGeoIP)
|
|
|
+ args = append(args, fmt.Sprintf("-m comment --comment \"id:%s\"", r.ID))
|
|
|
+
|
|
|
+ act := strings.ToLower(r.Action)
|
|
|
+ switch act {
|
|
|
+ case "masquerade":
|
|
|
args = append(args, "-j MASQUERADE")
|
|
|
- }
|
|
|
- case "dst-nat":
|
|
|
- if r.ToAddresses != "" {
|
|
|
- target := r.ToAddresses
|
|
|
+ case "src-nat":
|
|
|
+ if r.ToAddresses != "" {
|
|
|
+ target := r.ToAddresses
|
|
|
+ if r.ToPorts != "" {
|
|
|
+ target = fmt.Sprintf("%s:%s", r.ToAddresses, r.ToPorts)
|
|
|
+ }
|
|
|
+ args = append(args, fmt.Sprintf("-j SNAT --to-source %s", target))
|
|
|
+ } else {
|
|
|
+ args = append(args, "-j MASQUERADE")
|
|
|
+ }
|
|
|
+ case "dst-nat":
|
|
|
+ if r.ToAddresses != "" {
|
|
|
+ target := r.ToAddresses
|
|
|
+ if r.ToPorts != "" {
|
|
|
+ target = fmt.Sprintf("%s:%s", r.ToAddresses, r.ToPorts)
|
|
|
+ }
|
|
|
+ args = append(args, fmt.Sprintf("-j DNAT --to-destination %s", target))
|
|
|
+ }
|
|
|
+ case "redirect":
|
|
|
if r.ToPorts != "" {
|
|
|
- target = fmt.Sprintf("%s:%s", r.ToAddresses, r.ToPorts)
|
|
|
+ args = append(args, fmt.Sprintf("-j REDIRECT --to-ports %s", r.ToPorts))
|
|
|
+ } else {
|
|
|
+ args = append(args, "-j REDIRECT")
|
|
|
}
|
|
|
- args = append(args, fmt.Sprintf("-j DNAT --to-destination %s", target))
|
|
|
- }
|
|
|
- case "redirect":
|
|
|
- if r.ToPorts != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j REDIRECT --to-ports %s", r.ToPorts))
|
|
|
- } else {
|
|
|
- args = append(args, "-j REDIRECT")
|
|
|
- }
|
|
|
- case "jump":
|
|
|
- if r.JumpTarget != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j %s", strings.ToUpper(r.JumpTarget)))
|
|
|
- }
|
|
|
- case "log":
|
|
|
- args = append(args, "-j LOG")
|
|
|
- if r.LogPrefix != "" {
|
|
|
- args = append(args, fmt.Sprintf("--log-prefix \"%s: \"", r.LogPrefix))
|
|
|
- }
|
|
|
- case "add-src-to-address-list":
|
|
|
- if r.AddressList != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j SET --add-set %s src", GetIPSetName(r.AddressList)))
|
|
|
- }
|
|
|
- case "add-dst-to-address-list":
|
|
|
- if r.AddressList != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j SET --add-set %s dst", GetIPSetName(r.AddressList)))
|
|
|
+ case "jump":
|
|
|
+ if r.JumpTarget != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j %s", strings.ToUpper(r.JumpTarget)))
|
|
|
+ }
|
|
|
+ case "log":
|
|
|
+ args = append(args, "-j LOG")
|
|
|
+ if r.LogPrefix != "" {
|
|
|
+ args = append(args, fmt.Sprintf("--log-prefix \"%s: \"", r.LogPrefix))
|
|
|
+ }
|
|
|
+ case "add-src-to-address-list":
|
|
|
+ if r.AddressList != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j SET --add-set %s src", GetIPSetName(r.AddressList)))
|
|
|
+ }
|
|
|
+ case "add-dst-to-address-list":
|
|
|
+ if r.AddressList != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j SET --add-set %s dst", GetIPSetName(r.AddressList)))
|
|
|
+ }
|
|
|
+ case "accept":
|
|
|
+ args = append(args, "-j ACCEPT")
|
|
|
+ case "return":
|
|
|
+ args = append(args, "-j RETURN")
|
|
|
+ default:
|
|
|
+ args = append(args, "-j MASQUERADE")
|
|
|
}
|
|
|
- case "accept":
|
|
|
- args = append(args, "-j ACCEPT")
|
|
|
- case "return":
|
|
|
- args = append(args, "-j RETURN")
|
|
|
- default:
|
|
|
- args = append(args, "-j MASQUERADE")
|
|
|
+
|
|
|
+ lines = append(lines, strings.Join(args, " "))
|
|
|
}
|
|
|
|
|
|
- return strings.Join(args, " ")
|
|
|
+ return lines
|
|
|
}
|
|
|
|
|
|
-func buildMangleRuleLine(r MangleRule) string {
|
|
|
+func buildMangleRuleLines(r MangleRule) []string {
|
|
|
+ combos := getInterfaceCombinations(r.InInterface, r.InInterfaceList, r.OutInterface, r.OutInterfaceList)
|
|
|
+ if len(combos) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
chain := strings.ToUpper(r.Chain)
|
|
|
if chain == "" {
|
|
|
chain = "PREROUTING"
|
|
|
}
|
|
|
|
|
|
- var args []string
|
|
|
- args = append(args, fmt.Sprintf("-A %s", chain))
|
|
|
+ var lines []string
|
|
|
+ for _, combo := range combos {
|
|
|
+ inIface, outIface := combo[0], combo[1]
|
|
|
|
|
|
- args = appendMatchCriteria(args, r.SrcAddress, r.DstAddress, r.Protocol, r.SrcPort, r.DstPort, r.InInterface, r.OutInterface, r.ConnectionState, r.ConnectionMark, r.RoutingMark, r.SrcAddressList, r.DstAddressList, r.SrcGeoIP, r.DstGeoIP)
|
|
|
- args = append(args, fmt.Sprintf("-m comment --comment \"id:%s\"", r.ID))
|
|
|
+ var args []string
|
|
|
+ args = append(args, fmt.Sprintf("-A %s", chain))
|
|
|
|
|
|
- act := strings.ToLower(r.Action)
|
|
|
- switch act {
|
|
|
- case "mark-connection":
|
|
|
- if r.NewConnectionMark != "" {
|
|
|
- markID := MarkNameToID(r.NewConnectionMark)
|
|
|
- args = append(args, fmt.Sprintf("-j CONNMARK --set-mark %d", markID))
|
|
|
- }
|
|
|
- case "mark-routing":
|
|
|
- if r.NewRoutingMark != "" {
|
|
|
- markID := MarkNameToID(r.NewRoutingMark)
|
|
|
- args = append(args, fmt.Sprintf("-j MARK --set-mark %d", markID))
|
|
|
- }
|
|
|
- case "mark-packet":
|
|
|
- if r.NewPacketMark != "" {
|
|
|
- markID := MarkNameToID(r.NewPacketMark)
|
|
|
- args = append(args, fmt.Sprintf("-j MARK --set-mark %d", markID))
|
|
|
- }
|
|
|
- case "change-mss":
|
|
|
- args = append(args, "-p tcp --tcp-flags SYN,RST SYN -j TCPMSS")
|
|
|
- if r.NewMSS == "clamp-to-pmtu" || r.NewMSS == "" {
|
|
|
- args = append(args, "--clamp-mss-to-pmtu")
|
|
|
- } else {
|
|
|
- args = append(args, fmt.Sprintf("--set-mss %s", r.NewMSS))
|
|
|
- }
|
|
|
- case "set-dscp", "change-dscp":
|
|
|
- if r.NewDSCP > 0 {
|
|
|
- args = append(args, fmt.Sprintf("-j DSCP --set-dscp %d", r.NewDSCP))
|
|
|
- }
|
|
|
- case "change-ttl":
|
|
|
- if r.NewTTL != "" {
|
|
|
- if strings.HasPrefix(r.NewTTL, "+") {
|
|
|
- args = append(args, fmt.Sprintf("-j TTL --ttl-inc %s", strings.TrimPrefix(r.NewTTL, "+")))
|
|
|
- } else if strings.HasPrefix(r.NewTTL, "-") {
|
|
|
- args = append(args, fmt.Sprintf("-j TTL --ttl-dec %s", strings.TrimPrefix(r.NewTTL, "-")))
|
|
|
+ args = appendMatchCriteria(args, r.SrcAddress, r.DstAddress, r.Protocol, r.SrcPort, r.DstPort, inIface, outIface, r.ConnectionState, r.ConnectionMark, r.RoutingMark, r.SrcAddressList, r.DstAddressList, r.SrcGeoIP, r.DstGeoIP)
|
|
|
+ args = append(args, fmt.Sprintf("-m comment --comment \"id:%s\"", r.ID))
|
|
|
+
|
|
|
+ act := strings.ToLower(r.Action)
|
|
|
+ switch act {
|
|
|
+ case "mark-connection":
|
|
|
+ if r.NewConnectionMark != "" {
|
|
|
+ markID := MarkNameToID(r.NewConnectionMark)
|
|
|
+ args = append(args, fmt.Sprintf("-j CONNMARK --set-mark %d", markID))
|
|
|
+ }
|
|
|
+ case "mark-routing":
|
|
|
+ if r.NewRoutingMark != "" {
|
|
|
+ markID := MarkNameToID(r.NewRoutingMark)
|
|
|
+ args = append(args, fmt.Sprintf("-j MARK --set-mark %d", markID))
|
|
|
+ }
|
|
|
+ case "mark-packet":
|
|
|
+ if r.NewPacketMark != "" {
|
|
|
+ markID := MarkNameToID(r.NewPacketMark)
|
|
|
+ args = append(args, fmt.Sprintf("-j MARK --set-mark %d", markID))
|
|
|
+ }
|
|
|
+ case "change-mss":
|
|
|
+ args = append(args, "-p tcp --tcp-flags SYN,RST SYN -j TCPMSS")
|
|
|
+ if r.NewMSS == "clamp-to-pmtu" || r.NewMSS == "" {
|
|
|
+ args = append(args, "--clamp-mss-to-pmtu")
|
|
|
} else {
|
|
|
- args = append(args, fmt.Sprintf("-j TTL --ttl-set %s", r.NewTTL))
|
|
|
+ args = append(args, fmt.Sprintf("--set-mss %s", r.NewMSS))
|
|
|
}
|
|
|
+ case "set-dscp", "change-dscp":
|
|
|
+ if r.NewDSCP > 0 {
|
|
|
+ args = append(args, fmt.Sprintf("-j DSCP --set-dscp %d", r.NewDSCP))
|
|
|
+ }
|
|
|
+ case "change-ttl":
|
|
|
+ if r.NewTTL != "" {
|
|
|
+ if strings.HasPrefix(r.NewTTL, "+") {
|
|
|
+ args = append(args, fmt.Sprintf("-j TTL --ttl-inc %s", strings.TrimPrefix(r.NewTTL, "+")))
|
|
|
+ } else if strings.HasPrefix(r.NewTTL, "-") {
|
|
|
+ args = append(args, fmt.Sprintf("-j TTL --ttl-dec %s", strings.TrimPrefix(r.NewTTL, "-")))
|
|
|
+ } else {
|
|
|
+ args = append(args, fmt.Sprintf("-j TTL --ttl-set %s", r.NewTTL))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case "set-priority":
|
|
|
+ if r.NewPriority != "" && chain == "POSTROUTING" {
|
|
|
+ args = append(args, fmt.Sprintf("-j CLASSIFY --set-class 0:%s", r.NewPriority))
|
|
|
+ }
|
|
|
+ case "drop":
|
|
|
+ args = append(args, "-j DROP")
|
|
|
+ case "jump":
|
|
|
+ if r.JumpTarget != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j %s", strings.ToUpper(r.JumpTarget)))
|
|
|
+ }
|
|
|
+ case "log":
|
|
|
+ args = append(args, "-j LOG")
|
|
|
+ if r.LogPrefix != "" {
|
|
|
+ args = append(args, fmt.Sprintf("--log-prefix \"%s: \"", r.LogPrefix))
|
|
|
+ }
|
|
|
+ case "add-src-to-address-list":
|
|
|
+ if r.AddressList != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j SET --add-set %s src", GetIPSetName(r.AddressList)))
|
|
|
+ }
|
|
|
+ case "add-dst-to-address-list":
|
|
|
+ if r.AddressList != "" {
|
|
|
+ args = append(args, fmt.Sprintf("-j SET --add-set %s dst", GetIPSetName(r.AddressList)))
|
|
|
+ }
|
|
|
+ case "accept":
|
|
|
+ args = append(args, "-j ACCEPT")
|
|
|
+ case "return":
|
|
|
+ args = append(args, "-j RETURN")
|
|
|
+ case "clear-df", "strip-ipv4-options", "route", "sniff-pc", "sniff-tzsp", "passthrough":
|
|
|
+ continue
|
|
|
+ default:
|
|
|
+ continue
|
|
|
}
|
|
|
- case "set-priority":
|
|
|
- if r.NewPriority != "" && chain == "POSTROUTING" {
|
|
|
- args = append(args, fmt.Sprintf("-j CLASSIFY --set-class 0:%s", r.NewPriority))
|
|
|
- }
|
|
|
- case "drop":
|
|
|
- args = append(args, "-j DROP")
|
|
|
- case "jump":
|
|
|
- if r.JumpTarget != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j %s", strings.ToUpper(r.JumpTarget)))
|
|
|
- }
|
|
|
- case "log":
|
|
|
- args = append(args, "-j LOG")
|
|
|
- if r.LogPrefix != "" {
|
|
|
- args = append(args, fmt.Sprintf("--log-prefix \"%s: \"", r.LogPrefix))
|
|
|
- }
|
|
|
- case "add-src-to-address-list":
|
|
|
- if r.AddressList != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j SET --add-set %s src", GetIPSetName(r.AddressList)))
|
|
|
- }
|
|
|
- case "add-dst-to-address-list":
|
|
|
- if r.AddressList != "" {
|
|
|
- args = append(args, fmt.Sprintf("-j SET --add-set %s dst", GetIPSetName(r.AddressList)))
|
|
|
- }
|
|
|
- case "accept":
|
|
|
- args = append(args, "-j ACCEPT")
|
|
|
- case "return":
|
|
|
- args = append(args, "-j RETURN")
|
|
|
- case "clear-df", "strip-ipv4-options", "route", "sniff-pc", "sniff-tzsp", "passthrough":
|
|
|
- return ""
|
|
|
- default:
|
|
|
- return ""
|
|
|
+
|
|
|
+ lines = append(lines, strings.Join(args, " "))
|
|
|
}
|
|
|
|
|
|
- return strings.Join(args, " ")
|
|
|
+ return lines
|
|
|
}
|
|
|
|
|
|
func appendMatchCriteria(args []string, srcAddr, dstAddr, proto, srcPort, dstPort, inIface, outIface string, ctStates []string, connMark, routingMark, srcList, dstList, srcGeoIP, dstGeoIP string) []string {
|