diff --git a/cmd/create/create_firewall.go b/cmd/create/create_firewall.go index fd2e45f..b30916d 100644 --- a/cmd/create/create_firewall.go +++ b/cmd/create/create_firewall.go @@ -17,6 +17,7 @@ package create import ( "context" + "errors" "fmt" "loxicmd/pkg/api" "net/http" @@ -31,6 +32,7 @@ import ( type CreateFirewallOptions struct { FirewallRule []string Redirect []string + SnatArgs []string Allow bool Drop bool Trap bool @@ -64,6 +66,8 @@ ex) loxicmd create firewall --firewallRule="sourceIP:1.2.3.2/32,destinationIP:2. loxicmd create firewall --firewallRule="sourceIP:1.2.3.2/32,destinationIP:2.3.1.2/32,preference:200" --drop loxicmd create firewall --firewallRule="sourceIP:1.2.3.2/32,destinationIP:2.3.1.2/32,preference:200" --trap loxicmd create firewall --firewallRule="sourceIP:1.2.3.2/32,destinationIP:2.3.1.2/32,preference:200" --redirect=hs1 + loxicmd create firewall --firewallRule="sourceIP:1.2.3.2/32,destinationIP:2.3.1.2/32,preference:200" --snat=10.10.10.1,3030 + loxicmd create firewall --firewallRule="sourceIP:1.2.3.2/32,destinationIP:2.3.1.2/32,preference:200" --snat=10.10.10.1 (Do not change sourceport) `, Aliases: []string{"Firewall", "fw", "firewalls"}, PreRun: func(cmd *cobra.Command, args []string) { @@ -107,6 +111,7 @@ ex) loxicmd create firewall --firewallRule="sourceIP:1.2.3.2/32,destinationIP:2. createFirewallCmd.Flags().BoolVarP(&o.Record, "record", "", false, "Record/Dump any matching rule") createFirewallCmd.Flags().BoolVarP(&o.Trap, "trap", "", false, " Trap anything matching rule") createFirewallCmd.Flags().IntVarP(&o.Mark, "setmark", "", 0, " Add a fw mark") + createFirewallCmd.Flags().StringSliceVar(&o.SnatArgs, "snat", o.SnatArgs, "SNAT any matching rule") createFirewallCmd.MarkFlagRequired("firewallRule") return createFirewallCmd } @@ -175,6 +180,21 @@ func GetFWOptionPairList(FirewallMods *api.FwRuleMod, o CreateFirewallOptions) e } else if len(o.Redirect) != 0 { FirewallMods.Opts.Rdr = true FirewallMods.Opts.RdrPort = o.Redirect[0] + } else if len(o.SnatArgs) != 0 { + if len(o.SnatArgs) > 2 { + return errors.New("invalid snat-args") + } + FirewallMods.Opts.DoSnat = true + FirewallMods.Opts.ToIP = o.SnatArgs[0] + if len(o.SnatArgs) > 1 { + sPort, err := strconv.Atoi(o.SnatArgs[1]) + if err != nil { + return errors.New("invalid snat-args") + } + FirewallMods.Opts.ToPort = uint16(sPort) + } else { + FirewallMods.Opts.ToPort = 0 + } } FirewallMods.Opts.Record = o.Record FirewallMods.Opts.Mark = o.Mark diff --git a/cmd/get/get_firewall.go b/cmd/get/get_firewall.go index edd9a42..bd80a4c 100644 --- a/cmd/get/get_firewall.go +++ b/cmd/get/get_firewall.go @@ -111,6 +111,8 @@ func MakeFirewallOptionToString(t api.FwOptArg) (ret string) { ret = "Trap" } else if t.Rdr { ret = fmt.Sprintf("Redirect(%s)", t.RdrPort) + } else if t.DoSnat { + ret = fmt.Sprintf("Snat(%s:%d)", t.ToIP, t.ToPort) } if t.Record { ret += fmt.Sprintf(",Record") diff --git a/cmd/get/get_loadbalancer.go b/cmd/get/get_loadbalancer.go index cdc8408..7364658 100644 --- a/cmd/get/get_loadbalancer.go +++ b/cmd/get/get_loadbalancer.go @@ -156,7 +156,7 @@ func PrintGetLbResult(resp *http.Response, o api.RESTOptions) { // Making load balance data for _, lbrule := range lbresp.LbRules { - if o.ServiceName != "" && o.ServiceName != lbrule.Service.Name { + if o.ServiceName != "" && o.ServiceName != lbrule.Service.Name || lbrule.Service.Snat { continue } protocolStr := lbrule.Service.Protocol @@ -258,7 +258,7 @@ func Lbdump(restOptions *api.RESTOptions, path string) (string, error) { } for _, lbrule := range lbresp.LbRules { - if !lbrule.Service.Managed && !strings.Contains(lbrule.Service.Name, "ipvs") { + if !lbrule.Service.Managed && !lbrule.Service.Snat && !strings.Contains(lbrule.Service.Name, "ipvs") { for i := range lbrule.Endpoints { lbacts := &lbrule.Endpoints[i] lbacts.Counter = "" diff --git a/pkg/api/firewall.go b/pkg/api/firewall.go index 39372c9..4aba3be 100644 --- a/pkg/api/firewall.go +++ b/pkg/api/firewall.go @@ -42,7 +42,10 @@ type FwOptArg struct { Mark int `json:"fwMark" yaml:"fwMark"` // Record - Record packets matching rule Record bool `json:"record" yaml:"record"` - + // DoSNAT - Do snat on matching rule + DoSnat bool `json:"doSnat"` + ToIP string `json:"toIP"` + ToPort uint16 `json:"toPort"` // Counter - Traffic counter Counter string `json:"counter"` } diff --git a/pkg/api/loadBalancer.go b/pkg/api/loadBalancer.go index 48c6f20..3a2ade2 100644 --- a/pkg/api/loadBalancer.go +++ b/pkg/api/loadBalancer.go @@ -51,6 +51,7 @@ type LoadBalancerService struct { Block uint16 `json:"block" yaml:"block"` Managed bool `json:"managed,omitempty" yaml:"managed"` Name string `json:"name,omitempty" yaml:"name"` + Snat bool `json:"snat,omitempty"` Oper LbOP `json:"oper,omitempty"` Security LbSec `json:"security,omitempty" yaml:"security"` }