Firewall-4.2.0.rb

OpenNebula Systems Support Team, 10/21/2013 05:07 PM

Download (4.51 KB)

 
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

    
13
        vm_id =  @vm['ID']
14
        process do |nic|
15

    
16
            tap = nic[:tap]
17
            ip  = nic[:ip]
18

    
19
            if tap
20

    
21
                if rules = nic[:fw_in]
22
                    chain = "one-#{vm_id}-#{ip}-in"
23
                    nic_rules = Array.new
24
                    nic_rules << new_chain(chain)
25
                    nic_rules << tap_to_chain(tap, chain, "FW_IN") 
26
                    nic_rules << filter_established(chain, :accept)
27
                    rules.split(" ").each do |rule|
28
                        nic_rules << filter_rule(chain, rule)
29
                    end
30
                    nic_rules << filter_all(chain, :drop)
31
                end
32

    
33
                if rules = nic[:fw_out]
34
                    chain = "one-#{vm_id}-#{ip}-out"
35
                    nic_rules << new_chain(chain)
36
                    nic_rules << tap_to_chain(tap, chain, "FW_OUT")
37
                    nic_rules << filter_established(chain, :accept)
38
                    rules.split(" ").each do |rule|
39
                        nic_rules << filter_rule(chain, rule)
40
                    end
41
                    nic_rules << filter_all(chain, :drop)
42
                end
43

    
44
                iptables_out = `#{COMMANDS[:iptables]} -L FORWARD`
45
                if ! iptables_out.match(/^FW_IN/) || ! iptables_out.match(/^FW_OUT/)
46
                    `#{COMMANDS[:iptables]} -N FW_IN >/dev/null 2>&1`
47
                    `#{COMMANDS[:iptables]} -N FW_OUT >/dev/null 2>&1`
48
                    `#{COMMANDS[:iptables]} -A FORWARD -j FW_IN >/dev/null 2>&1`
49
                    `#{COMMANDS[:iptables]} -A FORWARD -j FW_OUT >/dev/null 2>&1`
50
                end
51

    
52
                run_rules(nic_rules)
53
            end
54
        end
55

    
56
        unlock
57
    end
58

    
59
    def deactivate
60
        lock
61

    
62
        vm_id =  @vm['ID']
63
        process do |nic|
64
            ip = nic[:ip]
65
            purge_chain("one-#{vm_id}-#{ip}-in", "FW_IN")
66
            purge_chain("one-#{vm_id}-#{ip}-out", "FW_OUT")
67
        end
68

    
69
        unlock
70
    end
71

    
72
    def purge_chain(chain, parent)
73
        rules = Array.new
74
        rules << rule(`#{COMMANDS[:iptables]}-save | grep #{parent} | grep #{chain}`.gsub!(/^-A/,"-D"))
75
        rules << rule("-F #{chain}")
76
        rules << rule("-X #{chain}")
77
        run_rules(rules)
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_IN"
151
                rule "-A #{parent} -m physdev --physdev-is-bridged --physdev-out #{tap} -j #{chain}"
152
            when "FW_OUT"
153
                rule "-A #{parent} -m physdev --physdev-in #{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