5 Star 6 Fork 4

zstackio/zstack-vyos

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
vyosIptables.go 16.57 KB
一键复制 编辑 原始数据 按行查看 历史
shixin.ruan 提交于 2024-03-18 17:45 +08:00 . [data]: add slb ha
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
package utils
import (
"fmt"
"strconv"
"strings"
)
const (
IPTABLES_RULENUMBER_9999 = 9999
IPTABLES_RULENUMBER_MAX = 10000
)
const (
SystemTopRule = "default rule"
SystemLastLastRule = "default rule 9999"
SystemLastRule = "default rule 10000"
/*network service rule comment*/
FirewallRule = "firewall rule"
PortFordingRuleComment = "pf rule"
EipRuleComment = "eip rule"
IpsecRuleComment = "IPSec rule"
LbRuleComment = "lb rule"
SNATComment = "snat rule"
PolicyRouteComment = "policy route rule"
PolicyRouteChainPrefix = "zs-rt-"
PolicyRouteRuleChainPrefix = "zs-rule-"
)
const (
VYOS_INPUT_ROOT_CHAIN = "VYATTA_FW_LOCAL_HOOK"
VYATTA_PRE_FW_IN_HOOK = "VYATTA_PRE_FW_IN_HOOK"
VYATTA_POST_FW_IN_HOOK = "VYATTA_POST_FW_IN_HOOK"
VYOS_PRE_FW_FWD_HOOK = "VYATTA_PRE_FW_FWD_HOOK"
VYOS_FWD_ROOT_CHAIN = "VYATTA_FW_IN_HOOK"
VYOS_FWD_OUT_ROOT_CHAIN = "VYATTA_FW_OUT_HOOK"
VYOS_POST_FW_FWD_HOOK = "VYATTA_POST_FW_FWD_HOOK"
LOCAL_CHAIN_SYSTEM_RULE_RULE_NUMBER_MIN = 1
LOCAL_CHAIN_SYSTEM_RULE_RULE_NUMBER_MAX = 1000
LOCAL_CHAIN_SERVICE_RULE_NUMBER_MIN = 4000
LOCAL_CHAIN_SERVICE_RULE_NUMBER_MAX = 9000
FORWARD_CHAIN_SYSTEM_RULE_RULE_NUMBER_MIN = 4000
FORWARD_CHAIN_SYSTEM_RULE_RULE_NUMBER_MAX = 5000
FORWARD_CHAIN_SERVICE_RULE_NUMBER_MIN = 5001
FORWARD_CHAIN_SERVICE_RULE_NUMBER_MAX = 9000
)
const (
ACTION = "action"
COMMNET = "comment"
)
var filterLocalRulesPriority = map[string]int{
SystemTopRule: LOCAL_CHAIN_SYSTEM_RULE_RULE_NUMBER_MIN,
IpsecRuleComment: 5000,
PortFordingRuleComment: 6000,
LbRuleComment: 7000,
EipRuleComment: 8000,
SystemLastLastRule: IPTABLES_RULENUMBER_9999,
SystemLastRule: IPTABLES_RULENUMBER_MAX,
}
var filterForwardRulesPriority = map[string]int{
SystemTopRule: FORWARD_CHAIN_SYSTEM_RULE_RULE_NUMBER_MIN,
FirewallRule: 1000,
IpsecRuleComment: 5000,
PortFordingRuleComment: 6000,
EipRuleComment: 7001,
SystemLastLastRule: IPTABLES_RULENUMBER_9999,
SystemLastRule: IPTABLES_RULENUMBER_MAX,
}
var filterOutRulesPriority = map[string]int{
FirewallRule: 1000,
SystemLastLastRule: IPTABLES_RULENUMBER_9999,
SystemLastRule: IPTABLES_RULENUMBER_MAX,
}
var snatRulesPriority = map[string]int{
SystemTopRule: 1,
IpsecRuleComment: 1000,
EipRuleComment: 2000,
SNATComment: IPTABLES_RULENUMBER_MAX,
}
var dnatRulesPriority = map[string]int{
PortFordingRuleComment: 1000,
EipRuleComment: 900,
PolicyRouteComment: 800, /* policy route is in mangle table, put code here for a moment */
}
var filterFORWARDRulesPriority = map[string]int{
VYOS_PRE_FW_FWD_HOOK: 0,
VYOS_FWD_ROOT_CHAIN: 1,
VYOS_FWD_OUT_ROOT_CHAIN: 2,
VYOS_POST_FW_FWD_HOOK: 3,
}
var INPUTRulesPriority = map[string]int{
VYATTA_PRE_FW_IN_HOOK: 0,
VYOS_INPUT_ROOT_CHAIN: 1,
VYATTA_POST_FW_IN_HOOK: 2,
}
type RuleSetDirection int
const (
RULESET_IN RuleSetDirection = iota
RULESET_LOCAL
RULESET_OUT
RULESET_DNAT
RULESET_SNAT
INPUT
FORWARD
PREROUTING
POSTROUTING
CHAIN_ERROR
)
func (d RuleSetDirection) String() string {
switch d {
case RULESET_IN:
return ".in"
case RULESET_LOCAL:
return ".local"
case RULESET_OUT:
return ".out"
case RULESET_DNAT:
return "PREROUTING"
case RULESET_SNAT:
return "POSTROUTING"
case FORWARD:
return "FORWARD"
case PREROUTING:
return "PREROUTING"
case POSTROUTING:
return "POSTROUTING"
case INPUT:
return "INPUT"
default:
return ".unkonwn"
}
}
func GetRuleSetName(nic string, ch RuleSetDirection) string {
return nic + ch.String()
}
func (d RuleSetDirection) getPriorityByAction(action string) (int, bool) {
var m *map[string]int
switch d {
case INPUT:
m = &INPUTRulesPriority
case FORWARD:
m = &filterFORWARDRulesPriority
default:
return 0, false
}
p, ok := (*m)[action]
return p, ok
}
func (d RuleSetDirection) getPriorityByComment(comment string) (int, bool) {
var m *map[string]int
switch d {
case RULESET_IN:
m = &filterForwardRulesPriority
case RULESET_LOCAL:
m = &filterLocalRulesPriority
case RULESET_OUT:
m = &filterOutRulesPriority
case RULESET_DNAT:
m = &dnatRulesPriority
case RULESET_SNAT:
m = &snatRulesPriority
default:
return 0, false
}
p, ok := (*m)[comment]
return p, ok
}
type VyosIpTableHelper struct{}
func (p VyosIpTableHelper) parseIpTableRule(rule *IpTableRule, t *IpTables) *IpTableRule {
priority, err := getPriority(rule)
if priority == 0 || err != nil {
rule.priority = t.priorityOfLastRule
return rule
}
rule.priority = priority
/* firewall rule priority is same to rulenum */
if strings.Contains(rule.GetComment(), FirewallRule) {
rule.ruleNumber = priority
return rule
} else {
_, _, ruleNum, err := parseRuleNumberFromComment(rule.GetComment())
if ruleNum != 0 && err == nil {
rule.ruleNumber = ruleNum
}
return rule
}
}
func (p VyosIpTableHelper) getNextRuleNumber(t *IpTables, rule *IpTableRule) int {
/* firewall rule already has rule No. */
if rule.ruleNumber != 0 {
return rule.ruleNumber
}
/* no comment, priority is 0 */
if rule.comment == "" {
return 0
}
/* TODO: only rule in filter table need rule No. */
if t.Name != FirewallTable {
return 0
}
existed := map[int]int{}
for _, r := range t.Rules {
if r.chainName == rule.chainName {
if r.ruleNumber != 0 {
existed[r.ruleNumber] = r.ruleNumber
}
}
}
ruleNo := 0
if strings.Contains(rule.chainName, RULESET_LOCAL.String()) {
if strings.Contains(rule.comment, SystemTopRule) {
for i := LOCAL_CHAIN_SYSTEM_RULE_RULE_NUMBER_MIN; i <= LOCAL_CHAIN_SYSTEM_RULE_RULE_NUMBER_MAX; i++ {
if _, ok := existed[i]; !ok {
ruleNo = i
break
}
}
} else {
for i := LOCAL_CHAIN_SERVICE_RULE_NUMBER_MIN; i <= LOCAL_CHAIN_SERVICE_RULE_NUMBER_MAX; i++ {
if _, ok := existed[i]; !ok {
ruleNo = i
break
}
}
}
} else if strings.Contains(rule.chainName, RULESET_IN.String()) {
if strings.Contains(rule.comment, SystemTopRule) {
for i := FORWARD_CHAIN_SYSTEM_RULE_RULE_NUMBER_MIN; i <= FORWARD_CHAIN_SYSTEM_RULE_RULE_NUMBER_MAX; i++ {
if _, ok := existed[i]; !ok {
ruleNo = i
break
}
}
} else {
for i := FORWARD_CHAIN_SERVICE_RULE_NUMBER_MIN; i <= FORWARD_CHAIN_SERVICE_RULE_NUMBER_MAX; i++ {
if _, ok := existed[i]; !ok {
ruleNo = i
break
}
}
}
}
return ruleNo
}
func getComment(rule *IpTableRule) string {
items := strings.Split(rule.GetComment(), "@")
if rule.ruleNumber != 0 {
return fmt.Sprintf("%s@%s-%d", items[0], rule.chainName, rule.ruleNumber)
} else {
return fmt.Sprintf("%s@%s", items[0], rule.chainName)
}
}
func getPriority(rule *IpTableRule) (int, error) {
c := CHAIN_ERROR
/* if chain is default chain */
if rule.chainName == FORWARD.String() {
c = FORWARD
} else if rule.chainName == INPUT.String() {
c = INPUT
}
if c != CHAIN_ERROR {
p, ok := c.getPriorityByAction(rule.action)
if ok {
return p, nil
}
}
return getPriorityFromComment(rule)
}
func getPriorityFromComment(rule *IpTableRule) (int, error) {
/* if rule is added by customer, no comment or comment format error,
it priority is same to last priority */
if rule.comment == "" {
rule.priority = 0
return 0, fmt.Errorf("no comment for priotity [%s]", rule.comment)
}
comment, _, ruleNum, err := parseRuleNumberFromComment(rule.GetComment())
if err == nil && strings.Contains(rule.GetComment(), FirewallRule) {
return ruleNum, nil
}
c := PREROUTING
if strings.Contains(rule.GetChainName(), RULESET_LOCAL.String()) {
c = RULESET_LOCAL
} else if strings.Contains(rule.GetChainName(), RULESET_IN.String()) {
c = RULESET_IN
} else if strings.Contains(rule.GetChainName(), RULESET_OUT.String()) {
c = RULESET_OUT
} else if strings.Contains(rule.GetChainName(), RULESET_SNAT.String()) {
c = RULESET_SNAT
} else if strings.Contains(rule.GetChainName(), RULESET_DNAT.String()) {
c = RULESET_DNAT
} else {
return 0, fmt.Errorf("no define priority for chainname [%s]", rule.GetChainName())
}
p, ok := c.getPriorityByComment(comment)
if !ok {
return 0, fmt.Errorf("no define priority for comment [%s]", comment)
} else {
return p, nil
}
}
/* this api is called before add rule to iptables */
func (r *IpTableRule) SetComment(comment string) *IpTableRule {
r.setComment(comment)
r.priority, _ = getPriorityFromComment(r)
r.comment = getComment(r)
return r
}
/* this api is called before add rule to iptables */
func (r *IpTableRule) SetCompareTarget(compare bool) *IpTableRule {
r.compareTarget = compare
return r
}
func NewDefaultIpTableRule(ruleSetName string, ruleNumber int) *IpTableRule {
var rule IpTableRule
rule.chainName = ruleSetName
c := SystemLastRule
if ruleNumber == IPTABLES_RULENUMBER_9999 {
c = SystemLastLastRule
rule.SetState([]string{IPTABLES_STATE_NEW})
}
rule.comment = c
rule.comment = getComment(&rule)
if strings.Contains(ruleSetName, RULESET_OUT.String()) {
rule.priority = filterOutRulesPriority[c]
} else {
rule.priority = filterForwardRulesPriority[c]
}
rule.ruleNumber = ruleNumber
return &rule
}
/*
firewall comment format: "system rule@eth1.in-1001"
return comment, chain name, rule number when success
*/
func parseRuleNumberFromComment(comment string) (string, string, int, error) {
fields := strings.Split(comment, "@")
if len(fields) < 2 {
return fields[0], "", 0, fmt.Errorf("comment format error: %s", comment)
}
items := strings.Split(fields[1], "-")
if len(items) < 2 {
return fields[0], items[0], 0, nil
}
v, err := strconv.Atoi(items[1])
return fields[0], items[0], v, err
}
func SetFirewallRuleNumber(r *IpTableRule, ruleSetName string, ruleNumber int) *IpTableRule {
r.comment = FirewallRule
r.priority = ruleNumber
r.ruleNumber = ruleNumber
r.comment = getComment(r)
return r
}
func IsDefaultRule(r *IpTableRule) bool {
return strings.Contains(r.comment, SystemLastRule) && r.action != IPTABLES_ACTION_LOG
}
func GetFirewallIpTableRule(t *IpTables) []*IpTableRule {
var rules []*IpTableRule
for _, r := range t.Rules {
if strings.Contains(r.comment, FirewallRule) {
rules = append(rules, r.Copy())
}
}
return rules
}
func GetPimdIpTableRule(t *IpTables) []*IpTableRule {
var rules []*IpTableRule
for _, r := range t.Rules {
if !strings.Contains(r.chainName, RULESET_LOCAL.String()) {
continue
}
if r.proto == IPTABLES_PROTO_PIMD || r.proto == IPTABLES_PROTO_IGMP {
rules = append(rules, r.Copy())
}
}
return rules
}
func GetOSPFIpTableRule(t *IpTables) []*IpTableRule {
var rules []*IpTableRule
for _, r := range t.Rules {
if r.proto == IPTABLES_PROTO_OSPF {
rules = append(rules, r.Copy())
}
}
return rules
}
func GetDnsIpTableRule(t *IpTables) []*IpTableRule {
var rules []*IpTableRule
for _, r := range t.Rules {
if !strings.Contains(r.chainName, RULESET_LOCAL.String()) {
continue
}
if r.dstPort == "53" {
rules = append(rules, r.Copy())
}
}
return rules
}
func GetFirewallInputChains(t *IpTables) []string {
var chains []string
for _, c := range t.Chains {
if strings.Contains(c.Name, RULESET_IN.String()) {
chains = append(chains, c.Name)
}
}
return chains
}
func GetFirewallOutputChains(t *IpTables) []string {
var chains []string
for _, c := range t.Chains {
if strings.Contains(c.Name, RULESET_OUT.String()) {
chains = append(chains, c.Name)
}
}
return chains
}
func SetNicDefaultFirewallRule(nic string, defaultAction string) error {
t := NewIpTables(FirewallTable)
var rules []*IpTableRule
nicLocalChain := GetRuleSetName(nic, RULESET_LOCAL)
rule := NewDefaultIpTableRule(nicLocalChain, IPTABLES_RULENUMBER_MAX)
if strings.ToUpper(defaultAction) == IPTABLES_ACTION_REJECT {
rule.SetAction(IPTABLES_ACTION_REJECT)
} else {
rule.SetAction(IPTABLES_ACTION_RETURN)
}
rules = append(rules, rule)
nicFwdChain := GetRuleSetName(nic, RULESET_IN)
rule = NewDefaultIpTableRule(nicFwdChain, IPTABLES_RULENUMBER_MAX)
if strings.ToUpper(defaultAction) == IPTABLES_ACTION_REJECT {
rule.action = IPTABLES_ACTION_REJECT
} else {
rule.action = IPTABLES_ACTION_RETURN
}
rules = append(rules, rule)
t.AddIpTableRules(rules)
return t.Apply()
}
func DestroyNicFirewall(nic string) error {
t := NewIpTables(FirewallTable)
t.removeChainRules(GetRuleSetName(nic, RULESET_LOCAL))
t.removeChainRules(GetRuleSetName(nic, RULESET_IN))
t.removeChainRules(GetRuleSetName(nic, RULESET_OUT))
return t.Apply()
}
func InitNicFirewall(nic string, ip string, pubNic bool, defaultAction string) error {
InitVyattaFilterTable()
table := NewIpTables(FirewallTable)
localChain := GetRuleSetName(nic, RULESET_LOCAL)
forwardChain := GetRuleSetName(nic, RULESET_IN)
outChain := GetRuleSetName(nic, RULESET_OUT)
table.AddChain(localChain)
table.AddChain(forwardChain)
table.AddChain(outChain)
var rules []*IpTableRule
rule := NewIpTableRule(VYOS_INPUT_ROOT_CHAIN)
rule.SetAction(localChain).SetInNic(nic)
rules = append(rules, rule)
rule = NewIpTableRule(VYOS_FWD_ROOT_CHAIN)
rule.SetAction(forwardChain).SetInNic(nic)
rules = append(rules, rule)
rule = NewIpTableRule(VYOS_FWD_OUT_ROOT_CHAIN)
rule.SetAction(outChain).SetOutNic(nic)
rules = append(rules, rule)
/* add Rules for FORWARD chain */
rule = NewIpTableRule(forwardChain)
rule.SetAction(IPTABLES_ACTION_RETURN)
rule.SetComment(SystemTopRule)
rule.SetState([]string{IPTABLES_STATE_RELATED, IPTABLES_STATE_ESTABLISHED})
rules = append(rules, rule)
rule = NewDefaultIpTableRule(forwardChain, IPTABLES_RULENUMBER_9999)
rule.SetAction(IPTABLES_ACTION_RETURN)
rules = append(rules, rule)
rule = NewDefaultIpTableRule(forwardChain, IPTABLES_RULENUMBER_MAX)
rule.SetAction(defaultAction)
rules = append(rules, rule)
sshPort := GetSshPortFromBootInfo()
if IsIpv4Address(ip) {
rule = NewIpTableRule(localChain)
rule.SetAction(IPTABLES_ACTION_RETURN).SetComment(SystemTopRule)
rule.SetDstIp(ip + "/32").SetState([]string{IPTABLES_STATE_RELATED, IPTABLES_STATE_ESTABLISHED})
rules = append(rules, rule)
rule = NewIpTableRule(localChain)
rule.SetAction(IPTABLES_ACTION_RETURN).SetComment(SystemTopRule)
rule.SetDstIp(ip + "/32").SetProto(IPTABLES_PROTO_ICMP)
rules = append(rules, rule)
if IsMgtNic(nic) {
rule = NewIpTableRule(localChain)
rule.SetAction(IPTABLES_ACTION_RETURN).SetComment(SystemTopRule)
rule.SetDstIp(ip + "/32").SetProto(IPTABLES_PROTO_TCP).SetDstPort(strconv.FormatFloat(sshPort, 'f', 0, 64))
rules = append(rules, rule)
rule = NewIpTableRule(localChain)
rule.SetAction(IPTABLES_ACTION_RETURN).SetComment(SystemTopRule)
rule.SetDstIp(ip + "/32").SetProto(IPTABLES_PROTO_TCP).SetDstPort("7272")
rules = append(rules, rule)
} else {
rule = NewIpTableRule(localChain)
rule.SetAction(IPTABLES_ACTION_REJECT).SetRejectType(REJECT_TYPE_ICMP_UNREACHABLE)
rule.SetComment(SystemTopRule).SetDstIp(ip + "/32").SetProto(IPTABLES_PROTO_TCP).SetDstPort(strconv.FormatFloat(sshPort, 'f', 0, 64))
rules = append(rules, rule)
}
}
rule = NewDefaultIpTableRule(localChain, IPTABLES_RULENUMBER_MAX)
rule.SetAction(defaultAction)
rules = append(rules, rule)
table.AddIpTableRules(rules)
return table.Apply()
}
func InitNatRule() {
if !IsSkipVyosIptables() {
return
}
/*flush raw table to clear NOTRACK rule at startup*/
cmd := Bash{
Command: "sudo iptables -t raw -C DNAT -j NOTRACK && sudo iptables -t raw -D DNAT -j NOTRACK;" +
"sudo iptables -t raw -C PREROUTING -j NOTRACK && sudo iptables -t raw -D PREROUTING -j NOTRACK;" +
"sudo iptables -t raw -C OUTPUT -j NOTRACK && sudo iptables -t raw -D OUTPUT -j NOTRACK;" +
"sudo iptables -t raw -A DNAT -p vrrp -j NOTRACK;" + // do not track VRRP
"sudo iptables -t raw -A OUTPUT -p vrrp -j NOTRACK",
}
cmd.Run()
return
}
func InitVyattaFilterTable() {
if !IsSkipVyosIptables() {
return
}
/* INPT chain rule
rule sequence:
-A INPUT -j VYATTA_PRE_FW_IN_HOOK
-A INPUT -j VYATTA_FW_LOCAL_HOOK
-A INPUT -j VYATTA_POST_FW_IN_HOOK
*/
table := NewIpTables(FirewallTable)
table.AddChain(VYOS_INPUT_ROOT_CHAIN)
table.AddChain(VYOS_FWD_ROOT_CHAIN)
table.AddChain(VYOS_FWD_OUT_ROOT_CHAIN)
rule := NewIpTableRule("INPUT")
rule.SetAction(VYOS_INPUT_ROOT_CHAIN).SetCompareTarget(true).SetPriority(1)
table.addIpTableRule(rule)
/*add FORWARD chain rule
rule sequence:
-A FORWARD -j VYATTA_PRE_FW_FWD_HOOK
-A FORWARD -j VYATTA_FW_IN_HOOK
-A FORWARD -j VYATTA_FW_OUT_HOOK
-A FORWARD -j VYATTA_POST_FW_FWD_HOOK
*/
rule = NewIpTableRule("FORWARD")
rule.SetAction(VYOS_FWD_ROOT_CHAIN).SetCompareTarget(true).SetPriority(1)
table.addIpTableRule(rule)
rule = NewIpTableRule("FORWARD")
rule.SetAction(VYOS_FWD_OUT_ROOT_CHAIN).SetCompareTarget(true).SetPriority(2)
table.addIpTableRule(rule)
table.Apply()
return
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zstackio/zstack-vyos.git
git@gitee.com:zstackio/zstack-vyos.git
zstackio
zstack-vyos
zstack-vyos
master

搜索帮助