Class: Dcmgr::VNet::Netfilter::VNicProtocolTaskManager

Inherits:
NetfilterTaskManager show all
Includes:
Helpers::NicHelper
Defined in:
lib/dcmgr/vnet/netfilter/task_manager.rb

Overview

Task manager that creates chains based on vif uuid and protocol Supports ebtables rules and iptables rules

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers::NicHelper

#clean_mac, #find_nic, #is_natted?, #nic_state, #valid_nic?

Constructor Details

#initializeVNicProtocolTaskManager

Returns a new instance of VNicProtocolTaskManager.



43
44
45
46
47
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 43

def initialize
  super
  @iptables_protocols = IptablesRule.protocols
  @ebtables_protocols = EbtablesRule.protocols
end

Instance Attribute Details

#ebtables_protocolsObject (readonly)

Returns the value of attribute ebtables_protocols.



36
37
38
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 36

def ebtables_protocols
  @ebtables_protocols
end

#enable_ebtablesObject

Returns the value of attribute enable_ebtables.



39
40
41
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 39

def enable_ebtables
  @enable_ebtables
end

#enable_iptablesObject

These are flags that decide whether or not iptables and ebtables are enabled



38
39
40
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 38

def enable_iptables
  @enable_iptables
end

#iptables_protocolsObject (readonly)

These store the protocols used by iptables and ebtables



35
36
37
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 35

def iptables_protocols
  @iptables_protocols
end

#verbose_commandsObject

Flag that decides whether or not we output commands that are applied



41
42
43
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 41

def verbose_commands
  @verbose_commands
end

Instance Method Details

#apply_ebtables_chains(vnic_map) ⇒ Object



235
236
237
238
239
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 235

def apply_ebtables_chains(vnic_map)
  cmds = get_ebtables_chains_apply_commands(vnic_map)
  puts cmds.join("\n") if self.verbose_commands
  system(cmds.join("\n"))
end

#apply_iptables_chains(vnic_map) ⇒ Object

Apply the custom iptables chains for this vnic This method only applies the chains and doesn’t make any rules



208
209
210
211
212
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 208

def apply_iptables_chains(vnic_map)
  cmds = get_iptables_chains_apply_commands(vnic_map)
  puts cmds.join("\n") if self.verbose_commands
  system(cmds.join("\n"))
end

#apply_task(task) ⇒ Object



422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 422

def apply_task(task)
  task.rules.each { |rule|
    cmds = []
    if rule.is_a?(EbtablesRule)  && self.enable_ebtables
      cmds << get_rule_command(rule,:apply)
    elsif rule.is_a?(IptablesRule) && self.enable_iptables
      cmds << get_rule_command(rule,:apply)
    end
    cmds.flatten!
    cmds.compact!
    
    puts cmds.join("\n") if self.verbose_commands
  
    system(cmds.join("\n"))
  }
end

#apply_tasks(tasks) ⇒ Object



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 307

def apply_tasks(tasks)
  commands = []

  commands = tasks.map { |task|
    next unless task.is_a? Task
    task.rules.map { |rule|
      next unless rule.is_a? Rule
      get_rule_command(rule,:apply)
    }
  }
  
  final_commands = commands.flatten.uniq.compact
  puts final_commands.join("\n") if self.verbose_commands
  
  system(final_commands.join("\n"))
end

#apply_vnic_chains(vnic_map) ⇒ Object



286
287
288
289
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 286

def apply_vnic_chains(vnic_map)
  apply_iptables_chains(vnic_map) if self.enable_iptables
  apply_ebtables_chains(vnic_map) if self.enable_ebtables
end

#apply_vnic_tasks(vnic_map, tasks) ⇒ Object

Jumps to custom chains named after the vnic’s uuid, then jumps to more custom chains based on the protocol used. In those the real netfiltering happens



281
282
283
284
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 281

def apply_vnic_tasks(vnic_map, tasks)
  # Apply the tasks to our chains
  apply_tasks(tailor_vnic_tasks(vnic_map,tasks))
end

#ebtables_chains(vnic) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 134

def ebtables_chains(vnic)
  chains = []
  
  chains << EbtablesChain.new(:filter, "s_#{vnic[:uuid]}")
  chains << EbtablesChain.new(:filter, "d_#{vnic[:uuid]}")
  chains << EbtablesChain.new(:filter, "s_#{vnic[:uuid]}_d_hst")
  chains << EbtablesChain.new(:filter, "d_#{vnic[:uuid]}_s_hst")
  self.ebtables_protocols.each { |k,v|
    chains << EbtablesChain.new(:filter, "s_#{vnic[:uuid]}_#{k}")
    chains << EbtablesChain.new(:filter, "d_#{vnic[:uuid]}_#{k}")
    chains << EbtablesChain.new(:filter, "s_#{vnic[:uuid]}_d_hst_#{k}")
    chains << EbtablesChain.new(:filter, "d_#{vnic[:uuid]}_s_hst_#{k}")
  }
  
  chains
end

#ebtables_forward_chain_jumps(vnic) ⇒ Object



151
152
153
154
155
156
157
158
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 151

def ebtables_forward_chain_jumps(vnic)
  jumps = []
  
  jumps << EbtablesRule.new(:filter,:forward,nil,nil,"-i #{vnic[:uuid]} -j s_#{vnic[:uuid]}")
  jumps << EbtablesRule.new(:filter,:forward,nil,nil,"-o #{vnic[:uuid]} -j d_#{vnic[:uuid]}")
  
  jumps
end

#ebtables_input_chain_jumps(vnic) ⇒ Object



173
174
175
176
177
178
179
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 173

def ebtables_input_chain_jumps(vnic)
  jumps = []
  
  jumps << EbtablesRule.new(:filter,:input,nil,:outgoing,"-i #{vnic[:uuid]} -j s_#{vnic[:uuid]}_d_hst")
  
  jumps
end

#ebtables_output_chain_jumps(vnic) ⇒ Object



181
182
183
184
185
186
187
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 181

def ebtables_output_chain_jumps(vnic)
  jumps = []
  
  jumps << EbtablesRule.new(:filter,:output,nil,:incoming,"-o #{vnic[:uuid]} -j d_#{vnic[:uuid]}_s_hst")
  
  jumps
end

#ebtables_protocol_chain_jumps(vnic) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 160

def ebtables_protocol_chain_jumps(vnic)
  jumps = []
  
  self.ebtables_protocols.each { |k,v|
    jumps << EbtablesRule.new(:filter,"s_#{vnic[:uuid]}",nil,:outgoing,"-p #{v} -j s_#{vnic[:uuid]}_#{k}")
    jumps << EbtablesRule.new(:filter,"d_#{vnic[:uuid]}",nil,:incoming,"-p #{v} -j d_#{vnic[:uuid]}_#{k}")
    jumps << EbtablesRule.new(:filter,"s_#{vnic[:uuid]}_d_hst",nil,:outgoing,"-p #{v} -j s_#{vnic[:uuid]}_d_hst_#{k}")
    jumps << EbtablesRule.new(:filter,"d_#{vnic[:uuid]}_s_hst",nil,:incoming,"-p #{v} -j d_#{vnic[:uuid]}_s_hst_#{k}")
  }
  
  jumps
end

#get_ebtables_chains_apply_commands(vnic_map) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 241

def get_ebtables_chains_apply_commands(vnic_map)
  commands = []
  
  commands << ebtables_chains(vnic_map).map {|chain| ["ebtables -t #{chain.table} -N #{chain.name}","ebtables -t #{chain.table} -P #{chain.name} RETURN"]}#,"ebtables -t #{chain.table} -P #{chain.name} DROP"]}
  
  create_jump_block = Proc.new {|jump| "ebtables -t #{jump.table} -A #{jump.chain} #{jump.rule}"}
  
  commands << ebtables_forward_chain_jumps(vnic_map).map(&create_jump_block)
  commands << ebtables_input_chain_jumps(vnic_map).map(&create_jump_block)
  commands << ebtables_output_chain_jumps(vnic_map).map(&create_jump_block)
  commands << ebtables_protocol_chain_jumps(vnic_map).map(&create_jump_block)
  
  commands.flatten.uniq
end

#get_ebtables_chains_remove_commands(vnic_map) ⇒ Object



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 262

def get_ebtables_chains_remove_commands(vnic_map)
  commands = []
  
  delete_jump_block = Proc.new {|jump| "ebtables -t #{jump.table} -D #{jump.chain} #{jump.rule}"}
  
  commands << ebtables_forward_chain_jumps(vnic_map).map(&delete_jump_block)
  commands << ebtables_input_chain_jumps(vnic_map).map(&delete_jump_block)
  commands << ebtables_output_chain_jumps(vnic_map).map(&delete_jump_block)
  
  commands << ebtables_chains(vnic_map).map {|chain|
    ["ebtables -t #{chain.table} -F #{chain.name}","ebtables -t #{chain.table} -X #{chain.name}"]
  }
  
  commands.flatten.uniq
end

#get_iptables_chains_apply_commands(vnic_map) ⇒ Object

Returns commands for creating iptables chains and their jump rules



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 190

def get_iptables_chains_apply_commands(vnic_map)
  commands = []
  
  commands << iptables_chains(vnic_map).map { |chain| "iptables -t #{chain.table} -N #{chain.name}"}
  
  create_jump_block = Proc.new { |jump| 
    "iptables -t #{jump.table} -A #{jump.chain} #{jump.rule}"
  }
  
  commands << iptables_forward_chain_jumps(vnic_map).map(&create_jump_block)
  commands << iptables_nat_chain_jumps(vnic_map).map(&create_jump_block)
  commands << iptables_protocol_chain_jumps(vnic_map).map(&create_jump_block)
  
  commands.flatten.uniq
end

#get_iptables_chains_remove_commands(vnic_map) ⇒ Object



220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 220

def get_iptables_chains_remove_commands(vnic_map)
  commands = []
  
  delete_jump_block = Proc.new {|jump| "iptables -t #{jump.table} -D #{jump.chain} #{jump.rule}"}
  
  commands << iptables_forward_chain_jumps(vnic_map).map(&delete_jump_block)
  commands << iptables_nat_chain_jumps(vnic_map).map(&delete_jump_block)
  
  commands << iptables_chains(vnic_map).map {|chain| 
    ["iptables -t #{chain.table} -F #{chain.name}","iptables -t #{chain.table} -X #{chain.name}"]
  }
  
  commands.flatten.uniq
end

#get_rule_command(rule, action) ⇒ Object

Translates rule into a command that can be directly passed on to the OS action determines if the command must :apply or :remove a rule.

Raises:

  • (ArgumentError)


293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 293

def get_rule_command(rule,action)
  actions = {:apply => "I", :remove => "D"}
  raise ArgumentError, "#{rule} is not a Rule" unless rule.is_a? Rule
  raise ArgumentError, "action must be one of the following: '#{actions.keys.join(",")}'" unless actions.member? action
  
  if rule.is_a?(IptablesRule) && self.enable_iptables
    "iptables -t #{rule.table} -#{actions[action]} #{rule.chain} #{rule.rule}"
  elsif rule.is_a?(EbtablesRule) && self.enable_ebtables
    "ebtables -t #{rule.table} -#{actions[action]} #{rule.chain} #{rule.rule}"
  else
    nil
  end
end

#iptables_chains(vnic_map) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 49

def iptables_chains(vnic_map)
  chains = []
  
  [ 's', 'd' ].each { |bound|
    self.iptables_protocols.each { |k,v|
        chains << IptablesChain.new(:filter, "#{bound}_#{vnic_map[:uuid]}")
        chains << IptablesChain.new(:filter, "#{bound}_#{vnic_map[:uuid]}_#{k}")

        chains << IptablesChain.new(:filter, "#{bound}_#{vnic_map[:uuid]}_drop")
        chains << IptablesChain.new(:filter, "#{bound}_#{vnic_map[:uuid]}_#{k}_drop")
    }
    
    #[ 'pre', 'post'].each { |nat_chain|
      #chains << IptablesChain.new(:nat, "#{bound}_#{vnic_map[:uuid]}_#{nat_chain}")
    #}
  }
  #chains << IptablesChain.new(:nat, "#{vnic_map[:uuid]}_dnat_exceptions")
  chains << IptablesChain.new(:nat, "#{vnic_map[:uuid]}_snat_exceptions")
  chains << IptablesChain.new(:nat, "#{vnic_map[:uuid]}_snat")
  
  chains
end

#iptables_forward_chain_jumps(vnic) ⇒ Object



72
73
74
75
76
77
78
79
80
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 72

def iptables_forward_chain_jumps(vnic)
  jumps = []
  
  #Main jumps from the forward chains
  jumps << IptablesRule.new(:filter,:forward,nil,nil,"-m physdev --physdev-is-bridged --physdev-in  #{vnic[:uuid]} -j s_#{vnic[:uuid]}")
  jumps << IptablesRule.new(:filter,:forward,nil,nil,"-m physdev --physdev-is-bridged --physdev-out #{vnic[:uuid]} -j d_#{vnic[:uuid]}")
  
  jumps
end

#iptables_nat_chain_jumps(vnic_map) ⇒ Object

Returns the rules that direct packets for a vnic to that specific vnic’s custom nat chains



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 117

def iptables_nat_chain_jumps(vnic_map)
  jumps = []
  
  #[ :prerouting, :postrouting].each { |chain|
  #jumps << IptablesRule.new(:nat,:prerouting,nil,nil,"-d #{vnic_map[:ipv4][:nat_address]} -j #{vnic_map[:uuid]}_dnat_exceptions")
  jumps << IptablesRule.new(:nat,:postrouting,nil,nil,"-s #{vnic_map[:ipv4][:address]} -j #{vnic_map[:uuid]}_snat_exceptions")
  jumps << IptablesRule.new(:nat,:postrouting,nil,nil,"-s #{vnic_map[:ipv4][:address]} -j #{vnic_map[:uuid]}_snat")
  #}
  
  #jumps << IptablesRule.new(:nat,:prerouting,nil,nil,"-m physdev --physdev-in  #{vnic[:uuid]} -j s_#{vnic[:uuid]}_pre")
  #jumps << IptablesRule.new(:nat,:prerouting,nil,nil,"-m physdev --physdev-out  #{vnic[:uuid]} -j d_#{vnic[:uuid]}_pre")
  #jumps << IptablesRule.new(:nat,:postrouting,nil,nil,"-m physdev --physdev-in #{vnic[:uuid]} -j s_#{vnic[:uuid]}_post")
  #jumps << IptablesRule.new(:nat,:postrouting,nil,nil,"-m physdev --physdev-out #{vnic[:uuid]} -j d_#{vnic[:uuid]}_post")
  
  jumps
end

#iptables_protocol_chain_jumps(vnic) ⇒ Object



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
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 82

def iptables_protocol_chain_jumps(vnic)
  jumps = []
  
  [ 's', 'd' ].each do |bound|
    self.iptables_protocols.each { |k,v|
      case k
      when 'tcp'
        case bound
        when 's'
          jumps << IptablesRule.new(:filter,"#{bound}_#{vnic[:uuid]}",nil,:outgoing,"-m state --state NEW,ESTABLISHED -p #{k} -j #{bound}_#{vnic[:uuid]}_#{k}")
        when 'd'
          jumps << IptablesRule.new(:filter,"#{bound}_#{vnic[:uuid]}",nil,:incoming,"-p #{k} -j #{bound}_#{vnic[:uuid]}_#{k}")
        end
      when 'udp'
        case bound
        when 's'
          jumps << IptablesRule.new(:filter,"#{bound}_#{vnic[:uuid]}",nil,:outgoing,"-m state --state NEW,ESTABLISHED -p #{k} -j #{bound}_#{vnic[:uuid]}_#{k}")
        when 'd'
          jumps << IptablesRule.new(:filter,"#{bound}_#{vnic[:uuid]}",nil,:incoming,"-p #{k} -j #{bound}_#{vnic[:uuid]}_#{k}")
        end
      when 'icmp'
        case bound
        when 's'
          jumps << IptablesRule.new(:filter,"#{bound}_#{vnic[:uuid]}",nil,:outgoing,"-m state --state NEW,ESTABLISHED,RELATED -p #{k} -j #{bound}_#{vnic[:uuid]}_#{k}")
        when 'd'
          jumps << IptablesRule.new(:filter,"#{bound}_#{vnic[:uuid]}",nil,:incoming,"-p #{k} -j #{bound}_#{vnic[:uuid]}_#{k}")
        end
      end
    }
  end
  
  jumps
end

#remove_ebtables_chains(vnic) ⇒ Object



256
257
258
259
260
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 256

def remove_ebtables_chains(vnic)
  cmds = get_ebtables_chains_remove_commands(vnic)
  puts cmds.join("\n") if self.verbose_commands
  system(cmds.join("\n"))
end

#remove_iptables_chains(vnic) ⇒ Object



214
215
216
217
218
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 214

def remove_iptables_chains(vnic)
  cmds = get_iptables_chains_remove_commands(vnic)
  puts cmds.join("\n") if self.verbose_commands
  system(cmds.join("\n"))
end

#remove_task(task) ⇒ Object



439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 439

def remove_task(task)
  task.rules.each { |rule|
    cmds = []
    if rule.is_a?(EbtablesRule) && self.enable_ebtables
      cmds << get_rule_command(rule,:remove)
    elsif rule.is_a?(IptablesRule) && self.enable_iptables
      cmds << get_rule_command(rule,:remove)
    end
    cmds.flatten!
    cmds.compact!
    
    puts cmds.join("\n") if self.verbose_commands
  
    system(cmds.join("\n"))
  }
end

#remove_tasks(tasks) ⇒ Object



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 324

def remove_tasks(tasks)
  commands = []
  
  commands = tasks.map { |task|
    next unless task.is_a? Task
    task.rules.map { |rule|
      get_rule_command(rule,:remove)
    }
  }
  
  final_commands = commands.flatten.uniq.compact
  puts final_commands.join("\n") if self.verbose_commands
  
  system(final_commands.join("\n"))
end

#remove_vnic_chains(vnic) ⇒ Object



417
418
419
420
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 417

def remove_vnic_chains(vnic)
  remove_iptables_chains(vnic) if self.enable_iptables
  remove_ebtables_chains(vnic) if self.enable_ebtables
end

#remove_vnic_tasks(vnic, tasks = nil) ⇒ Object

Removes tasks for this specific vnic if they are applied If no tasks argument is provided, all tasks for this vnic will be removed



413
414
415
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 413

def remove_vnic_tasks(vnic,tasks = nil)
    remove_tasks(tailor_vnic_tasks(vnic,tasks))
end

#tailor_vnic_tasks(vnic, tasks) ⇒ Object

Changes the chains of each rule in tasks to match this TaskManager’s model



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/dcmgr/vnet/netfilter/task_manager.rb', line 341

def tailor_vnic_tasks(vnic,tasks)
  bound = {:incoming => "d", :outgoing => "s"}
  nat_chains = {"PREROUTING" => "pre", "POSTROUTING" => "post"}

  # Use the marshal trick to make a deep copy of tasks
  new_tasks = Marshal.load( Marshal.dump(tasks) )

  new_tasks.each { |task|
    # For protocol independent tasks, generate a copy of their rules for each protocol
    # This is needed because this task manager uses custom chains for each protocol
    task.rules = task.rules.map { |rule|
      if rule.protocol.nil?
        rule.class.protocols.values.map { |prot|
          new_rule = rule.dup
          new_rule.protocol = prot
          new_rule
        }
      else
        rule
      end
    }.flatten
  
    task.rules.each { |rule|
      # Direct iptables rules to their vnic's custom chains
      if rule.is_a?(IptablesRule) && self.enable_iptables
        case rule.table
          when :nat
            case rule.chain
              when :prerouting.to_s.upcase then
                #unless rule.rule.include? "-j DNAT"
                  #rule.chain = "#{vnic[:uuid]}_dnat_exceptions"
                #end
                #p rule.chain
                #rule.chain = "#{bound[rule.bound]}_#{vnic[:uuid]}_#{nat_chains[rule.chain]}"
                #p rule.chain
              when :postrouting.to_s.upcase then
                # Very hackish but should work for now
                if rule.rule.include? "-j SNAT"
                  rule.chain = "#{vnic[:uuid]}_snat"
                else
                  rule.chain = "#{vnic[:uuid]}_snat_exceptions"
                end
                #rule.chain = "#{bound[rule.bound]}_#{vnic[:uuid]}_#{nat_chains[rule.chain]}"
            end
          when :filter
            case rule.chain
              when :forward.to_s.upcase then
                rule.chain = "#{bound[rule.bound]}_#{vnic[:uuid]}_#{rule.protocol}"
            end
        end
      # Direct ebtables rules to their vnic's custom chains
      elsif rule.is_a?(EbtablesRule) && self.enable_ebtables
        case rule.table
          when :filter then
            case rule.chain
              when :input.to_s.upcase then
                rule.chain = "s_#{vnic[:uuid]}_d_hst_#{rule.protocol}"
              when :output.to_s.upcase then
                rule.chain = "d_#{vnic[:uuid]}_s_hst_#{rule.protocol}"
              when :forward.to_s.upcase then
                rule.chain = "#{bound[rule.bound]}_#{vnic[:uuid]}_#{rule.protocol}"
            end
        end
      end
    }
  }
  
  new_tasks
end