Puppet: System Administration Automated

Support

Recipes/ModuleIptables: rebuild-iptables-modified

File rebuild-iptables-modified, 8.1 kB (added by mrproper, 3 months ago)

modified rebuilt-iptables

Line 
1 #!/usr/bin/perl -w
2 our $ID = q$Id: rebuild-iptables 344 2006-10-04 02:48:30Z digant $;
3 #
4 # rebuild-iptables -- Construct an iptables rules file from fragments.
5 #
6 # Written by Russ Allbery <rra@stanford.edu>
7 # Adapted by Digant C Kasundra <digant@stanford.edu>
8 # Copyright 2005, 2006 Board of Trustees, Leland Stanford Jr. University
9 #
10 # Constructs an iptables rules file from the prefix, standard, and suffix
11 # files in the iptables configuration area, adding any additional modules
12 # specified in the command line, and prints the resulting iptables rules to
13 # standard output (suitable for saving into /var/lib/iptables or some other
14 # appropriate location on the system).
15
16 ##############################################################################
17 # Modules and declarations
18 ##############################################################################
19
20 require 5.006;
21 use strict;
22
23 use Getopt::Long qw(GetOptions);
24
25 # Path to the iptables template area.
26 our $TEMPLATE   = '/afs/ir/service/jumpstart/data/iptables';
27
28 ##############################################################################
29 # Installation
30 ##############################################################################
31
32 # Return the prefix
33 sub prefix {
34         my $type = shift;
35     my $data;
36         if ( $type eq 'filter' ) {
37         ( $data = <<'END_OF_PREFIX' ) =~ s/^\s+//gm;
38 *filter
39 :INPUT ACCEPT
40 :FORWARD ACCEPT
41 :OUTPUT ACCEPT
42 END_OF_PREFIX
43         }
44         elsif ( $type eq 'mangle' ) {
45         ( $data = <<'END_OF_PREFIX' ) =~ s/^\s+//gm;
46 *nat
47 :PREROUTING ACCEPT
48 :POSTROUTING ACCEPT
49 :OUTPUT ACCEPT
50 END_OF_PREFIX
51         }
52     return $data;
53 }
54
55 # Return the suffix
56 sub suffix {
57     my $data;
58     ( $data = <<'END_OF_SUFFIX' ) =~ s/^\s+//gm;
59         COMMIT
60 END_OF_SUFFIX
61
62     return $data;
63 }
64 # Read in a file, processing includes as required.  Returns the contents of
65 # the file as an array.
66 sub read_iptables {
67     my ($file) = @_;
68     my @data;
69     $file = $TEMPLATE . '/' . $file unless $file =~ m%^\.?/%;
70     open my $MODULE, '<', $file or die "$0: cannot open $file: $!\n";
71     local $_;
72     while (<$MODULE>) {
73         if (/^\s*include\s+(\S+)$/) {
74             my $included = $1;
75             $included = $TEMPLATE . '/' . $included
76                 unless $included =~ m%^\.?/%;
77             if ($file eq $included) {
78                 die "$0: include loop in $file, line $.\n";
79             }
80             push (@data, "\n");
81             push (@data, read_iptables ($included));
82             push (@data, "\n");
83         } elsif (/^\s*include\s/) {
84             die "$0: malformed include line in $file, line $.\n";
85         } else {
86                         # strip comments/whitespace/blank lines out of module
87                         $_ =~ s/\s*#.*$//;
88                         $_ =~ s/^\s*//;
89                         if ( $_ !~ /^\s*$/ ) {
90                 push (@data, $_);
91                         }
92         }
93     }
94     close $MODULE;
95     return @data;
96 }
97
98 # Write a file carefully.
99 # Consider using File::Temp
100 sub write_iptables {
101     my ($file, @data) = @_;
102     open my $NEW, '>', "$file.new" or die "$0: cannot create $file.new: $!\n";
103     print $NEW @data           or die "$0: cannot write to $file.new: $!\n";
104     close $NEW                 or die "$0: cannot flush $file.new: $!\n";
105     rename ("$file.new", $file)
106         or die "$0: cannot install new $file: $!\n";
107 }
108
109 # Install iptables on a Red Hat system.  Takes the array containing the new
110 # iptables data.
111 sub install_redhat {
112     my (@data) = @_;
113     write_iptables ('/etc/sysconfig/iptables', @data);
114     system('/sbin/service', 'iptables', 'restart');
115 }
116
117 # Install iptables on a Debian system.  Take the array containing the new
118 # iptables data.
119 sub install_debian {
120     my (@data) = @_;
121     unless (-d '/etc/iptables') {
122         mkdir ('/etc/iptables', 0755)
123             or die "$0: cannot mkdir /etc/iptables: $!\n";
124     }
125     write_iptables ('/etc/iptables/general', @data);
126     system('/sbin/iptables-restore < /etc/iptables/general');
127 }
128
129 ##############################################################################
130 # Main routine
131 ##############################################################################
132
133 # Fix things up for error reporting.
134 $| = 1;
135 my $fullpath = $0;
136 $0 =~ s%.*/%%;
137
138 # Parse command-line options.
139 my ($help, $version);
140 Getopt::Long::config ('bundling', 'no_ignore_case');
141 GetOptions ('h|help'             => \$help,
142             'v|version'          => \$version) or exit 1;
143 if ($help) {
144     print "Feeding myself to perldoc, please wait....\n";
145     exec ('perldoc', '-t', $fullpath);
146 } elsif ($version) {
147     my $version = join (' ', (split (' ', $ID))[1..3]);
148     $version =~ s/,v\b//;
149     $version =~ s/(\S+)$/($1)/;
150     $version =~ tr%/%-%;
151     print $version, "\n";
152     exit;
153 }
154 my ( @filter_modules, @mangle_modules );
155
156 if ( -d '/etc/iptables.d' ) {
157     @filter_modules = </etc/iptables.d/filter-*>;
158     @mangle_modules = </etc/iptables.d/mangle-*>;
159         print "Filter modules found: " . join(', ', @filter_modules) . "\n";
160         print "Mangle modules found: " . join(', ', @mangle_modules) . "\n";
161 }
162
163 # Concatenate everything together.
164 my @data;
165 push (@data, prefix('filter'));
166 push (@data, "\n");
167 for my $module (@filter_modules) {
168     push (@data, read_iptables($module));
169     push (@data, "\n");
170 }
171 push (@data, suffix());
172
173 push (@data, prefix('mangle'));
174 push (@data, "\n");
175 for my $module (@mangle_modules) {
176     push (@data, read_iptables($module));
177     push (@data, "\n");
178 }
179 push (@data, suffix());
180
181 if (-f '/etc/debian_version') {
182     install_debian (@data);
183 } elsif (-f '/etc/redhat-release') {
184     install_redhat (@data);
185 } else {
186     die "$0: cannot figure out whether this is Red Hat or Debian\n";
187 }
188
189 exit 0;
190 __END__
191
192 ##############################################################################
193 # Documentation
194 ##############################################################################
195
196 =head1 NAME
197
198 rebuild-iptables - Construct an iptables rules file from fragments
199
200 =head1 SYNOPSIS
201
202 rebuild-iptables [B<-hv>]
203
204 =head1 DESCRIPTION
205
206 B<rebuild-iptables> constructs an iptables configuration file by concatenating
207 various modules found in F</etc/iptables.d>.  The resulting iptables
208 configuration file is written to the appropriate file for either Red Hat or
209 Debian (determined automatically) and iptables is restarted.
210
211 Each module is just a text file located in the directory mentioned above that
212 contains one or more iptables configuration lines (basically the arguments to
213 an B<iptables> invocation), possibly including comments.
214
215 NOTE: the module name needs to be prefixed with either filter- or mangle- . For
216 example: /etc/iptables.d/filter-foo. This is required so the rules can be put
217 in the appropriate table.
218
219 WARNING: if the module name is not prefixed with filter- or mangle- it WILL be
220 ignored.
221
222 Along with the modules in the directory specified, a standard prefix and suffix
223 is added.
224
225 Normally, the contents of each module are read in verbatim, but a module may
226 also contain the directive:
227
228     include <module>
229
230 on a separate line, where <module> is the path to another module to include,
231 specified the same way as modules given on the command line (hence, either a
232 file name relative to F</afs/ir/service/jumpstart/data/iptables> or an
233 absolute path).  Such a line will be replaced with the contents of the named
234 file.  Be careful when using this directive to not create loops; files
235 including themselves will be detected, but more complex loops will not and
236 will result in infinite output.
237
238 =head1 OPTIONS
239
240 =over 4
241
242 =item B<-h>, B<--help>
243
244 Print out this documentation (which is done simply by feeding the script to
245 C<perldoc -t>).
246
247 =item B<-v>, B<--version>
248
249 Print out the version of B<rebuild-iptables> and exit.
250
251 =back
252
253 =head1 FILES
254
255 =over 4
256
257 =item F</etc/iptables.d>
258
259 The default module location.
260
261 =item F</etc/debian_version>
262
263 If this file exists, the system is assumed to be a Debian system for
264 determining the installation location when B<-i> is used.
265
266 =item F</etc/iptables/general>
267
268 The install location of the generated configuration file on Debian.
269
270 =item F</etc/redhat-release>
271
272 If this file exists, the system is assumed to be a Red Hat system for
273 determining the installation location when B<-i> is used.
274
275 =item F</etc/sysconfig/iptables>
276
277 The install location of the generated configuration file on Red Hat.
278
279 =back
280
281 =head1 AUTHOR
282
283 Russ Allbery <rra@stanford.edu>
284 Digant C Kasundra <digant@stanford.edu>
285
286 =head1 SEE ALSO
287
288 iptables(8)
289
290 =cut
291