Firewall-4.2.0-1.rb

Chris Johnston, 11/04/2013 03:18 PM

Download (4.73 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
        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