Skip to content

Commit

Permalink
Network: firewall masquerade
Browse files Browse the repository at this point in the history
  • Loading branch information
cheina97 committed Dec 12, 2023
1 parent 968c427 commit fa2396a
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 26 deletions.
16 changes: 8 additions & 8 deletions apis/networking/v1alpha1/firewall/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,25 @@ const (
IPValueTypeIP IPValueType = "ip"
// IPValueTypeSubnet is a string representing a subnet (eg. 10.0.0.0/24).
IPValueTypeSubnet IPValueType = "subnet"
// IPValueTypeInvalid is an invalid match value.
IPValueTypeInvalid IPValueType = "invalid"
// IPValueTypeVoid is a void match value.
IPValueTypeVoid IPValueType = "void"
)

// GetIPValueType parses the match value and returns the type of the value.
func GetIPValueType(value string) (IPValueType, error) {
if value == "" {
return IPValueTypeInvalid, fmt.Errorf("match value cannot be empty")
func GetIPValueType(value *string) (IPValueType, error) {
if value == nil {
return IPValueTypeVoid, nil
}

// Check if the value is a pool subnet.
if _, _, err := net.ParseCIDR(value); err == nil {
if _, _, err := net.ParseCIDR(*value); err == nil {
return IPValueTypeSubnet, nil
}

// Check if the value is an IP.
if net.ParseIP(value) != nil {
if net.ParseIP(*value) != nil {
return IPValueTypeIP, nil
}

return IPValueTypeInvalid, fmt.Errorf("invalid match value %s", value)
return IPValueTypeVoid, fmt.Errorf("invalid match value %s", *value)
}
2 changes: 1 addition & 1 deletion apis/networking/v1alpha1/firewall/match.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func applyMatch(m *Match, rule *nftables.Rule) error {
}

func applyMatchIP(m *Match, rule *nftables.Rule, op expr.CmpOp) error {
matchIPValueType, err := GetIPValueType(m.IP.Value)
matchIPValueType, err := GetIPValueType(&m.IP.Value)
if err != nil {
return err
}
Expand Down
28 changes: 20 additions & 8 deletions apis/networking/v1alpha1/firewall/natrule.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,19 @@ func applyNatRule(nr *NatRule, rule *nftables.Rule) error {
return applyNatIP(nr.To, natType, rule)
case IPValueTypeSubnet:
return applyNatSubnet(nr.To, natType, rule)
default:
return fmt.Errorf("invalid ip value %s", nr.To)
case IPValueTypeVoid:
return applyNatVoid(rule)
}
return nil
}

func applyNatIP(ip string, natType expr.NATType, rule *nftables.Rule) error {
ipNet := net.ParseIP(ip)
func applyNatIP(ip *string, natType expr.NATType, rule *nftables.Rule) error {
if ip == nil {
return fmt.Errorf("\"to\" argument cannot be nil for nat type snat/dnat")
}
ipNet := net.ParseIP(*ip)
if ipNet == nil {
return fmt.Errorf("invalid ip %s", ip)
return fmt.Errorf("invalid ip %s", *ip)
}

rule.Exprs = append(rule.Exprs,
Expand All @@ -132,8 +136,16 @@ func applyNatIP(ip string, natType expr.NATType, rule *nftables.Rule) error {
return nil
}

func applyNatSubnet(ip string, natType expr.NATType, rule *nftables.Rule) error {
_, subnet, err := net.ParseCIDR(ip)
func applyNatVoid(rule *nftables.Rule) error {
rule.Exprs = append(rule.Exprs, &expr.Masq{})
return nil
}

func applyNatSubnet(ip *string, natType expr.NATType, rule *nftables.Rule) error {
if ip == nil {
return fmt.Errorf("\"to\" argument cannot be nil for nat type snat/dnat")
}
_, subnet, err := net.ParseCIDR(*ip)
if err != nil {
return err
}
Expand Down Expand Up @@ -169,7 +181,7 @@ func getNatRuleType(natrule *NatRule) (expr.NATType, error) {
switch natrule.NatType {
case NatTypeDestination:
return expr.NATTypeDestNAT, nil
case NatTypeSource:
case NatTypeSource, NatTypeMasquerade:
return expr.NATTypeSourceNAT, nil
default:
return expr.NATType(0), fmt.Errorf("invalid nat type %s", natrule.NatType)
Expand Down
6 changes: 4 additions & 2 deletions apis/networking/v1alpha1/firewall/natrule_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const (
NatTypeDestination NatType = "dnat"
// NatTypeSource is the type of the NAT rule.
NatTypeSource NatType = "snat"
// NatTypeMasquerade is the type of the NAT rule.
NatTypeMasquerade NatType = "masquerade"
)

var _ Rule = &NatRule{}
Expand All @@ -36,8 +38,8 @@ type NatRule struct {
// Using multiple ip matches with same position or
Match []Match `json:"match"`
// NatType is the type of the NAT rule.
// +kubebuilder:validation:Enum=dnat;snat
// +kubebuilder:validation:Enum=dnat;snat;masquerade
NatType NatType `json:"natType"`
// To is the IP to be used for the NAT translation.
To string `json:"to"`
To *string `json:"to,omitempty"`
}
5 changes: 5 additions & 0 deletions apis/networking/v1alpha1/firewall/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ spec:
enum:
- dnat
- snat
- masquerade
type: string
to:
description: To is the IP to be used for the NAT
Expand All @@ -180,7 +181,6 @@ spec:
required:
- match
- natType
- to
type: object
type: array
routeRules:
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,6 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/nftables v0.1.0 h1:T6lS4qudrMufcNIZ8wSRrL+iuwhsKxpN+zFLxhUWOqk=
github.com/google/nftables v0.1.0/go.mod h1:b97ulCCFipUC+kSin+zygkvUVpx0vyIAwxXFdY3PlNc=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,23 @@ func checkNatRulesInChain(chain *firewallapi.Chain) error {
if err := checkNatRuleChainHook(*chain.Hook, &natrules[i]); err != nil {
return err
}
if err := checkNatRuleTo(&natrules[i]); err != nil {
return err
}
}
return nil
}

func checkNatRuleTo(natrule *firewallapi.NatRule) error {
switch natrule.NatType {
case firewallapi.NatTypeDestination, firewallapi.NatTypeSource:
if natrule.To == nil {
return fmt.Errorf("natrule %s is %s but has no To field", *natrule.GetName(), natrule.NatType)
}
case firewallapi.NatTypeMasquerade:
if natrule.To != nil {
return fmt.Errorf("natrule %s is Masquerade or masquerade but has a To field", *natrule.GetName())
}
}
return nil
}
Expand All @@ -39,28 +56,28 @@ func checkNatRuleChainHook(hook firewallapi.ChainHook, rule *firewallapi.NatRule
switch rule.NatType {
case firewallapi.NatTypeDestination:
return fmt.Errorf("natrule %s is DNAT that is incompatible with postrouting", *rule.GetName())
case firewallapi.NatTypeSource:
case firewallapi.NatTypeSource, firewallapi.NatTypeMasquerade:
return nil
}
case firewallapi.ChainHookPrerouting:
switch rule.NatType {
case firewallapi.NatTypeDestination:
return nil
case firewallapi.NatTypeSource:
case firewallapi.NatTypeSource, firewallapi.NatTypeMasquerade:
return fmt.Errorf("natrule %s is SNAT that is incompatible with prerouting", *rule.GetName())
}
case firewallapi.ChainHookInput:
switch rule.NatType {
case firewallapi.NatTypeDestination:
return fmt.Errorf("natrule %s is DNAT that is incompatible with input", *rule.GetName())
case firewallapi.NatTypeSource:
case firewallapi.NatTypeSource, firewallapi.NatTypeMasquerade:
return nil
}
case firewallapi.ChainHookOutput:
switch rule.NatType {
case firewallapi.NatTypeDestination:
return nil
case firewallapi.NatTypeSource:
case firewallapi.NatTypeSource, firewallapi.NatTypeMasquerade:
return fmt.Errorf("natrule %s is SNAT that is incompatible with output", *rule.GetName())
}
default:
Expand Down

0 comments on commit fa2396a

Please sign in to comment.