iptables-ruby 0.2.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.
@@ -0,0 +1,8 @@
1
+ {
2
+ "policy6": {
3
+ "filter": "DROP",
4
+ "mangle": "DROP",
5
+ "nat": "DROP",
6
+ "raw": "DROP"
7
+ }
8
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "primitives": {
3
+ "iana_reserved": [
4
+ "0.0.0.0/8",
5
+ "5.0.0.0/8",
6
+ "10.0.0.0/8",
7
+ "36.0.0.0/7",
8
+ "39.0.0.0/8",
9
+ "42.0.0.0/8",
10
+ "49.0.0.0/8",
11
+ "100.0.0.0/6",
12
+ "104.0.0.0/7",
13
+ "106.0.0.0/8",
14
+ "127.0.0.0/8",
15
+ "179.0.0.0/8",
16
+ "185.0.0.0/8",
17
+ "240.0.0.0/4",
18
+ "169.254.0.0/16",
19
+ "172.16.0.0/12",
20
+ "192.0.2.0/24",
21
+ "192.88.99.0/24",
22
+ "192.168.0.0/16"
23
+ ],
24
+ "internet": {
25
+ "address": "198.51.100.10/32",
26
+ "broadcast": "198.51.100.255/32",
27
+ "device": "eth0",
28
+ "subnet": {
29
+ "internet": "198.51.100.0/24",
30
+ "vpn": "203.0.113.0/24"
31
+ }
32
+ },
33
+ "storage": {
34
+ "address": "192.0.2.100/32",
35
+ "device": "eth1",
36
+ "subnet": "192.0.2.0/24"
37
+ }
38
+ }
39
+ }
40
+
@@ -0,0 +1,30 @@
1
+ {
2
+ "rules": {
3
+ "nat": {
4
+ "INPUT": {
5
+ "policy": "ACCEPT"
6
+ },
7
+ "OUTPUT": {
8
+ "policy": "ACCEPT"
9
+ },
10
+ "POSTROUTING": {
11
+ "policy": "ACCEPT"
12
+ },
13
+ "PREROUTING": {
14
+ "policy": "ACCEPT"
15
+ }
16
+ },
17
+ "filter": {
18
+ "in_*": {
19
+ "additions": []
20
+ },
21
+ "in_peers": {
22
+ "additions": []
23
+ },
24
+ "in_public": {
25
+ "additions": []
26
+ }
27
+ }
28
+ }
29
+ }
30
+
@@ -0,0 +1,81 @@
1
+ {
2
+ "services": {
3
+ "dhcp": "-p udp -m udp --sport 67:68 --dport 67:68 -m state --state NEW,ESTABLISHED -j ACCEPT",
4
+ "domain": [
5
+ "-p udp -m udp --sport 53 --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT",
6
+ {
7
+ "service_udp": "53"
8
+ },
9
+ "-p tcp -m tcp --sport 53 --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT",
10
+ {
11
+ "service_tcp": "53"
12
+ }
13
+ ],
14
+ "http": 80,
15
+ "https": 443,
16
+ "icmp": "-p icmp -m state --state NEW,ESTABLISHED -j ACCEPT",
17
+ "ipp": 631,
18
+ "jabber": [
19
+ {
20
+ "service_tcp": "5222"
21
+ },
22
+ {
23
+ "service_tcp": "5223"
24
+ }
25
+ ],
26
+ "ldap": 389,
27
+ "ldaps": 636,
28
+ "mysql": 3306,
29
+ "nfs": [
30
+ {
31
+ "service_tcp": "2049"
32
+ },
33
+ {
34
+ "service_udp": "2049"
35
+ }
36
+ ],
37
+ "ntp": [
38
+ "-p udp -m udp --sport 123 --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPT",
39
+ {
40
+ "service_udp": "123"
41
+ },
42
+ "-p tcp -m tcp --sport 123 --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPT",
43
+ {
44
+ "service_tcp": "123"
45
+ }
46
+ ],
47
+ "portmap": [
48
+ {
49
+ "service_tcp": "111"
50
+ },
51
+ {
52
+ "service_udp": "111"
53
+ }
54
+ ],
55
+ "postgres": 5432,
56
+ "rabbitmq": [
57
+ {
58
+ "service_tcp": "5670:5680"
59
+ },
60
+ {
61
+ "service_udp": "5670:5680"
62
+ }
63
+ ],
64
+ "smtp": 25,
65
+ "snmp": 161,
66
+ "ssh": 22,
67
+ "syslog": [
68
+ "-p udp -m udp --sport 514 --dport 514 -m state --state NEW,ESTABLISHED -j ACCEPT",
69
+ {
70
+ "service_udp": "514"
71
+ },
72
+ "-p tcp -m tcp --sport 514 --dport 514 -m state --state NEW,ESTABLISHED -j ACCEPT",
73
+ {
74
+ "service_tcp": "514"
75
+ }
76
+ ],
77
+ "tftp": {
78
+ "service_udp": "69"
79
+ }
80
+ }
81
+ }
data/lib/iptables.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'iptables/logger'
2
+ require 'iptables/tables'
3
+ require 'iptables/expansions'
4
+ require 'iptables/primitives'
5
+ require 'iptables/configuration'
@@ -0,0 +1,116 @@
1
+ require 'json'
2
+
3
+ module IPTables
4
+ class Configuration
5
+ @@json_pattern = /\.js(on)?$/
6
+
7
+ def initialize(*args)
8
+ @parsed_hash = {}
9
+ self.parse_files(*args)
10
+ end
11
+
12
+ def parse_files(*args)
13
+ args.each{ |arg|
14
+ $log.debug("reading arg #{arg}")
15
+ case arg
16
+ when @@json_pattern
17
+ handle_json(arg)
18
+ else
19
+ raise "don't know how to handle #{arg.inspect}"
20
+ end
21
+ }
22
+ end
23
+
24
+ def policy(in_policy = nil)
25
+ @policy ||= nil
26
+ return @policy unless @policy.nil?
27
+ unless in_policy.nil?
28
+ @policy = in_policy
29
+ return @policy
30
+ end
31
+ raise 'missing policy' unless @parsed_hash.has_key? 'policy'
32
+ @policy = IPTables::Tables.new(@parsed_hash['policy'], self)
33
+ end
34
+
35
+ def policy6(in_policy = nil)
36
+ @policy6 ||= nil
37
+ return @policy6 unless @policy6.nil?
38
+ unless in_policy.nil?
39
+ @policy6 = in_policy
40
+ return @policy6
41
+ end
42
+ raise 'missing policy6' unless @parsed_hash.has_key? 'policy6'
43
+ @policy6 = IPTables::Tables.new(@parsed_hash['policy6'], self)
44
+ end
45
+
46
+ def interpolations(in_interpolations = nil)
47
+ @interpolations ||= nil
48
+ return @interpolations unless @interpolations.nil?
49
+ unless in_interpolations.nil?
50
+ @interpolations = in_interpolations
51
+ return @interpolations
52
+ end
53
+ @interpolations = IPTables::Interpolations.new(self.primitives)
54
+ end
55
+
56
+ def primitives(in_primitives = nil)
57
+ @primitives ||= nil
58
+ return @primitives unless @primitives.nil?
59
+ unless in_primitives.nil?
60
+ @primitives = in_primitives
61
+ return @primitives
62
+ end
63
+ raise 'missing primitives' unless @parsed_hash.has_key? 'primitives'
64
+ @primitives = IPTables::Primitives.new(@parsed_hash['primitives'])
65
+ end
66
+
67
+ def rules(in_rules = nil)
68
+ @rules ||= nil
69
+ return @rules unless @rules.nil?
70
+ unless in_rules.nil?
71
+ @rules = in_rules
72
+ return @rules
73
+ end
74
+ raise 'missing rules' unless @parsed_hash.has_key? 'rules'
75
+ @rules = IPTables::Tables.new(@parsed_hash['rules'], self)
76
+ end
77
+
78
+ def services(in_services = nil)
79
+ @services ||= nil
80
+ return @services unless @services.nil?
81
+ unless in_services.nil?
82
+ @services = in_services
83
+ return @services
84
+ end
85
+ raise 'missing services' unless @parsed_hash.has_key? 'services'
86
+ @services = IPTables::Services.new(@parsed_hash['services'])
87
+ end
88
+
89
+ def macros(in_macros = nil)
90
+ @macros ||= nil
91
+ return @macros unless @macros.nil?
92
+ unless in_macros.nil?
93
+ @macros = in_macros
94
+ return @macros
95
+ end
96
+ raise 'missing macros' unless @parsed_hash.has_key? 'macros'
97
+ @macros = IPTables::Macros.new(@parsed_hash['macros'])
98
+ end
99
+
100
+ def handle_json(file_name)
101
+ json = File.read(file_name)
102
+ JSON.parse(json).each{ |key, value|
103
+ $log.debug("reading #{key} from file #{file_name}")
104
+ raise "duplicate key: #{key}" if @parsed_hash.has_key? key
105
+ @parsed_hash[key] = value
106
+ }
107
+ end
108
+
109
+ def converge_firewall()
110
+ policy_fw = self.policy
111
+ rules_fw = self.rules
112
+ policy_fw.merge(rules_fw)
113
+ return policy_fw
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,189 @@
1
+ require 'iptables/logger'
2
+
3
+ module IPTables
4
+ class Macros
5
+ attr_reader :named
6
+ def initialize(expansion_hash)
7
+ @expansion_hash = expansion_hash
8
+ @named = {}
9
+ @expansion_hash.each{ |name, info|
10
+ @named[name] = Macro.new(name, info)
11
+ }
12
+ end
13
+ end
14
+
15
+ class Macro
16
+ attr_reader :name, :children
17
+ def initialize(name, info)
18
+ @name = name
19
+ @info = info
20
+ @children = []
21
+
22
+ case info
23
+ when Array
24
+ self.handle_array()
25
+ when Hash
26
+ self.handle_hash()
27
+ when String
28
+ self.handle_string()
29
+ else
30
+ raise "don't know how to handle info: #{info.inspect}"
31
+ end
32
+ end
33
+
34
+ def add_child(rule_hash)
35
+ @children.push(rule_hash)
36
+ end
37
+
38
+ def handle_array()
39
+ @info.each{ |macro_hash|
40
+ self.add_child(macro_hash)
41
+ }
42
+ end
43
+
44
+ def handle_hash()
45
+ self.add_child( @info )
46
+ end
47
+
48
+ def handle_string()
49
+ self.add_child( {'raw' => @info} )
50
+ end
51
+ end
52
+
53
+ class Services
54
+ attr_reader :named
55
+ def initialize(expansion_hash)
56
+ @expansion_hash = expansion_hash
57
+ @named = {}
58
+ @expansion_hash.each{ |name, info|
59
+ @named[name] = Service.new(name, info)
60
+ }
61
+ end
62
+ end
63
+
64
+ class Service
65
+ attr_reader :name, :children
66
+ def initialize(name, info)
67
+ @name = name
68
+ @info = info
69
+ @children = []
70
+
71
+ case info
72
+ when Array
73
+ self.handle_array()
74
+ when Hash
75
+ self.handle_hash()
76
+ when Integer
77
+ self.handle_integer()
78
+ when String
79
+ self.handle_string()
80
+ else
81
+ raise "don't know how to handle info: #{info.inspect}"
82
+ end
83
+ end
84
+
85
+ def add_child(rule_hash)
86
+ @children.push(rule_hash)
87
+ end
88
+
89
+ def handle_array()
90
+ self.add_child( { 'comment' => "_ #{@name}" } )
91
+ raise 'empty @info' if @info.empty?
92
+ @info.each{ |service_info_hash|
93
+ self.add_child(service_info_hash)
94
+ }
95
+ end
96
+
97
+ def handle_hash()
98
+ raise 'empty @info' if @info.empty?
99
+ @info['service_name'] = @name
100
+ self.add_child( @info )
101
+ end
102
+
103
+ def handle_integer()
104
+ self.add_child( { 'comment' => "_ Port #{@info} - #{@name}" } )
105
+ self.add_child({
106
+ 'raw' =>
107
+ "-p tcp -m tcp --sport 1024:65535 --dport #{@info} -m state --state NEW,ESTABLISHED -j ACCEPT"
108
+ })
109
+ end
110
+
111
+ def handle_string()
112
+ self.add_child( { 'comment' => "_ #{@name}" } )
113
+ self.add_child( {'raw' => @info} )
114
+ end
115
+ end
116
+
117
+ class Interpolations
118
+ # interpret strings such as "<% foo.bar %>" into equivalent primitives
119
+ attr_reader :primitives, :named
120
+ def initialize(primitives)
121
+ @primitives = primitives
122
+ $log.debug("interpolations primitives: #{@primitives}")
123
+ @named = {}
124
+ end
125
+
126
+ def add(interpolation_string)
127
+ @named[interpolation_string] = Interpolation.new(self, interpolation_string)
128
+ end
129
+
130
+ def children(interpolation_string)
131
+ self.add(interpolation_string) unless @named.has_key? interpolation_string
132
+ strings = @named[interpolation_string].children()
133
+ returned_array = []
134
+ case strings
135
+ when Array
136
+ strings.each{ |result|
137
+ returned_array.push({'raw' => result})
138
+ }
139
+ else
140
+ returned_array.push({'raw' => strings})
141
+ end
142
+ return returned_array
143
+ end
144
+ end
145
+
146
+ class Interpolation
147
+ @@interpolation_regex = /(.*?)<%\s*(\S+)\s*%>(.*)/
148
+
149
+ def initialize(interpolations, initial_string)
150
+ @interpolations = interpolations
151
+ @initial_string = initial_string
152
+ @child = nil
153
+ if @initial_string =~ @@interpolation_regex
154
+ self.add_child($1, $2, $3)
155
+ else
156
+ $log.debug("completed substitution: #{@initial_string}")
157
+ end
158
+ end
159
+
160
+ def add_child(first, identifier, last)
161
+ interpolated = @interpolations.primitives.substitute(identifier)
162
+ case interpolated
163
+ when Array
164
+ @child = []
165
+ interpolated.each{ |value|
166
+ @child.push(Interpolation.new(@interpolations, "#{first}#{value}#{last}"))
167
+ }
168
+ else
169
+ @child = Interpolation.new(@interpolations, "#{first}#{interpolated}#{last}")
170
+ end
171
+ end
172
+
173
+ def children()
174
+ return_value = nil
175
+ case @child
176
+ when nil
177
+ return_value = @initial_string
178
+ when Array
179
+ return_value = []
180
+ @child.each{ |value|
181
+ return_value.push(value.children())
182
+ }
183
+ else
184
+ return_value = @child.children()
185
+ end
186
+ return return_value
187
+ end
188
+ end
189
+ end