/
fw_command.go
127 lines (104 loc) · 3.23 KB
/
fw_command.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package internal
import (
"encoding/json"
"net"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
var _ Firewall = &FirewallCommand{}
type FirewallCommand struct {
FirewallSetupCmd string
RuleAddCmd string
RuleRemoveCmd string
exec CommandExecuter
}
type FirewallCommandRuleAddInput struct {
ClientUUID string `json:"clientUUID"`
IPIsIPv6 bool `json:"ipIsIPv6"`
ClientIP net.IP `json:"clientIP"`
TargetIP net.IP `json:"targetIP"`
TargetProtocol string `json:"targetProtocol"`
PortStart int `json:"portStart"`
PortEnd int `json:"portEnd,omitempty"`
Duration int `json:"duration"`
}
type FirewallCommandRuleRemoveInput struct {
ClientUUID string `json:"clientUUID"`
IPIsIPv6 bool `json:"ipIsIPv6"`
ClientIP net.IP `json:"clientIP"`
TargetIP net.IP `json:"targetIP"`
TargetProtocol string `json:"targetProtocol"`
PortStart int `json:"portStart"`
PortEnd int `json:"portEnd,omitempty"`
}
func NewFirewallCommand(setupCmd, ruleAddCmd, ruleRemoveCmd string) *FirewallCommand {
fc := &FirewallCommand{
FirewallSetupCmd: setupCmd,
RuleAddCmd: ruleAddCmd,
RuleRemoveCmd: ruleRemoveCmd,
exec: &CommandExecute{},
}
return fc
}
func (fc *FirewallCommand) FirewallSetup() error {
if fc.FirewallSetupCmd == "" {
return nil
}
_, err := fc.exec.Execute(fc.FirewallSetupCmd, nil)
return err
}
func (fc *FirewallCommand) RuleAdd(r FirewallRule, meta FirewallRuleMetadata) error {
input := FirewallCommandRuleAddInput{
ClientUUID: meta.ClientUUID,
IPIsIPv6: isIPv6(r.SrcIP),
ClientIP: r.SrcIP,
TargetIP: r.DstIP,
TargetProtocol: r.Proto,
PortStart: r.DstPortStart,
PortEnd: r.DstPortEnd,
Duration: int(meta.Duration.Seconds()),
}
stdin, err := json.Marshal(input)
if err != nil {
return errors.Wrap(err, "json marshal input")
}
output, err := fc.exec.Execute(fc.RuleAddCmd, stdin)
if err != nil {
log.Warn().Msgf("Failed to add rule %s, external command output: %s", r.String(), output)
return errors.Wrap(err, "execute rule add command")
}
return nil
}
func (fc *FirewallCommand) RuleRemove(r FirewallRule, meta FirewallRuleMetadata) error {
input := FirewallCommandRuleRemoveInput{
ClientUUID: meta.ClientUUID,
IPIsIPv6: isIPv6(r.SrcIP),
ClientIP: r.SrcIP,
TargetIP: r.DstIP,
TargetProtocol: r.Proto,
PortStart: r.DstPortStart,
PortEnd: r.DstPortEnd,
}
stdin, err := json.Marshal(input)
if err != nil {
return errors.Wrap(err, "json marshal input")
}
output, err := fc.exec.Execute(fc.RuleRemoveCmd, stdin)
if err != nil {
log.Warn().Msgf("Failed to remove rule %s, external command output: %s", r.String(), output)
return errors.Wrap(err, "execute rule remove command")
}
return nil
}
func newFirewallCommandFromServerConfigFirewall(fc ServerConfigFirewall) (*FirewallCommand, error) {
setup := fc.Command.FirewallSetup
add := fc.Command.RuleAdd
remove := fc.Command.RuleRemove
if len(add) == 0 {
return nil, errors.New("rule add command is empty")
}
if len(remove) == 0 {
return nil, errors.New("rule remove command is empty")
}
return NewFirewallCommand(setup, add, remove), nil
}