ript 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.rbenv-version +1 -0
- data/AUTHORS.md +16 -0
- data/CHANGELOG.md +93 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +62 -0
- data/LICENCE +19 -0
- data/README.md +564 -0
- data/Rakefile +136 -0
- data/bin/rbenv-sudo +18 -0
- data/bin/ript +207 -0
- data/dist/init.d +48 -0
- data/examples/accept-multiple-from-and-to.rb +16 -0
- data/examples/accept-with-a-list-of-ports.rb +13 -0
- data/examples/accept-with-specific-port-and-interface.rb +14 -0
- data/examples/accept-without-specific-from.rb +11 -0
- data/examples/accept.rb +12 -0
- data/examples/basic.rb +4 -0
- data/examples/dash-in-partition-name.rb +2 -0
- data/examples/drop.rb +11 -0
- data/examples/duplicate-partition-names/foobar1.rb +2 -0
- data/examples/duplicate-partition-names/foobar2.rb +2 -0
- data/examples/errors-undefined-method-with-no-match.rb +12 -0
- data/examples/errors-undefined-method.rb +12 -0
- data/examples/forward-dnat-with-different-destination-port.rb +16 -0
- data/examples/forward-dnat-with-explicit-from-and-port-mappings.rb +11 -0
- data/examples/forward-dnat-with-explicit-from-and-ports.rb +11 -0
- data/examples/forward-dnat-with-explicit-from.rb +11 -0
- data/examples/forward-dnat-with-explicit-protocols.rb +15 -0
- data/examples/forward-dnat-with-multiple-froms.rb +13 -0
- data/examples/forward-dnat-with-multiple-ports.rb +10 -0
- data/examples/forward-dnat-with-multiple-sources.rb +15 -0
- data/examples/forward-dnat.rb +16 -0
- data/examples/forward-snat-with-explicit-from.rb +16 -0
- data/examples/forward-snat-with-multiple-sources.rb +13 -0
- data/examples/forward-snat.rb +9 -0
- data/examples/log-and-accept.rb +12 -0
- data/examples/log-and-drop.rb +11 -0
- data/examples/log-dnat.rb +10 -0
- data/examples/log-snat.rb +13 -0
- data/examples/log.rb +11 -0
- data/examples/missing-address-definition-in-destination.rb +15 -0
- data/examples/missing-address-definition-in-from.rb +15 -0
- data/examples/multiple-partitions-in-this-file.rb +14 -0
- data/examples/multiple-partitions/bar.rb +11 -0
- data/examples/multiple-partitions/foo.rb +17 -0
- data/examples/partition-name-exactly-20-characters.rb +2 -0
- data/examples/partition-name-longer-than-20-characters.rb +2 -0
- data/examples/postclean.rb +10 -0
- data/examples/preclean.rb +10 -0
- data/examples/raw-with-chain-deletion.rb +9 -0
- data/examples/raw-with-flush.rb +9 -0
- data/examples/raw.rb +50 -0
- data/examples/reject.rb +11 -0
- data/examples/space-in-partition-name.rb +2 -0
- data/features/cli.feature +115 -0
- data/features/dsl/errors.feature +107 -0
- data/features/dsl/filter.feature +187 -0
- data/features/dsl/logging.feature +114 -0
- data/features/dsl/nat.feature +271 -0
- data/features/dsl/raw.feature +28 -0
- data/features/setup.feature +58 -0
- data/features/step_definitions/cli_steps.rb +15 -0
- data/features/step_definitions/example_steps.rb +44 -0
- data/features/support/env.rb +25 -0
- data/lib/ript/bootstrap.rb +20 -0
- data/lib/ript/dsl.rb +14 -0
- data/lib/ript/dsl/primitives.rb +7 -0
- data/lib/ript/dsl/primitives/common.rb +78 -0
- data/lib/ript/dsl/primitives/filter.rb +145 -0
- data/lib/ript/dsl/primitives/nat.rb +206 -0
- data/lib/ript/dsl/primitives/raw.rb +45 -0
- data/lib/ript/exceptions.rb +2 -0
- data/lib/ript/partition.rb +162 -0
- data/lib/ript/patches.rb +10 -0
- data/lib/ript/rule.rb +70 -0
- data/lib/ript/version.rb +3 -0
- data/ript.gemspec +33 -0
- metadata +232 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
Before("@timeout-10") do
|
2
|
+
@aruba_timeout_seconds = 10
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^the output from "([^"]*)" should match:$/ do |cmd, partial_output|
|
6
|
+
output_from(cmd).should =~ /#{partial_output}/
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^the output from "([^"]*)" should contain exactly:$/ do |cmd, exact_output|
|
10
|
+
output_from(cmd).should == exact_output
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^I have no iptables rules loaded$/ do
|
14
|
+
run_simple("rake clean_slate")
|
15
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
Before do
|
2
|
+
rules_src = File.join(File.dirname(__FILE__), '..', '..', 'examples', '.')
|
3
|
+
rules_dest = File.join(current_dir, 'examples')
|
4
|
+
FileUtils.mkdir_p(rules_dest)
|
5
|
+
FileUtils.cp_r(rules_src, rules_dest)
|
6
|
+
end
|
7
|
+
|
8
|
+
Then /^the created chain name in all tables should match$/ do
|
9
|
+
lines = all_output.split("\n")
|
10
|
+
|
11
|
+
lines.each do |line|
|
12
|
+
@chain_names ||= []
|
13
|
+
if line =~ /^# /
|
14
|
+
@chain_name = line[2..-1]
|
15
|
+
@chain_names = ['s', 'd', 'a'].map { |table| client, hash = @chain_name.split(/-/); "#{client}-#{table}#{hash}" }
|
16
|
+
end
|
17
|
+
|
18
|
+
next if line.size == 0
|
19
|
+
next if line =~ /--(new-chain|jump) partition-/
|
20
|
+
next if line =~ /--(new-chain|jump) ript_bootstrap-/
|
21
|
+
|
22
|
+
line.should match(%r{(^\# #{@chain_name})|(#{@chain_names.join('|')})}) if line !~ /LOG/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
When /^I generate rules for packet filtering$/ do
|
27
|
+
examples_path = Pathname.new(__FILE__).parent.parent.parent.join('examples')
|
28
|
+
|
29
|
+
examples = Dir.glob("#{examples_path}/{accept,drop,reject,log}*.rb")
|
30
|
+
examples.each do |example|
|
31
|
+
run_simple("ript rules generate #{example}")
|
32
|
+
commands = all_output.split("\n").find_all {|line| line =~ /^iptables/ }
|
33
|
+
|
34
|
+
@all_outputs ||= []
|
35
|
+
@all_outputs += commands
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Then /^I should see a protocol specified when a port is specified$/ do
|
40
|
+
dports = @all_outputs.find_all {|line| line =~ /dport/}
|
41
|
+
dports.each do |command|
|
42
|
+
command.should =~ / --protocol /
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'aruba/cucumber'
|
6
|
+
require 'colorize'
|
7
|
+
|
8
|
+
if Process.uid != 0
|
9
|
+
puts "You need to be root to run these tests!"
|
10
|
+
abort
|
11
|
+
end
|
12
|
+
|
13
|
+
def clean_slate_after_2_minutes
|
14
|
+
root = Pathname.new(__FILE__).parent.parent.parent
|
15
|
+
path = ENV['PATH']
|
16
|
+
|
17
|
+
clean_command = "export PATH=#{path} && echo 'cd #{root} && rake clean_slate'"
|
18
|
+
at_command = "at 'now + 2 minutes' >/dev/null 2>&1"
|
19
|
+
command = "#{clean_command} | #{at_command}"
|
20
|
+
|
21
|
+
puts "If these tests lock you out, all iptables rules will be flushed in 2 minutes.\n".yellow
|
22
|
+
system(command)
|
23
|
+
end
|
24
|
+
|
25
|
+
clean_slate_after_2_minutes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ript
|
2
|
+
class Bootstrap
|
3
|
+
def self.partition
|
4
|
+
rules = []
|
5
|
+
|
6
|
+
rules << Rule.new("table" => "filter", "new-chain" => "partition-a")
|
7
|
+
rules << Rule.new("table" => "filter", "insert" => "INPUT 1", "jump" => "partition-a")
|
8
|
+
rules << Rule.new("table" => "filter", "insert" => "OUTPUT 1", "jump" => "partition-a")
|
9
|
+
rules << Rule.new("table" => "filter", "insert" => "FORWARD 1", "jump" => "partition-a")
|
10
|
+
|
11
|
+
rules << Rule.new("table" => "nat", "new-chain" => "partition-d")
|
12
|
+
rules << Rule.new("table" => "nat", "insert" => "PREROUTING 1", "jump" => "partition-d")
|
13
|
+
|
14
|
+
rules << Rule.new("table" => "nat", "new-chain" => "partition-s")
|
15
|
+
rules << Rule.new("table" => "nat", "insert" => "POSTROUTING 1", "jump" => "partition-s")
|
16
|
+
|
17
|
+
Partition.new('ript_bootstrap', nil, :rules => rules)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/ript/dsl.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if RUBY_VERSION =~ /^1.8/ then
|
4
|
+
puts "Ript requires Ruby 1.9 to run. Exiting."
|
5
|
+
exit 2
|
6
|
+
end
|
7
|
+
|
8
|
+
$: << Pathname.new(__FILE__).dirname.parent.expand_path.to_s
|
9
|
+
|
10
|
+
require 'ript/dsl/primitives'
|
11
|
+
require 'ript/rule'
|
12
|
+
require 'ript/partition'
|
13
|
+
require 'ript/exceptions'
|
14
|
+
require 'ript/patches'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Ript
|
4
|
+
module DSL
|
5
|
+
module Primitives
|
6
|
+
module Common
|
7
|
+
def label(label, opts={})
|
8
|
+
@labels[label] = opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def interface(arg)
|
12
|
+
@interface = arg
|
13
|
+
end
|
14
|
+
|
15
|
+
def ports(*args)
|
16
|
+
if args.class == Array
|
17
|
+
args.each do |port|
|
18
|
+
if port.class == Range
|
19
|
+
@ports << "#{port.begin}:#{port.end}"
|
20
|
+
else
|
21
|
+
@ports << port
|
22
|
+
end
|
23
|
+
end
|
24
|
+
else
|
25
|
+
port = args
|
26
|
+
@ports << port
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def from(*label)
|
31
|
+
label.flatten!(2)
|
32
|
+
if label.is_a?(Array)
|
33
|
+
label.each do |l|
|
34
|
+
@froms << l
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@froms << label
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def to(*label)
|
42
|
+
label.flatten!(2)
|
43
|
+
if label.is_a?(Array)
|
44
|
+
label.each do |l|
|
45
|
+
@tos << l
|
46
|
+
end
|
47
|
+
else
|
48
|
+
@tos << label
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def protocols(*args)
|
53
|
+
# FIXME: refactor to just use flatten!
|
54
|
+
if args.class == Array
|
55
|
+
args.each do |protocol|
|
56
|
+
@protocols << protocol
|
57
|
+
end
|
58
|
+
else
|
59
|
+
protocol = args
|
60
|
+
@protocols << protocol
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate(opts={})
|
65
|
+
opts.each_pair do |type, label|
|
66
|
+
if not label_exists?(label)
|
67
|
+
raise LabelError, "Address '#{label}' (a #{type}) isn't defined"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def label_exists?(label)
|
73
|
+
@labels.has_key?(label)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Ript
|
4
|
+
module DSL
|
5
|
+
module Primitives
|
6
|
+
module Filter
|
7
|
+
# Accept traffic to/from a destination/source.
|
8
|
+
#
|
9
|
+
# This allows traffic for a particular port/protocol to be passed into
|
10
|
+
# userland on the local machine.
|
11
|
+
def accept(name, opts={}, &block)
|
12
|
+
opts.merge!(:jump => "ACCEPT")
|
13
|
+
build_rule(name, block, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Reject traffic to/from a destination/source.
|
17
|
+
#
|
18
|
+
# Send an error packet back for traffic that matches.
|
19
|
+
def reject(name, opts={}, &block)
|
20
|
+
opts.merge!(:jump => "REJECT")
|
21
|
+
build_rule(name, block, opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Drop traffic to/from a destination/source.
|
25
|
+
#
|
26
|
+
# Silently drop packets that match.
|
27
|
+
def drop(name, opts={}, &block)
|
28
|
+
opts.merge!(:jump => "DROP")
|
29
|
+
build_rule(name, block, opts)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Log traffic to/from a destination/source.
|
33
|
+
#
|
34
|
+
# Log packets that match via the kernel log (read with dmesg or syslog).
|
35
|
+
def log(name, opts={}, &block)
|
36
|
+
opts.merge!(:jump => "LOG")
|
37
|
+
build_rule(name, block, opts)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
# Construct a rule to be applied to the `filter` table.
|
42
|
+
#
|
43
|
+
# This method is used to construct simple rules on the filter table to
|
44
|
+
# accept/reject/drop/log traffic to and from various addresses.
|
45
|
+
#
|
46
|
+
# Accepts a block of the actual rule definition to evaluate, and
|
47
|
+
# appends the generated rule to the @table instance variable on the
|
48
|
+
# partition instance.
|
49
|
+
#
|
50
|
+
# This method returns nothing.
|
51
|
+
#
|
52
|
+
def build_rule(name, block, opts={})
|
53
|
+
@froms = []
|
54
|
+
@tos = []
|
55
|
+
@ports = []
|
56
|
+
@protocols = []
|
57
|
+
insert = opts[:insert] || "partition-a"
|
58
|
+
jump = opts[:jump] || "DROP"
|
59
|
+
log = opts[:log]
|
60
|
+
|
61
|
+
# Evaluate the block.
|
62
|
+
instance_eval &block
|
63
|
+
|
64
|
+
# Default all rules to apply to TCP packets if no protocol is specified
|
65
|
+
@protocols << 'TCP' if @protocols.size == 0
|
66
|
+
|
67
|
+
@protocols.map! {|protocol| {"protocol" => protocol} }
|
68
|
+
@ports.map! {|port| {"dport" => port} }
|
69
|
+
|
70
|
+
# Provide a default from address, so the @ports => @protocols => @froms
|
71
|
+
# nested iteration below works.
|
72
|
+
@froms << 'all' if @froms.size == 0
|
73
|
+
|
74
|
+
@froms.each do |from|
|
75
|
+
@tos.each do |to|
|
76
|
+
validate(:from => from, :to => to)
|
77
|
+
|
78
|
+
from_address = @labels[from][:address]
|
79
|
+
to_address = @labels[to][:address]
|
80
|
+
|
81
|
+
attributes = {
|
82
|
+
"table" => "filter",
|
83
|
+
"insert" => insert,
|
84
|
+
"destination" => to_address,
|
85
|
+
"jump" => "#{@name}-a",
|
86
|
+
}
|
87
|
+
@input << Rule.new(attributes)
|
88
|
+
@input << Rule.new(attributes.merge("jump" => "LOG")) if log
|
89
|
+
|
90
|
+
attributes = {
|
91
|
+
"table" => "filter",
|
92
|
+
"append" => "#{@name}-a",
|
93
|
+
"destination" => to_address,
|
94
|
+
"source" => from_address,
|
95
|
+
"jump" => jump
|
96
|
+
}
|
97
|
+
attributes.insert_before("destination", "in-interface" => @interface) if @interface
|
98
|
+
|
99
|
+
# Build up a list of arguments we need to build expanded rules.
|
100
|
+
#
|
101
|
+
# This allows us to expand shorthand definitions like:
|
102
|
+
#
|
103
|
+
# accept "multiple rules in one" do
|
104
|
+
# from "foo", "bar", "baz"
|
105
|
+
# to "spoons"
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# ... into multiple rules, one ACCEPT rule for foo, bar, baz.
|
109
|
+
#
|
110
|
+
case
|
111
|
+
when @ports.size > 0 && @protocols.size > 0
|
112
|
+
# build the rules based on the arguments supplied
|
113
|
+
arguments = @protocols.product(@ports).map {|ary| ary.inject(:merge) }
|
114
|
+
when @ports.size == 0 && @protocols.size > 0
|
115
|
+
arguments = @protocols
|
116
|
+
when @protocols.size == 0 && @ports.size > 0
|
117
|
+
arguments = @ports
|
118
|
+
else
|
119
|
+
arguments = []
|
120
|
+
end
|
121
|
+
|
122
|
+
# If we have arguments, iterate through them
|
123
|
+
if arguments.size > 0
|
124
|
+
arguments.each do |options|
|
125
|
+
options.each_pair do |key, value|
|
126
|
+
attributes = attributes.dup # avoid overwriting existing hash values from previous iterations
|
127
|
+
attributes.insert_before("destination", key => value)
|
128
|
+
end
|
129
|
+
|
130
|
+
@table << Rule.new(attributes.merge("jump" => "LOG")) if log
|
131
|
+
@table << Rule.new(attributes)
|
132
|
+
end
|
133
|
+
else
|
134
|
+
@table << Rule.new(attributes.merge("jump" => "LOG")) if log
|
135
|
+
@table << Rule.new(attributes)
|
136
|
+
end # if
|
137
|
+
end # @tos.each
|
138
|
+
end # @froms.each
|
139
|
+
|
140
|
+
end # def build_rule
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
@@ -0,0 +1,206 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Ript
|
4
|
+
module DSL
|
5
|
+
module Primitives
|
6
|
+
module NAT
|
7
|
+
def rewrite(name, opts={}, &block)
|
8
|
+
# Reset these so parameters don't leak between calls to forward.
|
9
|
+
@sources = []
|
10
|
+
@destinations = []
|
11
|
+
@ports = []
|
12
|
+
@protocols = []
|
13
|
+
@tos = []
|
14
|
+
@froms = []
|
15
|
+
log = opts[:log]
|
16
|
+
|
17
|
+
@snat_sources = []
|
18
|
+
@snat_destinations = []
|
19
|
+
|
20
|
+
# Evaluate the block.
|
21
|
+
instance_eval &block
|
22
|
+
|
23
|
+
# Default all rules to apply to TCP packets if no protocol is specified
|
24
|
+
@protocols << 'TCP' if @protocols.size == 0
|
25
|
+
|
26
|
+
@snat_sources.zip(@snat_destinations) do |source, destination|
|
27
|
+
validate(:source => source, :destination => destination)
|
28
|
+
|
29
|
+
source_address = @labels[source][:address]
|
30
|
+
destination_address = @labels[destination][:address]
|
31
|
+
|
32
|
+
attributes = { "table" => "nat",
|
33
|
+
"insert" => "partition-s",
|
34
|
+
"source" => source_address,
|
35
|
+
"jump" => "#{@name}-s" }
|
36
|
+
|
37
|
+
fattributes = { "table" => "filter",
|
38
|
+
"insert" => "partition-a",
|
39
|
+
"source" => source_address,
|
40
|
+
"jump" => "#{@name}-a" }
|
41
|
+
|
42
|
+
@postrouting << Rule.new(attributes)
|
43
|
+
@postrouting << Rule.new(attributes.merge("jump" => "LOG")) if log
|
44
|
+
@input << Rule.new(fattributes)
|
45
|
+
@input << Rule.new(fattributes.merge("jump" => "LOG")) if log
|
46
|
+
|
47
|
+
|
48
|
+
attributes = { "table" => "nat",
|
49
|
+
"append" => "#{@name}-s",
|
50
|
+
"source" => source_address,
|
51
|
+
"jump" => "SNAT",
|
52
|
+
"to-source" => destination_address }
|
53
|
+
|
54
|
+
fattributes = { "table" => "filter",
|
55
|
+
"append" => "#{@name}-a",
|
56
|
+
"source" => source_address,
|
57
|
+
"jump" => "ACCEPT" }
|
58
|
+
|
59
|
+
@froms.map {|from| @labels[from][:address]}.each do |address|
|
60
|
+
attributes.insert_before("destination", "source" => address)
|
61
|
+
end
|
62
|
+
|
63
|
+
@table << Rule.new(attributes.merge("jump" => "LOG")) if log
|
64
|
+
@table << Rule.new(attributes)
|
65
|
+
@table << Rule.new(fattributes.merge("jump" => "LOG")) if log
|
66
|
+
@table << Rule.new(fattributes)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# Provide a default from address, so the @ports => @protocols => @froms
|
71
|
+
# nested iteration below works.
|
72
|
+
@froms << 'all' if @froms.size == 0
|
73
|
+
|
74
|
+
# Build up rules based on evaluation.
|
75
|
+
@sources.zip(@destinations).each do |source, destination|
|
76
|
+
validate(:source => source, :destination => destination)
|
77
|
+
|
78
|
+
source_address = @labels[source][:address]
|
79
|
+
destination_address = @labels[destination][:address]
|
80
|
+
|
81
|
+
attributes = { "table" => "nat",
|
82
|
+
"insert" => "partition-d",
|
83
|
+
"destination" => source_address,
|
84
|
+
"jump" => "#{@name}-d" }
|
85
|
+
|
86
|
+
fattributes = { "table" => "filter",
|
87
|
+
"insert" => "partition-a",
|
88
|
+
"destination" => destination_address,
|
89
|
+
"jump" => "#{@name}-a" }
|
90
|
+
|
91
|
+
@prerouting << Rule.new(attributes)
|
92
|
+
@prerouting << Rule.new(attributes.merge("jump" => "LOG")) if log
|
93
|
+
@input << Rule.new(fattributes)
|
94
|
+
@input << Rule.new(fattributes.merge("jump" => "LOG")) if log
|
95
|
+
|
96
|
+
@ports.each do |port|
|
97
|
+
@protocols.each do |protocol|
|
98
|
+
@froms.map {|from| @labels[from][:address]}.each do |from_address|
|
99
|
+
if port.class == Hash
|
100
|
+
port.each_pair do |source_port, destination_port|
|
101
|
+
attributes = { "table" => "nat",
|
102
|
+
"append" => "#{@name}-d",
|
103
|
+
"protocol" => protocol,
|
104
|
+
"destination" => source_address,
|
105
|
+
"dport" => source_port,
|
106
|
+
"jump" => "DNAT",
|
107
|
+
"to-destination" => destination_address + ":#{destination_port}" }
|
108
|
+
|
109
|
+
fattributes = { "table" => "filter",
|
110
|
+
"append" => "#{@name}-a",
|
111
|
+
"protocol" => protocol,
|
112
|
+
"destination" => destination_address,
|
113
|
+
"dport" => destination_port,
|
114
|
+
"jump" => "ACCEPT" }
|
115
|
+
|
116
|
+
attributes.insert_before("destination", "source" => from_address) unless from_address == "0.0.0.0/0"
|
117
|
+
|
118
|
+
@table << Rule.new(attributes.merge("jump" => "LOG")) if log
|
119
|
+
@table << Rule.new(attributes)
|
120
|
+
@table << Rule.new(fattributes.merge("jump" => "LOG")) if log
|
121
|
+
@table << Rule.new(fattributes)
|
122
|
+
end
|
123
|
+
else
|
124
|
+
attributes = { "table" => "nat",
|
125
|
+
"append" => "#{@name}-d",
|
126
|
+
"protocol" => protocol,
|
127
|
+
"destination" => source_address,
|
128
|
+
"dport" => port,
|
129
|
+
"jump" => "DNAT",
|
130
|
+
"to-destination" => destination_address }
|
131
|
+
|
132
|
+
fattributes = { "table" => "filter",
|
133
|
+
"append" => "#{@name}-a",
|
134
|
+
"protocol" => protocol,
|
135
|
+
"destination" => destination_address,
|
136
|
+
"dport" => port,
|
137
|
+
"jump" => "ACCEPT" }
|
138
|
+
|
139
|
+
attributes.insert_before("destination", "source" => from_address) unless from_address == "0.0.0.0/0"
|
140
|
+
|
141
|
+
@table << Rule.new(attributes.merge("jump" => "LOG")) if log
|
142
|
+
@table << Rule.new(attributes)
|
143
|
+
@table << Rule.new(fattributes.merge("jump" => "LOG")) if log
|
144
|
+
@table << Rule.new(fattributes)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def dnat(opts={})
|
153
|
+
opts.each_pair do |source, destination|
|
154
|
+
# If the source argument to dnat is an Array:
|
155
|
+
#
|
156
|
+
# dnat [ "www.bar.com",
|
157
|
+
# "secure.bar.com",
|
158
|
+
# "static.bar.com" ] => "barprod-proxy-01"
|
159
|
+
#
|
160
|
+
# loop through each source, and create the associated destination.
|
161
|
+
if source.is_a?(Array)
|
162
|
+
source.each do |s|
|
163
|
+
@sources << s
|
164
|
+
@destinations << destination
|
165
|
+
end
|
166
|
+
# If the source is just a plain label:
|
167
|
+
#
|
168
|
+
# dnat "www.bar.com" => "barprod-proxy-01"
|
169
|
+
#
|
170
|
+
# simply add it and the destination to the collection.
|
171
|
+
else
|
172
|
+
@sources << source
|
173
|
+
@destinations << destination
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def snat(opts={})
|
179
|
+
opts.each_pair do |source, destination|
|
180
|
+
# If the source argument to snat is an Array:
|
181
|
+
#
|
182
|
+
# snat [ "www.bar.com",
|
183
|
+
# "secure.bar.com",
|
184
|
+
# "static.bar.com" ] => "barprod-proxy-01"
|
185
|
+
#
|
186
|
+
# loop through each source, and create the associated destination.
|
187
|
+
if source.is_a?(Array)
|
188
|
+
source.each do |s|
|
189
|
+
@snat_sources << s
|
190
|
+
@snat_destinations << destination
|
191
|
+
end
|
192
|
+
# If the source is just a plain label:
|
193
|
+
#
|
194
|
+
# snat "www.bar.com" => "barprod-proxy-01"
|
195
|
+
#
|
196
|
+
# simply add it and the destination to the collection.
|
197
|
+
else
|
198
|
+
@snat_sources << source
|
199
|
+
@snat_destinations << destination
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|