first
This commit is contained in:
commit
e165b427fe
6
debian/README
vendored
Normal file
6
debian/README
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
The Debian Package pf6
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
This program loads different iptables rulesets from its config file.
|
||||||
|
|
||||||
|
-- ROTTLER Tamas <tom@bitfit.hu> Tue, 17 Feb 2015 22:54:04 +0100
|
||||||
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pf6 (1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Initial Release.
|
||||||
|
|
||||||
|
-- ROTTLER Tamas <tom@bitfit.hu> Tue, 17 Feb 2015 14:20:04 +0100
|
||||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
9
|
||||||
14
debian/control
vendored
Normal file
14
debian/control
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
Source: pf6
|
||||||
|
Section: utils
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: ROTTLER Tamas <tom@bitfit.hu>
|
||||||
|
Build-Depends: debhelper (>= 9)
|
||||||
|
Standards-Version: 3.9.5
|
||||||
|
Homepage: http://www.bitfit.hu/
|
||||||
|
|
||||||
|
Package: pf6
|
||||||
|
Architecture: all
|
||||||
|
Depends: perl, iptables
|
||||||
|
Description: iptables/ip6tables ruleset loader
|
||||||
|
This program loads different iptables/ip6tables rulesets from a configuration
|
||||||
|
file.
|
||||||
28
debian/copyright
vendored
Normal file
28
debian/copyright
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: pf6
|
||||||
|
Source: <url://example.com>
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2015 ROTTLER Tamas <tom@bitfit.hu>
|
||||||
|
License: GPL-3.0+
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2015 ROTTLER Tamas <tom@bitfit.hu>
|
||||||
|
License: GPL-3.0+
|
||||||
|
|
||||||
|
License: GPL-3.0+
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
.
|
||||||
|
This package is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
||||||
0
debian/docs
vendored
Normal file
0
debian/docs
vendored
Normal file
2
debian/install
vendored
Normal file
2
debian/install
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pf6 /usr/sbin
|
||||||
|
pf6.conf /etc
|
||||||
12
debian/pf6.init
vendored
Executable file
12
debian/pf6.init
vendored
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: pf6 firewall iptables ip6tables
|
||||||
|
# Required-Start: $syslog $remote_fs
|
||||||
|
# Required-Stop: $syslog $remote_fs
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: pf6 iptables firewall
|
||||||
|
# Description: pf6 iptables/6 firewall initialization
|
||||||
|
### END INIT INFO
|
||||||
|
[ -x /usr/sbin/pf6 ] && exec /usr/sbin/pf6 "$*"
|
||||||
|
exit 0
|
||||||
32
debian/rules
vendored
Executable file
32
debian/rules
vendored
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
# See debhelper(7) (uncomment to enable)
|
||||||
|
# output every command that modifies files on the build system.
|
||||||
|
#DH_VERBOSE = 1
|
||||||
|
|
||||||
|
# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*
|
||||||
|
DPKG_EXPORT_BUILDFLAGS = 1
|
||||||
|
include /usr/share/dpkg/default.mk
|
||||||
|
|
||||||
|
# see FEATURE AREAS in dpkg-buildflags(1)
|
||||||
|
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
|
# see ENVIRONMENT in dpkg-buildflags(1)
|
||||||
|
# package maintainers to append CFLAGS
|
||||||
|
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||||
|
# package maintainers to append LDFLAGS
|
||||||
|
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
||||||
|
|
||||||
|
|
||||||
|
# main packaging script based on dh7 syntax
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
|
|
||||||
|
# debmake generated override targets
|
||||||
|
# This is example for Cmake (See http://bugs.debian.org/641051 )
|
||||||
|
#override_dh_auto_configure:
|
||||||
|
# dh_auto_configure -- \
|
||||||
|
# -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.0 (native)
|
||||||
272
pf6
Executable file
272
pf6
Executable file
@ -0,0 +1,272 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
# Author: ROTTLER Tamas <tom@bitfit.hu>
|
||||||
|
# 2014-12-05 - release
|
||||||
|
# 2014-12-11 - looking for config in FindBin::RealBin
|
||||||
|
# - cleanup: detect tables with policy
|
||||||
|
# - cleanup: no ip6 nat table for kernels < 3.7
|
||||||
|
# 2015-02-17 - debian package
|
||||||
|
# - configuration now in /etc/pf6.conf
|
||||||
|
use strict; use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
print STDERR "Usage: $0 [OPTIONS..] ACTION\n".
|
||||||
|
" OPTIONS:\n".
|
||||||
|
" --verbose|-v print commands\n".
|
||||||
|
" --dry-run only show ip(6)tables commands\n".
|
||||||
|
" --ipv4|-4 IPv4 only\n".
|
||||||
|
" --ipv6|-6 IPv6 only\n".
|
||||||
|
" ACTION:\n".
|
||||||
|
" start|RULESET load given ruleset\n".
|
||||||
|
" stop unload all rules, set ACCEPT policies\n".
|
||||||
|
" restart|force-reload (re)load the 'start' ruleset\n".
|
||||||
|
" status print status (always running)\n";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $self = {
|
||||||
|
config_fn => "/etc/pf6.conf",
|
||||||
|
config => '',
|
||||||
|
iptables => '/sbin/iptables',
|
||||||
|
ip6tables => '/sbin/ip6tables',
|
||||||
|
cleanup_tables => [qw(filter nat mangle raw)],
|
||||||
|
verbose => 0,
|
||||||
|
dryrun => 0
|
||||||
|
};
|
||||||
|
|
||||||
|
sub iptables {
|
||||||
|
my %opts = @_;
|
||||||
|
|
||||||
|
$opts{ip} = '46' if !$opts{ip} or $opts{ip} !~ /[46]/;
|
||||||
|
my @ipts;
|
||||||
|
if ($opts{ip} =~ /4/) {
|
||||||
|
push @ipts, $self->{iptables};
|
||||||
|
}
|
||||||
|
if ($opts{ip} =~ /6/) {
|
||||||
|
push @ipts, $self->{ip6tables};
|
||||||
|
}
|
||||||
|
my @output;
|
||||||
|
for my $ipt (@ipts) {
|
||||||
|
my $cline = "$ipt $opts{cmd}";
|
||||||
|
if (!$opts{query}) {
|
||||||
|
print "pf6 CMD: $cline\n" if $self->{verbose};
|
||||||
|
next if $self->{dryrun};
|
||||||
|
}
|
||||||
|
@output = `$cline 2>&1`;
|
||||||
|
if ($? > 0) {
|
||||||
|
my $ec = $? >> 8;
|
||||||
|
print STDERR "pf6 ERR: exit code $ec on:\n$cline\n" .
|
||||||
|
join('', @output);
|
||||||
|
return 0, @output if $opts{output};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1, @output if $opts{output};
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub kernel_older {
|
||||||
|
my ($vmin) = @_;
|
||||||
|
|
||||||
|
my $output = qx(uname -sr);
|
||||||
|
if ($output !~ /^Linux\s+(\d+)\.(\d+)(\.(\d+))?/) {
|
||||||
|
return 0; # unexpexted output
|
||||||
|
}
|
||||||
|
my @v = ($1, $2, $4);
|
||||||
|
my @m = split /\./, $vmin;
|
||||||
|
|
||||||
|
for (my $i = 0; $i <= $#v and $i <= $#m; $i++) {
|
||||||
|
if ($v[$i] < $m[$i]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub grepchains {
|
||||||
|
my %opts = @_;
|
||||||
|
|
||||||
|
my @output = iptables(
|
||||||
|
cmd => "-n -t $opts{table} -L",
|
||||||
|
query => 1,
|
||||||
|
output => 1,
|
||||||
|
ip => $opts{ip},
|
||||||
|
);
|
||||||
|
|
||||||
|
my @chains;
|
||||||
|
for my $line (@output) {
|
||||||
|
next unless $line =~ /Chain (\S+) \((policy)?/;
|
||||||
|
push @chains, {
|
||||||
|
name => $1,
|
||||||
|
policy => $2 ? 1 : 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return @chains;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub cleanup {
|
||||||
|
my %opts = @_;
|
||||||
|
|
||||||
|
if ($opts{ip} ne '4' and $opts{ip} ne '6') {
|
||||||
|
print "pf6: cleanup: invalid ip protocol\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print "pf6: cleanup ip$opts{ip}..\n";
|
||||||
|
my $error = 0;
|
||||||
|
my $tables = $self->{cleanup_tables};
|
||||||
|
for my $table (@$tables) {
|
||||||
|
if ($opts{ip} eq '6' and kernel_older('3.7') and $table eq 'nat') {
|
||||||
|
# no ip6 nat table before linux 3.7
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
my @chains = grepchains(
|
||||||
|
table => $table,
|
||||||
|
ip => $opts{ip}
|
||||||
|
);
|
||||||
|
# clean up first
|
||||||
|
for my $chain (@chains) {
|
||||||
|
iptables(
|
||||||
|
cmd => "-t $table -F $chain->{name}",
|
||||||
|
ip => $opts{ip}
|
||||||
|
);
|
||||||
|
if ($chain->{policy}) {
|
||||||
|
iptables(
|
||||||
|
cmd => "-t $table -P $chain->{name} ACCEPT",
|
||||||
|
ip => $opts{ip}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# now there are no references to the chains
|
||||||
|
for my $chain (@chains) {
|
||||||
|
next if $chain->{policy};
|
||||||
|
my $success = iptables(
|
||||||
|
cmd => "-t $table -X $chain->{name}",
|
||||||
|
ip => $opts{ip}
|
||||||
|
);
|
||||||
|
$error++ if !$success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub loadconf {
|
||||||
|
open(CF, '<', $self->{config_fn})
|
||||||
|
or die "Could not open $self->{config_fn}: $!\n";
|
||||||
|
my @cf;
|
||||||
|
while (my $line = <CF>) {
|
||||||
|
chomp $line;
|
||||||
|
next if $line !~ /\S+/;
|
||||||
|
next if $line =~ /^\s*#/;
|
||||||
|
if ($line =~ /^\s+(.*)/) {
|
||||||
|
# lines beginning with \s continue last line
|
||||||
|
push @cf, '' if !scalar @cf;
|
||||||
|
$cf[-1] .= $1;
|
||||||
|
} else {
|
||||||
|
push @cf, $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close CF;
|
||||||
|
$self->{config} = \@cf;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub find_ruleset {
|
||||||
|
my ($ruleset) = @_;
|
||||||
|
my $in_ruleset = 0;
|
||||||
|
my @rules;
|
||||||
|
for (my $i = 0; $i < scalar @{$self->{config}}; $i++) {
|
||||||
|
my $line = $self->{config}->[$i];
|
||||||
|
if (!$in_ruleset) {
|
||||||
|
if ($line =~ /^R>\s*$ruleset\s*$/) {
|
||||||
|
$in_ruleset = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($line =~ /^R>/) {
|
||||||
|
$in_ruleset = 0;
|
||||||
|
$i--; # rerun line, perhaps it's us again
|
||||||
|
} else {
|
||||||
|
push @rules, $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return @rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub activate_rules {
|
||||||
|
my %opts = @_;
|
||||||
|
|
||||||
|
my ($good, $bad) = (0, 0);
|
||||||
|
for my $r (@{$opts{rules}}) {
|
||||||
|
if ($r =~ s/^PRINT>(.*)//) {
|
||||||
|
print "$1\n";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
my $ip = '46';
|
||||||
|
if ($r =~ s/^([46])>\s*//) {
|
||||||
|
$ip = $1;
|
||||||
|
}
|
||||||
|
$ip =~ s/6// if $opts{ip} eq '4';
|
||||||
|
$ip =~ s/4// if $opts{ip} eq '6';
|
||||||
|
next if $ip eq '';
|
||||||
|
my $success = iptables(
|
||||||
|
cmd => $r,
|
||||||
|
ip => $ip
|
||||||
|
);
|
||||||
|
if ($success) {
|
||||||
|
$good++;
|
||||||
|
} else {
|
||||||
|
$bad++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $good, $bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
my ($ipv4, $ipv6) = (0, 0);
|
||||||
|
GetOptions(
|
||||||
|
"verbose|v" => \$self->{verbose},
|
||||||
|
"dry-run" => \$self->{dryrun},
|
||||||
|
"ipv4|4" => \$ipv4,
|
||||||
|
"ipv6|6" => \$ipv6,
|
||||||
|
) or usage;
|
||||||
|
if (!$ipv4 and !$ipv6) {
|
||||||
|
($ipv4, $ipv6) = (1, 1);
|
||||||
|
}
|
||||||
|
if ($self->{dryrun}) {
|
||||||
|
print "pf6: DRY RUN!\n";
|
||||||
|
$self->{verbose} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadconf;
|
||||||
|
|
||||||
|
my $action = $ARGV[0] or usage;
|
||||||
|
# these are the same for us:
|
||||||
|
$action = 'start' if $action eq 'restart' or $action eq 'force-reload';
|
||||||
|
if ($action eq 'stop') {
|
||||||
|
cleanup(ip => '4') if $ipv4;
|
||||||
|
cleanup(ip => '6') if $ipv6;
|
||||||
|
exit 0;
|
||||||
|
} if ($action eq 'status') {
|
||||||
|
print "pf6 status is meaningless.\n";
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
my @rules = find_ruleset($action);
|
||||||
|
if (!scalar @rules) {
|
||||||
|
print STDERR "Ruleset '$action' not defined.\n";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
cleanup(ip => '4') if $ipv4;
|
||||||
|
cleanup(ip => '6') if $ipv6;
|
||||||
|
print "pf6: loading ruleset '$action'..\n";
|
||||||
|
my ($good, $bad) = activate_rules(
|
||||||
|
rules => \@rules,
|
||||||
|
ip => ($ipv4 ? '4' : '') . ($ipv6 ? '6' : '')
|
||||||
|
);
|
||||||
|
if ($bad) {
|
||||||
|
print "pf6: $good rules ok, $bad rules FAILED.\n";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
print "pf6: $good rules ok.\n";
|
||||||
|
exit 0;
|
||||||
|
__END__
|
||||||
|
# vim: set tabstop=4 shiftwidth=4 expandtab smarttab:
|
||||||
62
pf6.conf
Normal file
62
pf6.conf
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# pf6.conf syntax:
|
||||||
|
# - empty lines allowed; only full line comments beginning with '#'
|
||||||
|
# - lines beginning with whitespace continue last line
|
||||||
|
# - ruleset begin: 'R>ruleset'
|
||||||
|
# - rules only for IPv4 begin with '4>', IPv6 with '6>'
|
||||||
|
# - if no 4/6 given, rule is executed for both
|
||||||
|
# - lines beginning with 'PRINT>' are only printed
|
||||||
|
|
||||||
|
# ---%<--- delete this block
|
||||||
|
R> start
|
||||||
|
-P INPUT ACCEPT
|
||||||
|
-P OUTPUT ACCEPT
|
||||||
|
-P FORWARD ACCEPT
|
||||||
|
# --->%--- until here and change the ruleset name 'start2' -> 'start', and
|
||||||
|
# customize the rules for your needs...
|
||||||
|
R> start2
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
-N established
|
||||||
|
-A established -m state --state ESTABLISHED -j ACCEPT
|
||||||
|
-A established -m state --state RELATED -j ACCEPT
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
-N inbase
|
||||||
|
-A inbase -i lo -j ACCEPT
|
||||||
|
4> -A inbase -p icmp -j ACCEPT
|
||||||
|
6> -A inbase -p icmpv6 -j ACCEPT
|
||||||
|
-A inbase -p tcp --dport ssh -j ACCEPT
|
||||||
|
-A inbase -p tcp --dport domain -j ACCEPT
|
||||||
|
-A inbase -p udp --dport domain -j ACCEPT
|
||||||
|
-A inbase -p udp --sport ntp -j ACCEPT
|
||||||
|
-A inbase -p udp --dport ntp -j ACCEPT
|
||||||
|
-A inbase -p tcp --dport auth -j REJECT
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
-N input
|
||||||
|
#-A input -p tcp --dport http -j ACCEPT
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
-A INPUT -i lo -j ACCEPT
|
||||||
|
-A INPUT -j established
|
||||||
|
-A INPUT -j inbase
|
||||||
|
-A INPUT -j input
|
||||||
|
|
||||||
|
-P INPUT DROP
|
||||||
|
-P OUTPUT ACCEPT
|
||||||
|
-P FORWARD DROP
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##############################################################################
|
||||||
|
R> ssh
|
||||||
|
-P INPUT DROP
|
||||||
|
-P OUTPUT DROP
|
||||||
|
-P FORWARD DROP
|
||||||
|
-A INPUT -i lo -j ACCEPT
|
||||||
|
-A OUTPUT -o lo -j ACCEPT
|
||||||
|
-A INPUT -p tcp --dport 22 -j ACCEPT
|
||||||
|
-A OUTPUT -p tcp --sport 22 -j ACCEPT
|
||||||
|
PRINT>
|
||||||
|
PRINT> SSH only ruleset (stateless) loaded
|
||||||
|
PRINT>
|
||||||
|
# end.
|
||||||
Loading…
x
Reference in New Issue
Block a user