riptables 1.0.0
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +130 -0
- data/bin/riptables +34 -0
- data/lib/riptables.rb +26 -0
- data/lib/riptables/chain.rb +17 -0
- data/lib/riptables/condition.rb +25 -0
- data/lib/riptables/dsl/global.rb +30 -0
- data/lib/riptables/dsl/root.rb +19 -0
- data/lib/riptables/dsl/rule.rb +30 -0
- data/lib/riptables/dsl/table.rb +43 -0
- data/lib/riptables/error.rb +4 -0
- data/lib/riptables/role_condition.rb +16 -0
- data/lib/riptables/rule.rb +39 -0
- data/lib/riptables/rule_permutation.rb +41 -0
- data/lib/riptables/table.rb +29 -0
- data/lib/riptables/table_export.rb +40 -0
- data/lib/riptables/version.rb +3 -0
- data/lib/riptables/zone_condition.rb +14 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6163673be40ac8debc91fbbb58b934d622a0551b
|
4
|
+
data.tar.gz: 834420f08005d80abf266219d82445f9187b42cb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ffcca219d8afdab19f25844fa2e6352cd49f5149e7254fc70c691864db89c7698a4d7950639b9a93900165544cfe5bfb0b65901903352f1b3fa7d19eaaa71153
|
7
|
+
data.tar.gz: 97b4c44f8ec3b26978c6cf7e3bca149a7dfa79277f4f77db1e627beacf47f84b25e123444b427653e94bd8e1d087e6264a6a60ce26f48942e739ad7007b4c5e0
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2014 Adam Cooke.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
# Riptables
|
2
|
+
|
3
|
+
Riptables (pronounced ri-pee-tables) is a Ruby DSL for generating configuration
|
4
|
+
for IP tables. The following design goals were employed for development:
|
5
|
+
|
6
|
+
* Must support IPv4 and IPv6 rules
|
7
|
+
* Must allow a single file to contain configuration for multiple environments
|
8
|
+
based on a given `role` and `zone`.
|
9
|
+
* Must support any type of table or chain.
|
10
|
+
* Must support any rule or action without limitation.
|
11
|
+
* Must include a command line tool for exporting configuration.
|
12
|
+
* Should be simple to understand the configuration syntax.
|
13
|
+
* Should be well documentated.
|
14
|
+
|
15
|
+
## `FirewallFile` Syntax
|
16
|
+
|
17
|
+
Riptables works with `FirewallFile` which contains the complete configuration for
|
18
|
+
all servers where this configuration will be distributed. In this example, we're
|
19
|
+
just going to configure a single rule to drop everything except SSH.
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
# Using the `table` method we define a new table. In this case, we'll be
|
23
|
+
# configuring a simple firewall.
|
24
|
+
table :filter do
|
25
|
+
|
26
|
+
# Set some default actions for the three main chains in the filter table.
|
27
|
+
# The action you enter will simply be passed to iptables. If it is a symbol
|
28
|
+
# it will be uppercased otherwise it will be passed through un-touched.
|
29
|
+
default_action :input, :drop
|
30
|
+
default_action :forward, :accept
|
31
|
+
default_action :output, :accept
|
32
|
+
|
33
|
+
# In it's most basic form, you can add rules by simply calling the name of the
|
34
|
+
# chain and a description.
|
35
|
+
input "Allow SSH" do
|
36
|
+
# Set the conditions for the rule you want to apply. This is passed unfettered
|
37
|
+
# to iptables so you can write anything you would normally before the -j flag.
|
38
|
+
rule "-p tcp --dport 22"
|
39
|
+
# Set the action to take if the rule is matched. If this is a symbol it will
|
40
|
+
# be uppercased automatically. If it's a string, it will be passed stright
|
41
|
+
# through after a -j flag.
|
42
|
+
action :accept
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
### Permutations
|
49
|
+
|
50
|
+
If you have rules which are always similar to other rules (for example a set of
|
51
|
+
IP ranges which must all be permitted) you can use permutations.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
input "Allow web access" do
|
55
|
+
rule "-p tcp --dport {{port}}"
|
56
|
+
action :accept
|
57
|
+
permutation "Insecure", :port => "80"
|
58
|
+
permutation "Secure", :port => "443"
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
Each permutation will be applied as its own rule using the base rule as a template.
|
63
|
+
Using the variable interpolation, you can insert any variable you wish in each
|
64
|
+
permutation. The final `:v => 4` option sets that this should only apply to the
|
65
|
+
IPv4 firewall - it can be set to 6 to only apply them to IPv6 firewalls.
|
66
|
+
|
67
|
+
### Zones & Roles
|
68
|
+
|
69
|
+
If you have different types of servers and want to apply different rules based
|
70
|
+
on what and where a machine is, you can do so. You can either limit whole rules
|
71
|
+
or just permutations within a rule.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# Any rules which are defined within this role block will only be included when
|
75
|
+
# you generate an iptables config for the `vpn` role.
|
76
|
+
role :vpn do
|
77
|
+
|
78
|
+
input "Allow management access" do
|
79
|
+
rule "-s {{ip}}"
|
80
|
+
action :accept
|
81
|
+
permutation "Allow Internal", :ip => '10.0.0.0/16', :v => 4
|
82
|
+
permutation "Allow IPv6", :ip => '2a00:67a0:a:123::/64', :v => 6
|
83
|
+
|
84
|
+
# Any permutations within this block will only be included when you generate
|
85
|
+
# an iptavles config for any `eu-east` zone or 'us-west-4'.
|
86
|
+
zone /eu\-east\-(\d+)/, "us-west-4" do
|
87
|
+
permutation "aTech Media", :ip => "185.22.208.0/25", :v => 4
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
### IPv4 vs. IPv6
|
95
|
+
|
96
|
+
By default, any rule you configure will apply to both your IPv4 firewall and your
|
97
|
+
IPv6 firewall. However, you can define rule or permutations to only use one or
|
98
|
+
the other.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
input "Block nasty IPv6 person" do
|
102
|
+
rule "-s 2a00:67a0:abc::1234/128"
|
103
|
+
action :drop
|
104
|
+
# Add the `version` option to restrict this rule to the IPv6 firewall only.
|
105
|
+
# You can also use `4` for the IPv4 firewall.
|
106
|
+
version 6
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
You'll see in the previous example, you can pass the `:v` option to permutations
|
111
|
+
to restrict which firewall they belong to. Default rules will always apply to
|
112
|
+
both and cannot currently be different depending on IP version.
|
113
|
+
|
114
|
+
## Command Line
|
115
|
+
|
116
|
+
The `riptables` command is used to generate your iptables-save files. These can
|
117
|
+
then be used with `iptables-restore`.
|
118
|
+
|
119
|
+
```text
|
120
|
+
$ riptables
|
121
|
+
```
|
122
|
+
|
123
|
+
The following options are supported and can be used interchagably:
|
124
|
+
|
125
|
+
* `-4` - return the IPv4 configuration (default)
|
126
|
+
* `-6` - return the IPv6 configuration (defaults to v4)
|
127
|
+
* `-f [PATH]` - path to your FirewallFile (defaults to ./FirewallFile)
|
128
|
+
* `--zone [ZONE]` - set the zone to export configuration for
|
129
|
+
* `--role [ROLE]` - set the role to export configuration for
|
130
|
+
* `--color` - return a [colorized output](http://s.adamcooke.io/14/Vmzd2.png) (useful for debugging)
|
data/bin/riptables
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.expand_path('../../lib', __FILE__))
|
3
|
+
require 'riptables'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
options[:conditions] = {}
|
8
|
+
options[:color] = false
|
9
|
+
ipv = 4
|
10
|
+
load_path = File.expand_path('./FirewallFile')
|
11
|
+
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: riptables [options]"
|
14
|
+
opts.on("-4", "Return IPv6 records") { ipv = 4 }
|
15
|
+
opts.on("-6", "Return IPv6 records") { ipv = 6 }
|
16
|
+
opts.on("-r", "--role [ROLE]", "The role to generate for") { |v| options[:conditions][:role] = v }
|
17
|
+
opts.on("-z", "--zone [ZONE]", "The zone to generate for") { |v| options[:conditions][:zone] = v }
|
18
|
+
opts.on("--color", "Colorize the output") { |v| options[:color] = true }
|
19
|
+
opts.on("--color", "Colorize the output") { |v| options[:color] = true }
|
20
|
+
opts.on("-f", "--file [PATH]", "The Riptables configuration file") { |v| load_path = v }
|
21
|
+
end.parse!
|
22
|
+
|
23
|
+
begin
|
24
|
+
Riptables.load_from_file(load_path)
|
25
|
+
Riptables.tables.each do |table|
|
26
|
+
puts table.export(options).to_savefile(ipv)
|
27
|
+
end
|
28
|
+
rescue Riptables::Error => e
|
29
|
+
$stderr.puts "\e[31m#{e}\e[0m"
|
30
|
+
exit 1
|
31
|
+
rescue => e
|
32
|
+
$stderr.puts "\e[31m#{e.class}: #{e.message}\e[0m"
|
33
|
+
exit 1
|
34
|
+
end
|
data/lib/riptables.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'riptables/dsl/root'
|
2
|
+
require 'riptables/error'
|
3
|
+
|
4
|
+
module Riptables
|
5
|
+
|
6
|
+
#
|
7
|
+
# Store all tables configured
|
8
|
+
#
|
9
|
+
def self.tables
|
10
|
+
@tables ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# Parse a given file
|
15
|
+
#
|
16
|
+
def self.load_from_file(file)
|
17
|
+
if File.file?(file)
|
18
|
+
dsl = DSL::Root.new
|
19
|
+
dsl.instance_eval(File.read(file), file)
|
20
|
+
true
|
21
|
+
else
|
22
|
+
raise Error, "File not found at `#{file}`"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Riptables
|
2
|
+
class Chain
|
3
|
+
|
4
|
+
def initialize(table, name)
|
5
|
+
@table = table
|
6
|
+
@name = name
|
7
|
+
@default_action = :accept
|
8
|
+
@rules = []
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :default_action
|
12
|
+
attr_reader :table
|
13
|
+
attr_reader :name
|
14
|
+
attr_reader :rules
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'riptables/condition'
|
2
|
+
|
3
|
+
module Riptables
|
4
|
+
class Condition
|
5
|
+
|
6
|
+
def self.conditions
|
7
|
+
@conditions ||= []
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(condition, &block)
|
11
|
+
@condition = [condition].flatten
|
12
|
+
@block = block
|
13
|
+
self.call
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :condition
|
17
|
+
|
18
|
+
def call
|
19
|
+
Condition.conditions << self
|
20
|
+
@block.call
|
21
|
+
Condition.conditions.delete(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'riptables/zone_condition'
|
2
|
+
require 'riptables/role_condition'
|
3
|
+
|
4
|
+
module Riptables
|
5
|
+
module DSL
|
6
|
+
class Global
|
7
|
+
|
8
|
+
#
|
9
|
+
# Any rules which are defined while inside this block should only apply
|
10
|
+
# to the associated zones.
|
11
|
+
#
|
12
|
+
def zone(*zones, &block)
|
13
|
+
ZoneCondition.new(zones) do
|
14
|
+
block.call
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Any rules which are defined while inside this block should only apply
|
20
|
+
# to the associated roles.
|
21
|
+
#
|
22
|
+
def role(*roles, &block)
|
23
|
+
RoleCondition.new(roles) do
|
24
|
+
block.call
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'riptables/dsl/global'
|
2
|
+
require 'riptables/table'
|
3
|
+
|
4
|
+
module Riptables
|
5
|
+
module DSL
|
6
|
+
class Root < Global
|
7
|
+
|
8
|
+
#
|
9
|
+
# Rules within a given table
|
10
|
+
#
|
11
|
+
def table(name, &block)
|
12
|
+
table = Riptables::Table.new(name)
|
13
|
+
table.dsl.instance_eval(&block)
|
14
|
+
Riptables.tables << table
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'riptables/dsl/global'
|
2
|
+
require 'riptables/rule_permutation'
|
3
|
+
|
4
|
+
module Riptables
|
5
|
+
module DSL
|
6
|
+
class Rule < Global
|
7
|
+
|
8
|
+
def initialize(rule)
|
9
|
+
@rule = rule
|
10
|
+
end
|
11
|
+
|
12
|
+
def rule(rule)
|
13
|
+
@rule.rule = rule
|
14
|
+
end
|
15
|
+
|
16
|
+
def action(action)
|
17
|
+
@rule.action = action
|
18
|
+
end
|
19
|
+
|
20
|
+
def permutation(description, options = {})
|
21
|
+
@rule.permutations << RulePermutation.new(@rule, description, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def version(number)
|
25
|
+
@rule.versions = [number]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'riptables/dsl/global'
|
2
|
+
require 'riptables/rule'
|
3
|
+
|
4
|
+
module Riptables
|
5
|
+
module DSL
|
6
|
+
class Table < Global
|
7
|
+
|
8
|
+
def initialize(table)
|
9
|
+
@table = table
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Defines a default rule for a chain on this table
|
14
|
+
#
|
15
|
+
def default_action(chain, action)
|
16
|
+
@table.chain(chain).default_action = action
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Add a new rule in this table
|
21
|
+
#
|
22
|
+
def rule(chain, description = nil, &block)
|
23
|
+
rule = Riptables::Rule.new(@table.chain(chain))
|
24
|
+
rule.description = description
|
25
|
+
rule.dsl.instance_eval(&block)
|
26
|
+
@table.chain(chain).rules << rule
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Any method which do not exist are most likely just new rules when inside
|
31
|
+
# this block.
|
32
|
+
#
|
33
|
+
def method_missing(chain, *args, &block)
|
34
|
+
if block_given?
|
35
|
+
self.rule(chain, *args, &block)
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'riptables/condition'
|
2
|
+
|
3
|
+
module Riptables
|
4
|
+
class RoleCondition < Condition
|
5
|
+
|
6
|
+
def matches?(conditions)
|
7
|
+
return false unless conditions[:role]
|
8
|
+
roles = conditions[:role].split(/\s?\,\s?/)
|
9
|
+
roles.each do |role|
|
10
|
+
return true if condition.any? { |c| c.is_a?(Regexp) ? c.match(role) : role.to_s == c.to_s }
|
11
|
+
end
|
12
|
+
return false
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'riptables/dsl/rule'
|
2
|
+
|
3
|
+
module Riptables
|
4
|
+
class Rule
|
5
|
+
|
6
|
+
def initialize(chain)
|
7
|
+
@chain = chain
|
8
|
+
@permutations = []
|
9
|
+
@conditions = Condition.conditions.dup
|
10
|
+
@versions = [4, 6]
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :description
|
14
|
+
attr_accessor :rule
|
15
|
+
attr_accessor :action
|
16
|
+
attr_accessor :conditions
|
17
|
+
attr_accessor :versions
|
18
|
+
attr_reader :chain
|
19
|
+
attr_reader :permutations
|
20
|
+
attr_reader :conditions
|
21
|
+
|
22
|
+
def dsl
|
23
|
+
@dsl ||= DSL::Rule.new(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def include?(conditions)
|
27
|
+
@conditions.all? { |c| c.matches?(conditions) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def permuted_rules
|
31
|
+
if permutations.empty?
|
32
|
+
[self]
|
33
|
+
else
|
34
|
+
permutations.map(&:to_rule)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'riptables/condition'
|
2
|
+
require 'riptables/rule'
|
3
|
+
|
4
|
+
module Riptables
|
5
|
+
class RulePermutation
|
6
|
+
|
7
|
+
def initialize(rule, description, options = {})
|
8
|
+
@rule = rule
|
9
|
+
@description = description
|
10
|
+
@options = options
|
11
|
+
@conditions = Condition.conditions.dup - @rule.conditions
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :rule
|
15
|
+
attr_reader :description
|
16
|
+
attr_reader :options
|
17
|
+
attr_reader :conditions
|
18
|
+
|
19
|
+
#
|
20
|
+
# Convert this permutation into a full rule in its own right
|
21
|
+
#
|
22
|
+
def to_rule
|
23
|
+
new_rule = Rule.new(rule.chain)
|
24
|
+
new_rule.description = "#{rule.description} (#{self.description})"
|
25
|
+
new_rule.rule = rule.rule.gsub(/\{\{(\w+)\}\}/) do
|
26
|
+
if value = self.options[$1.to_sym]
|
27
|
+
value
|
28
|
+
else
|
29
|
+
"{{#{$1}}}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
new_rule.action = rule.action
|
33
|
+
new_rule.conditions = rule.conditions | self.conditions
|
34
|
+
if v = (self.options[:v] || self.options[:version])
|
35
|
+
new_rule.versions = [v.to_i]
|
36
|
+
end
|
37
|
+
new_rule
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'riptables/dsl/table'
|
2
|
+
require 'riptables/chain'
|
3
|
+
require 'riptables/table_export'
|
4
|
+
|
5
|
+
module Riptables
|
6
|
+
class Table
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :chains
|
10
|
+
|
11
|
+
def initialize(name)
|
12
|
+
@name = name
|
13
|
+
@chains = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def dsl
|
17
|
+
@dsl ||= DSL::Table.new(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def chain(name)
|
21
|
+
@chains[name] ||= Chain.new(self, name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def export(options = {})
|
25
|
+
TableExport.new(self, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Riptables
|
2
|
+
class TableExport
|
3
|
+
|
4
|
+
def initialize(table, options = {})
|
5
|
+
@table = table
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_savefile(version = 4)
|
10
|
+
Array.new.tap do |s|
|
11
|
+
s << "*#{col 31, @table.name}"
|
12
|
+
@table.chains.each do |_, chain|
|
13
|
+
s << ":#{col 32, chain.name.to_s.upcase} #{col 35, chain.default_action.to_s.upcase} [0:0]"
|
14
|
+
end
|
15
|
+
|
16
|
+
@table.chains.each do |_, chain|
|
17
|
+
chain.rules.map(&:permuted_rules).flatten.each do |rule|
|
18
|
+
next unless rule.include?(@options[:conditions] || {})
|
19
|
+
next unless rule.versions.include?(version)
|
20
|
+
action = rule.action ? "-j #{rule.action.is_a?(Symbol) ? rule.action.upcase : rule.action}" : ''
|
21
|
+
comment = "-m comment --comment=\"#{rule.description.gsub('"', '\'')}\""
|
22
|
+
s << "-A #{col 32, chain.name.to_s.upcase} #{col 33, rule.rule} #{col 35, action} #{col 36, comment}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
s << "COMMIT"
|
27
|
+
s << "# Compiled by riptables on #{Time.now.strftime("%a %b %e %H:%M:%S %Y")}"
|
28
|
+
end.join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def col(number, text)
|
32
|
+
if @options[:color] == false
|
33
|
+
text
|
34
|
+
else
|
35
|
+
"\e[#{number}m#{text}\e[0m"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'riptables/condition'
|
2
|
+
|
3
|
+
module Riptables
|
4
|
+
class ZoneCondition < Condition
|
5
|
+
|
6
|
+
def matches?(conditions)
|
7
|
+
conditions[:zone] &&
|
8
|
+
condition.any? do |c|
|
9
|
+
c.is_a?(Regexp) ? c.match(conditions[:zone]) : conditions[:zone].to_s == c.to_s
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: riptables
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Cooke
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-21 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: 'An Ruby DSL for generating iptables configuration. '
|
14
|
+
email:
|
15
|
+
- me@adamcooke.io
|
16
|
+
executables:
|
17
|
+
- riptables
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- MIT-LICENSE
|
22
|
+
- README.md
|
23
|
+
- bin/riptables
|
24
|
+
- lib/riptables.rb
|
25
|
+
- lib/riptables/chain.rb
|
26
|
+
- lib/riptables/condition.rb
|
27
|
+
- lib/riptables/dsl/global.rb
|
28
|
+
- lib/riptables/dsl/root.rb
|
29
|
+
- lib/riptables/dsl/rule.rb
|
30
|
+
- lib/riptables/dsl/table.rb
|
31
|
+
- lib/riptables/error.rb
|
32
|
+
- lib/riptables/role_condition.rb
|
33
|
+
- lib/riptables/rule.rb
|
34
|
+
- lib/riptables/rule_permutation.rb
|
35
|
+
- lib/riptables/table.rb
|
36
|
+
- lib/riptables/table_export.rb
|
37
|
+
- lib/riptables/version.rb
|
38
|
+
- lib/riptables/zone_condition.rb
|
39
|
+
homepage: http://adamcooke.io
|
40
|
+
licenses:
|
41
|
+
- MIT
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '2.0'
|
52
|
+
- - "<"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.2.2
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: An Ruby DSL for generating iptables configuration.
|
66
|
+
test_files: []
|
67
|
+
has_rdoc:
|