Class: PuppetX::SIMP::IPTables

Inherits:
Object
  • Object
show all
Defined in:
lib/puppetx/simp/iptables.rb

Defined Under Namespace

Classes: Rule

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rules) ⇒ IPTables

Returns a new instance of IPTables



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
# File 'lib/puppetx/simp/iptables.rb', line 9

def initialize(rules)
  current_table = nil

  # These are generally useful things to have around.
  #
  # The @tables Hash is a way to reference arrays of rules based on the
  # table that contains the rule.
  #
  # The @rules Array is an ordered array of Rule objects
  #
  @tables = {}
  @rules = []

  rules.chomp.split("\n").each do |rule|
    next if rule =~ /^\s*(#.*)?$/

    if rule =~ /^\s*(\*.*)/
      current_table = $1.strip
      @tables[current_table] ||= []
      next
    end

    rule = PuppetX::SIMP::IPTables::Rule.new(rule,current_table)

    @tables[current_table] << rule
    @rules << rule
  end
end

Instance Attribute Details

#rulesObject (readonly)

Returns the value of attribute rules



7
8
9
# File 'lib/puppetx/simp/iptables.rb', line 7

def rules
  @rules
end

Instance Method Details

#chains(to_match = []) ⇒ Object

Return a list of all chains used by a rule in this ruleset with a chain or jump segment matching the optional Array of compiled regular expressions.

If no Array is passed, all results will be returned.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/puppetx/simp/iptables.rb', line 58

def chains(to_match = [])
  to_match ||= []
  result = {}

  @rules.each do |rule|
    next unless rule.chain

    if to_match.empty?
      result[rule.chain] = true
    else
      to_match.each do |regex|
        if regex.match(rule.chain) || regex.match(rule.jump)
          result[rule.chain] = true
        end
      end
    end
  end

  return result.keys.sort
end

#live_format(protect = []) ⇒ Object

This returns the rules in a format suitable for direct application using subsequent calls to the iptables command.

Ensure that we DO NOT flush any chains that are only simple rules!

'protect' is an Array of chains that should never be flushed.



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
# File 'lib/puppetx/simp/iptables.rb', line 86

def live_format(protect=[])
  protect ||= []
  result = []
  flushed_chains = {}
  created_chains = []

  @rules.each do |rule|
    if rule.rule_type == :rule
      table = rule.table.split('*').last

      unless created_chains.include?(rule.chain)
        result.unshift("-N #{rule.chain} 2>/dev/null")
        created_chains << rule.chain
      end

      unless (protect.include?(rule.chain) || flushed_chains[rule.chain])
        result << "-t #{table} -F #{rule.chain}"
        flushed_chains[rule.chain] = true
      end

      result << "-t #{table} " + rule.to_s
    end
  end

  result
end

#optimizeObject



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/puppetx/simp/iptables.rb', line 165

def optimize
  new_rules = []

  # Hard coded limit in iptables multiport rules.
  max_ports = 15

  @tables.keys.sort.each do |table|
    new_rules << table

    @tables[table].each do |rule|
      rule = rule.to_s

      if new_rules.empty?
        new_rules << rule
        next
      end

      # Make sure we have a valid rule for multiport compression.
      if  rule !~ /-p(rotocol)?\s+(ud|tc)p/ &&
          rule !~ /--(d(estination-)?|s(ource-)?)ports?\s+/
      then
        new_rules << rule
        next
      end

      last_rule = new_rules.pop

      prev_ports = []
      new_ports = []
      prev_multiport = false
      port_type = nil

      prev_rule = last_rule.split(/\s+-/).delete_if{ |x|
        retval = false
        if x.empty?
          retval = true
        elsif x =~ /m(ulti)?port/
          prev_multiport = true
          retval = true
        elsif x =~ /(d(estination-)?|s(ource-)?)ports?\s+(.*)/
          port_type = $1[0].chr
          prev_ports += $4.split(',')
          retval = true
        end
        retval
      }

      new_rule = rule.split(/\s+-/).delete_if{ |x|
        retval = false
        if x.empty? || x =~ /m(ulti)?port/
          retval = true
        elsif x =~ /(d(estination-)?|s(ource-)?)ports?\s+(.*)/
          # Add ranges as sub-arrays.
          new_ports += $4.split(',')
          retval = true
        end
        retval
      }

      new_rule.map!{|x| x = normalize_rule(x)}
      prev_rule.map!{|x| x = normalize_rule(x)}

      if (new_rule.sort <=> prev_rule.sort) == 0
        Puppet.debug("Rule:\n  #{new_rule} matches\n  #{prev_rule}")
        # Flatten when comparing sizes to account for ranges.
        new_ports = (prev_ports + new_ports).uniq
        slice_array(new_ports,max_ports).each do |sub_ports|
          new_rules << prev_rule.dup.insert(-2,"m multiport --#{port_type}ports #{sub_ports.sort.uniq.join(',')}").join(' -')
        end
      else
        Puppet.debug("No match for: #{rule}")
        new_rules << last_rule
        new_rules << rule
      end
    end
  end

  return PuppetX::SIMP::IPTables.new(new_rules.join("\n"))
end

#report(to_ignore = []) ⇒ Object

Produces a hash-based report on the number of iptables rules, and type of operation in a given chain.

You may optionally pass an array of compiled regular expressions. If this array is present, all items with a chain or jump matching the regex will be ignored.



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/puppetx/simp/iptables.rb', line 135

def report(to_ignore=[])
  result = {}

  @tables.keys.each do |table|
    result[table] ||= {}

    @tables[table].each do |rule|
      next unless rule.rule_type == :rule

      do_ignore = false
      to_ignore.each do |ignore|
        if ignore.match(rule.chain) || ignore.match(rule.jump)
         do_ignore = true
         break
        end
      end
      next if do_ignore

      result[table][rule.chain] ||= {}

      if rule.jump
        result[table][rule.chain][rule.jump] ||= 0
        result[table][rule.chain][rule.jump] += 1
      end
    end
  end

  result
end

#to_hashObject

Return a hash of rules of the following format:

<table_name> => [rule1, rule2, etc…]



117
118
119
120
121
122
123
124
125
126
# File 'lib/puppetx/simp/iptables.rb', line 117

def to_hash
  result = {}
  @tables.keys.sort.each do |table|
    result[table] ||= []

    result[table] << @tables[table].map{|rule| rule = rule.to_s}
  end

  return result
end

#to_sObject



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/puppetx/simp/iptables.rb', line 38

def to_s
  result = []

  @tables.keys.sort.each do |table|
    result << table

    @tables[table].each do |rule|
      result << rule
    end
  end

  result.join("\n")
end