iptables-ruby 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/CHANGELOG +23 -0
- data/Gemfile +6 -0
- data/Generate.md +278 -0
- data/LICENSE +20 -0
- data/README.md +140 -0
- data/Rakefile +44 -0
- data/bin/check_firewall.rb +220 -0
- data/examples/policy/macros.json +92 -0
- data/examples/policy/policy.json +208 -0
- data/examples/policy/policy6.json +8 -0
- data/examples/policy/primitives.json +40 -0
- data/examples/policy/rules.json +30 -0
- data/examples/policy/services.json +81 -0
- data/lib/iptables.rb +5 -0
- data/lib/iptables/configuration.rb +116 -0
- data/lib/iptables/expansions.rb +189 -0
- data/lib/iptables/logger.rb +5 -0
- data/lib/iptables/primitives.rb +51 -0
- data/lib/iptables/tables.rb +851 -0
- data/test/common.rb +22 -0
- data/test/tc_all.rb +7 -0
- data/test/tc_comparison.rb +751 -0
- data/test/tc_configuration.rb +72 -0
- data/test/tc_expansions.rb +116 -0
- data/test/tc_primitives.rb +35 -0
- data/test/tc_tables.rb +652 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3cdee7f713d4749034b6106e46c562312fccbaf2
|
4
|
+
data.tar.gz: 24934051d8029a1798b7b8d5319274d68c2b5cce
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1bb21c4234d7b3880faa9c16aefac00b474856938f1ea2975e482238f9771b37bf24fca3af16dec71303d11db8302ed7f2785e3e37de0de898cee712562f8c9d
|
7
|
+
data.tar.gz: 5ef4fc170a0121d151963910e332ad064d622de4d1ce11e8592deca2cfaf383010cef6e496bb6cc4a5fb67ed2f5d99db966ef86d6cac69c4f25da71949baa86d
|
data/.gitignore
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
0.2.4
|
2
|
+
- Fix comparison corner case.
|
3
|
+
- Nagios example script can read iptables output from file.
|
4
|
+
- Fix Ruby 1.9-unfriendly bugs
|
5
|
+
|
6
|
+
0.2.3
|
7
|
+
- Compare two iptables.
|
8
|
+
- Add documentation.
|
9
|
+
- Add Nagios example script
|
10
|
+
- Add example policy files.
|
11
|
+
|
12
|
+
0.2.2
|
13
|
+
- Generate multi-table output correctly.
|
14
|
+
|
15
|
+
0.2.1
|
16
|
+
- Properly handle merging on top of a policy with a nil table.
|
17
|
+
|
18
|
+
0.2.0
|
19
|
+
- New Rule parameter: "has_primitive":
|
20
|
+
- Do not evaluate or add a rule if it requires a non-existent primitive.
|
21
|
+
|
22
|
+
0.1.0
|
23
|
+
- initial release
|
data/Gemfile
ADDED
data/Generate.md
ADDED
@@ -0,0 +1,278 @@
|
|
1
|
+
# Generating a firewall
|
2
|
+
|
3
|
+
A complete, generated firewall requires several JSON configuration
|
4
|
+
sections. These can either be compiled into one long JSON file or split
|
5
|
+
into separate files. An example usable firewall has been included within
|
6
|
+
this gem's `examples/policy` directory.
|
7
|
+
|
8
|
+
# Example JSON configuration files
|
9
|
+
|
10
|
+
## macros.json
|
11
|
+
|
12
|
+
This file defines macros, which are reusable rules or sets of rules.
|
13
|
+
Each macro consists of an identifier (example `accept-established`), and
|
14
|
+
its expansion. For more on rules, see section `Rules`.
|
15
|
+
|
16
|
+
## policy.json
|
17
|
+
|
18
|
+
This file defines policy, which is the "top-level" configuration
|
19
|
+
for your **desired** iptables rules.
|
20
|
+
|
21
|
+
Assuming you are using configuration-management software such as
|
22
|
+
[http://www.opscode.com/chef](Chef), you can set one policy for all of
|
23
|
+
your hosts, and then customize your policy per host using rules (see
|
24
|
+
`rules.json`) and primitives (see `primitives.json`).
|
25
|
+
|
26
|
+
The policy file is a hash of the four "standard" iptables tables:
|
27
|
+
`filter`, `mangle`, `nat`, and `raw`. Each of these can in turn either
|
28
|
+
be a hash configuring the table, or `null`.
|
29
|
+
|
30
|
+
### `null`
|
31
|
+
|
32
|
+
If `null`, the policy for that table will be "whatever is already
|
33
|
+
defined". For example, the example configuration file shows
|
34
|
+
`"mangle": null`, which means: "if there is a `mangle` table, use its
|
35
|
+
rules, otherwise leave this table undefined".
|
36
|
+
|
37
|
+
### hash
|
38
|
+
|
39
|
+
If a hash, the table must contain a hash of table names. These will be
|
40
|
+
the standard tables for the corresponding iptables table. For instance,
|
41
|
+
`filter` should minimally contain `INPUT`, `FORWARD`, and `OUTPUT`.
|
42
|
+
Other user-defined tables may also be defined/named.
|
43
|
+
|
44
|
+
Each defined table must have a `policy`. This can either be `DROP`,
|
45
|
+
`ACCEPT`, or `-`.
|
46
|
+
|
47
|
+
Each defined table must also have a `rules` section. This must be an
|
48
|
+
array of firewall rules. For more on rules, see section `Rules`.
|
49
|
+
|
50
|
+
## policy6.json
|
51
|
+
|
52
|
+
This is the same as `policy.json`, but defines ipv6 rules.
|
53
|
+
|
54
|
+
## primitives.json
|
55
|
+
|
56
|
+
Primitives are values that can be interpolated into other parts of your
|
57
|
+
firewall. For more on how these interpolations are used, see section
|
58
|
+
`Interpolation`.
|
59
|
+
|
60
|
+
## rules.json
|
61
|
+
|
62
|
+
`rules` can be an empty hash, or contain any of the named iptables
|
63
|
+
tables (`filter`, `nat`, etc). Any named table is **added** to the rules
|
64
|
+
defined by policy (see example `policy.json`).
|
65
|
+
|
66
|
+
If a table is **not** found in policy, it is added to the generated
|
67
|
+
firewall. It is advised to define at least all standard chains for the
|
68
|
+
table. For instance, `nat` should minimally contain `INPUT`, `OUTPUT`,
|
69
|
+
`POSTROUTING` and `PREROUTING`, and each of these should minimally
|
70
|
+
contain a `policy` definition.
|
71
|
+
|
72
|
+
If a table **is** found in policy, each specified chain can either
|
73
|
+
override or modify the existing table within the policy.
|
74
|
+
|
75
|
+
### Overriding Chain Policy
|
76
|
+
|
77
|
+
Set `"policy": "ACCEPT"` or any other valid policy.
|
78
|
+
|
79
|
+
### Overriding Chain Rules
|
80
|
+
|
81
|
+
Set `"rules": []`. In this case, rules will be reset to be empty.
|
82
|
+
Alternately, fill the array with rules (see section `Rules`).
|
83
|
+
|
84
|
+
### Adding Chain Rules
|
85
|
+
|
86
|
+
Set `"additions": []`. Rules (see section `Rules`) added into this array
|
87
|
+
will be added at node addition points within the policy rules (see
|
88
|
+
section `additions`).
|
89
|
+
|
90
|
+
## services.json
|
91
|
+
|
92
|
+
This file defines services that you will be using within your firewall.
|
93
|
+
See section `Rules` on how to define each service.
|
94
|
+
|
95
|
+
Once defined, a service may be used within policy, rules, or macros.
|
96
|
+
|
97
|
+
# Rules
|
98
|
+
|
99
|
+
Rules fall within an array, and can consist of strings or hashes.
|
100
|
+
|
101
|
+
## String Rules
|
102
|
+
|
103
|
+
A policy that is a string is inserted as-is into the policy
|
104
|
+
firewall, preceded by `-A the_chain_name`. A very simple firewall could
|
105
|
+
consist solely of string rules.
|
106
|
+
|
107
|
+
## Hash rules
|
108
|
+
|
109
|
+
Other kinds of rules are defined as hashes, with the hash key denoting
|
110
|
+
the type of rule:
|
111
|
+
|
112
|
+
### `comment`
|
113
|
+
|
114
|
+
This is shorthand for an iptables comment:
|
115
|
+
|
116
|
+
"comment": "comment1"
|
117
|
+
|
118
|
+
becomes
|
119
|
+
|
120
|
+
-A chain_name -m comment --comment "comment1"
|
121
|
+
|
122
|
+
The `chain_name` is the name of the chain in which the `comment` rule is
|
123
|
+
found.
|
124
|
+
|
125
|
+
### `interpolated`
|
126
|
+
|
127
|
+
See section "Interpolating strings"
|
128
|
+
|
129
|
+
### `macro`
|
130
|
+
|
131
|
+
This inserts the requested macro (see section `macros.json`) into the
|
132
|
+
rules.
|
133
|
+
|
134
|
+
### `node_addition_points`
|
135
|
+
|
136
|
+
See section "`additions` and `node_addition_points`"
|
137
|
+
|
138
|
+
### `service`
|
139
|
+
|
140
|
+
This inserts the requested service (see section `services.json`) into
|
141
|
+
the rules.
|
142
|
+
|
143
|
+
### `service_tcp`
|
144
|
+
|
145
|
+
This takes an integer or string as an argument and inserts a permitted
|
146
|
+
inbound TCP port into the rules:
|
147
|
+
|
148
|
+
"service_tcp": 8080
|
149
|
+
|
150
|
+
becomes
|
151
|
+
|
152
|
+
-A chain_name -p tcp -m tcp --sport 1024:65535 --dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT
|
153
|
+
|
154
|
+
Port ranges such as `"8080:8090"` can also be used. The `chain_name` is
|
155
|
+
the name of the chain in which the `service_tcp` rule is found.
|
156
|
+
|
157
|
+
### `service_udp`
|
158
|
+
|
159
|
+
This is identical to `service_tcp`, except that it inserts a permitted
|
160
|
+
inbound UDP port.
|
161
|
+
|
162
|
+
### `ulog`
|
163
|
+
|
164
|
+
This is shorthand for an iptables logging statement:
|
165
|
+
|
166
|
+
"ulog": ""
|
167
|
+
|
168
|
+
becomes
|
169
|
+
|
170
|
+
-A chain_name -m limit --limit 1/sec --limit-burst 2 -j ULOG --ulog-prefix "chain_name:"
|
171
|
+
|
172
|
+
This can also use `-p tcp`:
|
173
|
+
|
174
|
+
"ulog": "-p tcp"
|
175
|
+
|
176
|
+
becomes
|
177
|
+
|
178
|
+
-A chain_name -p tcp -m limit --limit 1/sec --limit-burst 2 -j ULOG --ulog-prefix "chain_name:"
|
179
|
+
|
180
|
+
The `chain_name` is the name of the chain in which the `ulog` rule is
|
181
|
+
found.
|
182
|
+
|
183
|
+
# Interpolation
|
184
|
+
|
185
|
+
Primitives (see section `primitives.json`) are available within your
|
186
|
+
configuration using the `<%%>` notation within an `interpolated` rule.
|
187
|
+
|
188
|
+
## Interpolating strings
|
189
|
+
|
190
|
+
An example usage is:
|
191
|
+
|
192
|
+
"interpolated": "-s <% internet.subnet.other %> -d <% internet.address %> -i <% internet.device %> -j ACCEPT"
|
193
|
+
|
194
|
+
Depending upon the defined primitives, the above rule could expand into:
|
195
|
+
|
196
|
+
-s 192.0.2.0/24 -d 198.51.100.10/32 -i eth0 -j ACCEPT
|
197
|
+
|
198
|
+
## Interpolating arrays
|
199
|
+
|
200
|
+
Primitives that are defined as an array, such as `iana_reserved` in the
|
201
|
+
example `primitives.json`, will expand into multiple rules. For instance
|
202
|
+
|
203
|
+
"interpolated": "-s <% iana_reserved %> -j DROP"
|
204
|
+
|
205
|
+
would expand into
|
206
|
+
|
207
|
+
-s 0.0.0.0/8 -j DROP
|
208
|
+
-s 5.0.0.0/8 -j DROP
|
209
|
+
-s 10.0.0.0/8 -j DROP
|
210
|
+
-s 36.0.0.0/7 -j DROP
|
211
|
+
-s 39.0.0.0/8 -j DROP
|
212
|
+
-s 42.0.0.0/8 -j DROP
|
213
|
+
-s 49.0.0.0/8 -j DROP
|
214
|
+
-s 100.0.0.0/6 -j DROP
|
215
|
+
-s 104.0.0.0/7 -j DROP
|
216
|
+
-s 106.0.0.0/8 -j DROP
|
217
|
+
-s 127.0.0.0/8 -j DROP
|
218
|
+
-s 179.0.0.0/8 -j DROP
|
219
|
+
-s 185.0.0.0/8 -j DROP
|
220
|
+
-s 240.0.0.0/4 -j DROP
|
221
|
+
-s 169.254.0.0/16 -j DROP
|
222
|
+
-s 172.16.0.0/12 -j DROP
|
223
|
+
-s 192.0.2.0/24 -j DROP
|
224
|
+
-s 192.88.99.0/24 -j DROP
|
225
|
+
-s 192.168.0.0/16 -j DROP
|
226
|
+
|
227
|
+
|
228
|
+
# `additions` and `node_addition_points`
|
229
|
+
|
230
|
+
Since adding rules to a policy firewall is very common, there is a
|
231
|
+
shorthand for adding rules to one or more policy chains at predefined
|
232
|
+
points.
|
233
|
+
|
234
|
+
For instance, you may define the following policy (see `Rules`):
|
235
|
+
|
236
|
+
"policy": {
|
237
|
+
(other chains)
|
238
|
+
"in_public": {
|
239
|
+
"policy": "ACCEPT",
|
240
|
+
"rules": {
|
241
|
+
{ "comment": "comment1" },
|
242
|
+
{
|
243
|
+
"node_addition_points": [
|
244
|
+
"in_public",
|
245
|
+
"in_*"
|
246
|
+
]
|
247
|
+
}
|
248
|
+
{ "comment": "comment2" },
|
249
|
+
}
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
253
|
+
You may then also choose to define the following rules:
|
254
|
+
|
255
|
+
"rules": {
|
256
|
+
"filter": {
|
257
|
+
"in_public": {
|
258
|
+
"additions": [
|
259
|
+
"comment": "public"
|
260
|
+
]
|
261
|
+
},
|
262
|
+
"in_*": {
|
263
|
+
"additions": [
|
264
|
+
"comment": "all"
|
265
|
+
]
|
266
|
+
}
|
267
|
+
}
|
268
|
+
}
|
269
|
+
|
270
|
+
The `rules` defined within the `in_public` chain or `in_*`
|
271
|
+
pseudo-chain would be added at the `node_addition_points` within the
|
272
|
+
table. So the generated firewall would contain:
|
273
|
+
|
274
|
+
-A in_public -m comment --comment "comment1"
|
275
|
+
-A in_public -m comment --comment "public"
|
276
|
+
-A in_public -m comment --comment "all"
|
277
|
+
-A in_public -m comment --comment "comment2"
|
278
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Library of Congress
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
Description
|
2
|
+
===========
|
3
|
+
|
4
|
+
Iptables-gem is a Ruby API for parsing, generating, and comparing Linux
|
5
|
+
iptables rules. It is configured using JSON and oriented toward use
|
6
|
+
within configuration-management software such as
|
7
|
+
[http://www.opscode.com/chef/](Chef).
|
8
|
+
|
9
|
+
Requirements
|
10
|
+
============
|
11
|
+
|
12
|
+
## Ruby:
|
13
|
+
|
14
|
+
* Ruby: 1.8
|
15
|
+
* Likely also works on 1.9, but testing is giving me fits so I am ignoring it for now
|
16
|
+
|
17
|
+
## Platforms:
|
18
|
+
|
19
|
+
The following platforms and versions are tested:
|
20
|
+
|
21
|
+
* Ubuntu 10.04, 12.04
|
22
|
+
* CentOS 6.4, Red Hat 6.4
|
23
|
+
|
24
|
+
Ruby Usage
|
25
|
+
==========
|
26
|
+
|
27
|
+
Install this gem and `require iptables`. In the examples below,
|
28
|
+
`/path/to/json/` refers to the directory containing JSON policy files.
|
29
|
+
See [Generate.md](the firewall generation documentation) for information
|
30
|
+
on setting these up. There are also example configuration files in
|
31
|
+
`examples/policy/*.json`.
|
32
|
+
|
33
|
+
## Generate a firewall
|
34
|
+
|
35
|
+
You will first need to create JSON firewall configuration files. See the
|
36
|
+
`Generating a Firewall` section below for details. Once this is done,
|
37
|
+
you can generate a firewall like so:
|
38
|
+
|
39
|
+
config = IPTables::Configuration.new
|
40
|
+
config.parse_files('/path/to/json/')
|
41
|
+
policy_fw = config.converge_firewall
|
42
|
+
puts policy_fw.as_array
|
43
|
+
|
44
|
+
## Compare two firewalls
|
45
|
+
|
46
|
+
You can determine whether a proposed/policy firewall and the
|
47
|
+
currently-applied firewall are identical:
|
48
|
+
|
49
|
+
config = IPTables::Configuration.new
|
50
|
+
config.parse_files('/path/to/json/')
|
51
|
+
policy_fw = config.converge_firewall
|
52
|
+
active_fw = IPTables::Tables.new(%x/iptables-save/)
|
53
|
+
comparison = IPTables::TablesComparison.new(active_fw, policy_fw)
|
54
|
+
comparison.equal?
|
55
|
+
|
56
|
+
Alternately, you can compare firewalls using only `iptables-save` output:
|
57
|
+
|
58
|
+
active_fw = IPTables::Tables.new(%x/iptables-save/)
|
59
|
+
other_fw = IPTables::Tables.new(File.readlines('/path/to/another/saved/firewall'))
|
60
|
+
comparison = IPTables::TablesComparison.new(active_fw, policy_fw)
|
61
|
+
comparison.equal?
|
62
|
+
|
63
|
+
If two firewalls are the same **except** for embedded firewall comments,
|
64
|
+
you can ignore comments:
|
65
|
+
|
66
|
+
comparison.ignore_comments
|
67
|
+
comparison.equal?
|
68
|
+
|
69
|
+
If you want to see **exactly** how two firewalls differ:
|
70
|
+
|
71
|
+
comparison.as_array
|
72
|
+
|
73
|
+
## Log
|
74
|
+
|
75
|
+
If you want to see debug messages, turn on logging:
|
76
|
+
|
77
|
+
require 'logger'
|
78
|
+
$log = Logger.new(STDOUT)
|
79
|
+
$log.level = Logger::DEBUG
|
80
|
+
config = IPTables::Configuration.new
|
81
|
+
config.parse_files('/path/to/json/')
|
82
|
+
policy_fw = config.converge_firewall
|
83
|
+
|
84
|
+
Generating a Firewall
|
85
|
+
=====================
|
86
|
+
|
87
|
+
An explanation of generating a firewall can be found within
|
88
|
+
[Generate.md](the firewall generation documentation). An example set of
|
89
|
+
configuration files to create a basic working firewall can be found in
|
90
|
+
`examples/policy/*.json`.
|
91
|
+
|
92
|
+
Included Scripts
|
93
|
+
================
|
94
|
+
|
95
|
+
## Nagios
|
96
|
+
|
97
|
+
The `bin` directory contains a Nagios helper script written in Ruby to
|
98
|
+
compare the running firewall against a "policy" firewall. To try it from
|
99
|
+
within the gem source directory (that is, without first installing the
|
100
|
+
gem), first copy `examples/policy` to a temporary location and edit the
|
101
|
+
policy files to taste. Then change to the `bin` directory and run:
|
102
|
+
|
103
|
+
`./check_firewall.rb -l=/path/to/iptables/gem/lib/ -v -c=/path/to/policy/`
|
104
|
+
|
105
|
+
The above example includes debugging information which makes it
|
106
|
+
unsuitable for use with Nagios. For "live" use with Nagios, you would
|
107
|
+
want to install this gem and run:
|
108
|
+
|
109
|
+
`check_firewall.rb -c=/path/to/policy/`
|
110
|
+
|
111
|
+
Tests
|
112
|
+
=====
|
113
|
+
|
114
|
+
To run unit tests:
|
115
|
+
|
116
|
+
* change to iptables directory
|
117
|
+
* run `rake`
|
118
|
+
* examine coverage reports in directory `coverage`
|
119
|
+
|
120
|
+
Future
|
121
|
+
======
|
122
|
+
|
123
|
+
Changes/Features I would like to see:
|
124
|
+
|
125
|
+
* Is ipv6 even working?
|
126
|
+
* Write policy in YAML **or** JSON
|
127
|
+
* Deprecate `requires_primitive`: these should be ignored if there is no matching interpolation
|
128
|
+
* Deprecate `interpolated`: these should be properly handled inside **any** kind of rule
|
129
|
+
* Deprecate `comment` and `ulog`? These seem like they ought to be macros.
|
130
|
+
* `ulog` has `-p tcp` but this seems awkward; is it even useful?
|
131
|
+
* Do other stuff like ebtables too? Not sure it's in scope here. Certainly the gem name would need to be reconsidered.
|
132
|
+
* Generate better error messages when we encounter failures parsing configurations.
|
133
|
+
* Move development/testing/coverage environment to Ruby 1.9
|
134
|
+
|
135
|
+
License and Authors
|
136
|
+
===================
|
137
|
+
|
138
|
+
* Author:: Kurt Yoder <kyoder@loc.gov>
|
139
|
+
|
140
|
+
See LICENSE file for project license information.
|