1
|
class OpenNebulaFirewall < OpenNebulaNetwork
|
2
|
DRIVER = "fw"
|
3
|
XPATH_FILTER = "TEMPLATE/NIC[FW_IN|FW_OUT]"
|
4
|
|
5
|
def initialize(vm, deploy_id = nil, hypervisor = nil)
|
6
|
super(vm,XPATH_FILTER,deploy_id,hypervisor)
|
7
|
@locking = true
|
8
|
end
|
9
|
|
10
|
def activate
|
11
|
lock
|
12
|
vm_id = @vm['ID']
|
13
|
process do |nic|
|
14
|
tap = nic[:tap]
|
15
|
if tap
|
16
|
init_and_clean(tap)
|
17
|
nic_rules = Array.new
|
18
|
if rules = nic[:fw_out]
|
19
|
chain = "one-#{vm_id}-#{tap}-out"
|
20
|
nic_rules << new_chain(chain)
|
21
|
nic_rules << tap_to_chain(tap, chain, "FW_OUT")
|
22
|
nic_rules << filter_established(chain, :accept)
|
23
|
rules.split(" ").each do |rule|
|
24
|
nic_rules << filter_rule(chain, rule)
|
25
|
end
|
26
|
nic_rules << filter_all(chain, :drop)
|
27
|
end
|
28
|
if rules = nic[:fw_in]
|
29
|
chain = "one-#{vm_id}-#{tap}-in"
|
30
|
nic_rules << new_chain(chain)
|
31
|
nic_rules << tap_to_chain(tap, chain, "FW_IN")
|
32
|
nic_rules << filter_established(chain, :accept)
|
33
|
rules.split(" ").each do |rule|
|
34
|
nic_rules << filter_rule(chain, rule)
|
35
|
end
|
36
|
nic_rules << filter_all(chain, :drop)
|
37
|
end
|
38
|
run_rules(nic_rules)
|
39
|
end
|
40
|
end
|
41
|
unlock
|
42
|
end
|
43
|
|
44
|
def deactivate
|
45
|
lock
|
46
|
vm_id = @vm['ID']
|
47
|
process do |nic|
|
48
|
ip = nic[:ip]
|
49
|
purge_chain("one-#{vm_id}-.*-out", "FW_OUT")
|
50
|
purge_chain("one-#{vm_id}-.*-in", "FW_IN")
|
51
|
end
|
52
|
unlock
|
53
|
end
|
54
|
|
55
|
def init_and_clean(tap)
|
56
|
iptables_out = `#{COMMANDS[:iptables]} -L FORWARD`
|
57
|
if ! iptables_out.match(/^FW_IN/) || ! iptables_out.match(/^FW_OUT/)
|
58
|
`#{COMMANDS[:iptables]} -N FW_OUT >/dev/null 2>&1`
|
59
|
`#{COMMANDS[:iptables]} -N FW_IN >/dev/null 2>&1`
|
60
|
`#{COMMANDS[:iptables]} -A FORWARD -j FW_OUT >/dev/null 2>&1`
|
61
|
`#{COMMANDS[:iptables]} -A FORWARD -j FW_IN >/dev/null 2>&1`
|
62
|
end
|
63
|
purge_chain("one-.*-#{tap}-out", "FW_OUT")
|
64
|
purge_chain("one-.*-#{tap}-in", "FW_IN")
|
65
|
end
|
66
|
|
67
|
|
68
|
def purge_chain(regex, parent)
|
69
|
iptables_out = `#{COMMANDS[:iptables]}-save | grep #{parent} | grep \'#{regex}\'`
|
70
|
if iptables_out.length != 0
|
71
|
chain = iptables_out.split(" ").last
|
72
|
rules = Array.new
|
73
|
rules << iptables_out.gsub!(/^-A/,"-D")
|
74
|
rules << rule("-F #{chain}")
|
75
|
rules << rule("-X #{chain}")
|
76
|
run_rules(rules)
|
77
|
end
|
78
|
end
|
79
|
|
80
|
def filter_established(chain, policy)
|
81
|
policy = policy.to_s.upcase
|
82
|
rule "-A #{chain} -m conntrack --ctstate ESTABLISHED,RELATED -j #{policy}"
|
83
|
end
|
84
|
|
85
|
def filter_rule(chain, rule)
|
86
|
r = rule.split(/,\s*(?=[^\[\]]*(?:\[|$))/)
|
87
|
p = get_protocol(r[0])
|
88
|
s = get_src(r[1])
|
89
|
d = get_dst(r[2])
|
90
|
a = get_action(r[3])
|
91
|
rule "-A #{chain} #{p} #{s} #{d} #{a}"
|
92
|
end
|
93
|
|
94
|
def filter_all(chain, policy)
|
95
|
policy = policy.to_s.upcase
|
96
|
rule "-A #{chain} -j #{policy}"
|
97
|
end
|
98
|
|
99
|
def get_protocol (protocol)
|
100
|
"-p #{protocol}"
|
101
|
end
|
102
|
|
103
|
def get_src (src)
|
104
|
host = get_host("s",src)
|
105
|
port = get_port("s",src)
|
106
|
"#{host} #{port}"
|
107
|
end
|
108
|
|
109
|
def get_dst (dst)
|
110
|
host = get_host("d",dst)
|
111
|
port = get_port("d",dst)
|
112
|
"#{host} #{port}"
|
113
|
end
|
114
|
|
115
|
def get_host (tag, data)
|
116
|
if host = data.split(":")[0].to_s
|
117
|
host.gsub!(/\[(.*)\]/,'\1')
|
118
|
if ! host.eql?("")
|
119
|
"-#{tag} #{host}"
|
120
|
end
|
121
|
end
|
122
|
end
|
123
|
|
124
|
def get_port (tag, data)
|
125
|
if port = data.split(":",2)[1].to_s
|
126
|
port.gsub!(/\[(.*)\]/,'\1')
|
127
|
if ! port.eql?("")
|
128
|
"-m multiport --#{tag}ports #{port}"
|
129
|
end
|
130
|
end
|
131
|
end
|
132
|
|
133
|
def get_action (action)
|
134
|
case action
|
135
|
when "ACCEPT"
|
136
|
"-j RETURN"
|
137
|
when "DROP"
|
138
|
"-j DROP"
|
139
|
end
|
140
|
end
|
141
|
|
142
|
def run_rules(rules)
|
143
|
rules.flatten.each do |rule|
|
144
|
OpenNebula.exec_and_log(rule)
|
145
|
end
|
146
|
end
|
147
|
|
148
|
def tap_to_chain(tap, chain, parent)
|
149
|
case parent
|
150
|
when "FW_OUT"
|
151
|
rule "-A #{parent} -m physdev --physdev-in #{tap} -j #{chain}"
|
152
|
when "FW_IN"
|
153
|
rule "-A #{parent} -m physdev --physdev-is-bridged --physdev-out #{tap} -j #{chain}"
|
154
|
end
|
155
|
end
|
156
|
|
157
|
def new_chain(chain)
|
158
|
rule "-N #{chain}"
|
159
|
end
|
160
|
|
161
|
def rule(rule)
|
162
|
"#{COMMANDS[:iptables]} #{rule}".gsub(/[ ]+/,' ')
|
163
|
end
|
164
|
end
|