17 #use constant FO => { chain => "ipac~fo", parent => "FORWARD", iface =>"--in" }; |
17 #use constant FO => { chain => "ipac~fo", parent => "FORWARD", iface =>"--in" }; |
18 #use constant I => { chain => "ipac~i", parent => "OUTPUT", iface => "--in" }; |
18 #use constant I => { chain => "ipac~i", parent => "OUTPUT", iface => "--in" }; |
19 #use constant O => { chain => "ipac~o", parent => "INPUT", iface => "--out" }; |
19 #use constant O => { chain => "ipac~o", parent => "INPUT", iface => "--out" }; |
20 |
20 |
21 my %TARGETS = ( |
21 my %TARGETS = ( |
22 "ipac~fi" => { chain => "ipac~fi", parent => "FORWARD", iface => "--in-interface" }, |
22 "ipac~fi" => |
23 "ipac~fo" => { chain => "ipac~fo", parent => "FORWARD", iface => "--out-interface" }, |
23 { chain => "ipac~fi", parent => "FORWARD", iface => "--in-interface" }, |
24 "ipac~i" => { chain => "ipac~i", parent => "OUTPUT", iface => "--out-interface" }, |
24 "ipac~fo" => |
25 "ipac~o" => { chain => "ipac~o", parent => "INPUT", iface => "--in-interface" }, |
25 { chain => "ipac~fo", parent => "FORWARD", iface => "--out-interface" }, |
|
26 "ipac~i" => |
|
27 { chain => "ipac~i", parent => "OUTPUT", iface => "--out-interface" }, |
|
28 "ipac~o" => |
|
29 { chain => "ipac~o", parent => "INPUT", iface => "--in-interface" }, |
26 ); |
30 ); |
27 |
31 |
28 use constant FILE => $ENV{IPAC_RULES} ? $ENV{IPAC_RULES} : "/etc/ipac-ng/rules.conf"; |
32 use constant FILE => $ENV{IPAC_RULES} |
|
33 ? $ENV{IPAC_RULES} |
|
34 : "/etc/ipac-ng/rules.conf"; |
29 |
35 |
30 use constant CONFIG => ( |
36 use constant CONFIG => ( |
31 { CASE => 1 }, |
37 { CASE => 1 }, |
32 nothing => { ARGS => "!", DEFAULT => 0 }, |
38 nothing => { ARGS => "!", DEFAULT => 0 }, |
33 verbose => { ARGS => "!", DEFAULT => 0 }, |
39 verbose => { ARGS => "!", DEFAULT => 0 }, |
34 ); |
40 ); |
35 |
41 |
36 my $Cf = new AppConfig CONFIG or die; |
42 my $Cf = new AppConfig CONFIG or die; |
37 $Cf->getopt or die; |
43 $Cf->getopt or die; |
38 |
44 |
39 sub checkTarget($); |
45 sub checkTarget($); |
40 sub insertTarget($); |
46 sub insertTarget($); |
41 sub cleanTarget($); |
47 sub cleanTarget($); |
42 sub parseConfig($); |
48 sub parseConfig($); |
43 sub expand($); |
49 sub expand($); |
44 |
50 |
45 MAIN: { |
51 MAIN: { |
46 my @cmds; |
52 my @cmds; |
47 |
53 |
48 # Check, if our rules exist |
54 # Check, if our rules exist |
49 foreach (keys %TARGETS) { |
55 foreach (keys %TARGETS) { |
50 checkTarget($TARGETS{$_}) |
56 checkTarget($TARGETS{$_}) |
51 or push @cmds, insertTarget($TARGETS{$_}); |
57 or push @cmds, insertTarget($TARGETS{$_}); |
52 |
58 |
53 push @cmds, cleanTarget($TARGETS{$_}); |
59 push @cmds, cleanTarget($TARGETS{$_}); |
54 } |
60 } |
55 |
61 |
56 |
|
57 my ($iptables, $rules) = parseConfig(FILE); |
62 my ($iptables, $rules) = parseConfig(FILE); |
58 push @cmds, @$iptables; |
63 push @cmds, @$iptables; |
59 |
64 |
60 |
|
61 foreach (@cmds) { |
65 foreach (@cmds) { |
62 print "@$_\n" if $Cf->verbose or $Cf->nothing; |
66 print "@$_\n" if $Cf->verbose or $Cf->nothing; |
63 next if $Cf->nothing; |
67 next if $Cf->nothing; |
64 system @$_ and do { |
68 system @$_ and do { |
65 warn "FAILED: @$_\n" if not $Cf->verbose; |
69 warn "FAILED: @$_\n" if not $Cf->verbose; |
66 }; |
70 }; |
67 } |
71 } |
68 |
72 |
69 if (!$Cf->nothing) { |
73 if (!$Cf->nothing) { |
70 open(RUNFILE, $_ = ">/var/run/ipac.rules") or die "Can't open $_: $!\n"; |
74 open(RUNFILE, $_ = ">/var/run/ipac.rules") or die "Can't open $_: $!\n"; |
71 print RUNFILE join "\n", @$rules; |
75 print RUNFILE join "\n", @$rules; |
72 close(RUNFILE); |
76 close(RUNFILE); |
73 } |
77 } |
74 } |
78 } |
75 |
79 |
76 { |
80 { |
77 my $dump; |
81 my $dump; |
78 sub checkTarget($) { |
|
79 my $target = shift; |
|
80 |
82 |
81 if (!$dump) { |
83 sub checkTarget($) { |
82 open(X, "iptables-save|") or die "Can't open iptables-save: $!\n"; |
84 my $target = shift; |
83 $dump = join "", grep /^:/, <X>; |
85 |
84 close(X); |
86 if (!$dump) { |
|
87 open(X, "iptables-save|") or die "Can't open iptables-save: $!\n"; |
|
88 $dump = join "", grep /^:/, <X>; |
|
89 close(X); |
|
90 } |
|
91 |
|
92 return $dump =~ /^:$target->{chain}/m |
|
93 |
85 } |
94 } |
86 |
95 } |
87 return $dump =~ /^:$target->{chain}/m |
|
88 |
|
89 } } |
|
90 |
96 |
91 sub insertTarget($) { |
97 sub insertTarget($) { |
92 my $target = shift; |
98 my $target = shift; |
93 |
99 |
94 return ( |
100 return ( |
95 ["iptables", "--new-chain" => $target->{chain}], |
101 ["iptables", "--new-chain" => $target->{chain}], |
96 ["iptables", |
102 [ |
97 "--insert" => $target->{parent}, |
103 "iptables", |
98 "--jump" => $target->{chain}] |
104 "--insert" => $target->{parent}, |
99 ); |
105 "--jump" => $target->{chain} |
|
106 ] |
|
107 ); |
100 } |
108 } |
101 |
109 |
102 sub cleanTarget($) { |
110 sub cleanTarget($) { |
103 my $target = shift; |
111 my $target = shift; |
104 return ["iptables", |
112 return ["iptables", "--flush" => $target->{chain}]; |
105 "--flush" => $target->{chain}]; |
|
106 } |
113 } |
107 |
114 |
108 sub parseConfig($) { |
115 sub parseConfig($) { |
109 my (@iptables, @rules); |
116 my (@iptables, @rules); |
110 my $file = shift; |
117 my $file = shift; |
111 local(@ARGV) = ($file); |
118 local (@ARGV) = ($file); |
112 |
119 |
113 die ME.": Can't open $file: $!\n" if not -r $file; |
120 die ME . ": Can't open $file: $!\n" if not -r $file; |
114 |
121 |
115 @ARGV = ($file); |
122 @ARGV = ($file); |
116 |
123 |
117 # Read the config file and create the iptables statements |
124 # Read the config file and create the iptables statements |
118 while (<>) { |
125 while (<>) { |
119 s/#.*//; |
126 s/#.*//; |
120 s/^\s*$//; |
127 s/^\s*$//; |
121 next unless $_; |
128 next unless $_; |
122 |
129 |
123 chomp; |
130 chomp; |
124 |
131 |
|
132 my (%src, %dst); |
|
133 (my ($name, $target, $iface, $proto), $src{ip}, $dst{ip}) = |
|
134 split /\s*\|\s*/, $_; |
125 |
135 |
126 my (%src, %dst); |
136 # $src / $dst |
127 (my ($name, $target, $iface, $proto), $src{ip}, $dst{ip}) |
137 foreach (\%src, \%dst) { |
128 = split /\s*\|\s*/, $_; |
138 @{$_}{qw/ip port/} = split /[:\s]/, $_->{ip}; |
|
139 } |
129 |
140 |
130 # $src / $dst |
141 my @cmd = ( |
131 foreach (\%src, \%dst) { |
142 "iptables", |
132 @{$_}{qw/ip port/} = split /[:\s]/, $_->{ip}; |
143 "--append" => $target, |
133 } |
144 $TARGETS{$target}->{iface} => $iface, |
|
145 "--src" => expand($src{ip}), |
|
146 "--dst" => expand($dst{ip}), |
|
147 "--proto" => expand($proto), |
|
148 $src{port} ? ("--sport" => $src{port}) : (), |
|
149 $dst{port} ? ("--dport" => $dst{port}) : (), |
|
150 ); |
134 |
151 |
135 |
152 push @iptables, \@cmd; |
136 my @cmd = ("iptables", |
153 push @rules, "$target|$name"; |
137 "--append" => $target, |
|
138 $TARGETS{$target}->{iface} => $iface, |
|
139 "--src" => expand($src{ip}), |
|
140 "--dst" => expand($dst{ip}), |
|
141 "--proto" => expand($proto), |
|
142 $src{port} ? ("--sport" => $src{port}) : (), |
|
143 $dst{port} ? ("--dport" => $dst{port}) : (), |
|
144 ); |
|
145 |
|
146 push @iptables, \@cmd; |
|
147 push @rules, "$target|$name"; |
|
148 } |
154 } |
149 |
155 |
150 return \@iptables, \@rules; |
156 return \@iptables, \@rules; |
151 } |
157 } |
152 |
158 |