mirror of
git://git.proxmox.com/git/pve-firewall.git
synced 2025-01-07 21:17:59 +03:00
cleanup firewall service implementation
We now run a separate server called 'pve-firewall' (renamed 'pvefw'). So service and management tool use the same name: # service pve-firewall start is the same as # pve-firewall start Also removed the read_pvefw_status/save_pvefw_status code.
This commit is contained in:
parent
2708398494
commit
e2beb7aa99
2
debian/pve-firewall.default
vendored
Normal file
2
debian/pve-firewall.default
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Should pve-firewall run automatically on startup? (default: yes)
|
||||
START_FIREWALL=yes
|
75
debian/pve-firewall.init
vendored
75
debian/pve-firewall.init
vendored
@ -6,43 +6,66 @@
|
||||
# Required-Stop: $remote_fs $network pvefw-logger pve-cluster
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: PVE firewall
|
||||
# Short-Description: Proxmox VE firewall
|
||||
### END INIT INFO
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
PATH=/sbin:/bin:/usr/bin:/usr/sbin
|
||||
PVEFW=/usr/sbin/pvefw
|
||||
NAME=pvefw
|
||||
DESC="PVE firewall"
|
||||
PIDFILE=/var/run/pvefw-logger.pid
|
||||
NAME=pve-firewall
|
||||
DAEMON=/usr/sbin/$NAME
|
||||
DESC="Proxmox VE firewall"
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
|
||||
test -f $PVEFW || exit 0
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
START_FIREWALL=yes
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
[ "$START_FIREWALL" = "yes" ] || exit 0
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
|
||||
# and status_of_proc is working.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
# avoid warnings about uninstalled locales
|
||||
export LC_ALL="C"
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
log_daemon_msg "Starting $DESC" "$NAME"
|
||||
$PVEFW start
|
||||
log_end_msg $?
|
||||
;;
|
||||
stop)
|
||||
log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
$PVEFW stop
|
||||
log_end_msg $?
|
||||
;;
|
||||
reload|restart|force-reload)
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
$PVEFW update
|
||||
log_end_msg $?
|
||||
;;
|
||||
*)
|
||||
N=/etc/init.d/$NAME
|
||||
echo "Usage: $N {start|stop|restart|force-reload}"
|
||||
exit 1
|
||||
;;
|
||||
start)
|
||||
log_daemon_msg "Starting $DESC" "$NAME"
|
||||
$DAEMON start
|
||||
log_end_msg $?
|
||||
;;
|
||||
stop)
|
||||
log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
$DAEMON stop
|
||||
log_end_msg $?
|
||||
;;
|
||||
status)
|
||||
$DAEMON status
|
||||
;;
|
||||
reload|restart|force-reload)
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
if ( [ -e $PIDFILE ] && kill -0 `cat $PIDFILE`) then
|
||||
start-stop-daemon --stop --quiet --pidfile $PIDFILE --signal HUP
|
||||
else
|
||||
$DAEMON start
|
||||
fi
|
||||
log_end_msg $?
|
||||
;;
|
||||
*)
|
||||
N=/etc/init.d/$NAME
|
||||
echo "Usage: $N {start|stop|status|restart|force-reload}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
2
debian/rules
vendored
2
debian/rules
vendored
@ -8,4 +8,4 @@
|
||||
|
||||
override_dh_installinit:
|
||||
dh_installinit -R -p pve-firewall
|
||||
dh_installinit --name pvefw-logger
|
||||
dh_installinit -R --name pvefw-logger
|
||||
|
1
debian/triggers
vendored
Normal file
1
debian/triggers
vendored
Normal file
@ -0,0 +1 @@
|
||||
interest /usr/share/perl5
|
@ -19,10 +19,10 @@ pvefw-logger: pvefw-logger.c
|
||||
$(shell pkg-config libnetfilter_log glib-2.0 gthread-2.0 --libs --cflags)
|
||||
|
||||
.PHONY: install
|
||||
install: pvefw pvefw-logger
|
||||
install: pve-firewall pvefw-logger
|
||||
make -C PVE install
|
||||
install -d -m 0755 ${DESTDIR}/${SBINDIR}
|
||||
install -m 0755 pvefw ${DESTDIR}/${SBINDIR}
|
||||
install -m 0755 pve-firewall ${DESTDIR}/${SBINDIR}
|
||||
install -m 0755 --strip pvefw-logger ${DESTDIR}/${SBINDIR}
|
||||
|
||||
.PHONY: clean
|
||||
|
@ -38,6 +38,7 @@ __PACKAGE__->register_method({
|
||||
description => "List security groups.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {},
|
||||
},
|
||||
returns => {
|
||||
type => 'array',
|
||||
|
@ -98,7 +98,6 @@ use Data::Dumper;
|
||||
my $nodename = PVE::INotify::nodename();
|
||||
|
||||
my $pve_fw_lock_filename = "/var/lock/pvefw.lck";
|
||||
my $pve_fw_status_filename = "/var/lib/pve-firewall/pvefw.status";
|
||||
|
||||
my $default_log_level = 'info';
|
||||
|
||||
@ -2451,30 +2450,6 @@ sub round_powerof2 {
|
||||
return ++$int;
|
||||
}
|
||||
|
||||
sub save_pvefw_status {
|
||||
my ($status) = @_;
|
||||
|
||||
die "unknown status '$status' - internal error"
|
||||
if $status !~ m/^(stopped|active)$/;
|
||||
|
||||
mkdir dirname($pve_fw_status_filename);
|
||||
PVE::Tools::file_set_contents($pve_fw_status_filename, $status);
|
||||
}
|
||||
|
||||
sub read_pvefw_status {
|
||||
|
||||
my $status = 'unknown';
|
||||
|
||||
return 'stopped' if ! -f $pve_fw_status_filename;
|
||||
|
||||
eval {
|
||||
$status = PVE::Tools::file_get_contents($pve_fw_status_filename);
|
||||
};
|
||||
warn $@ if $@;
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub load_clusterfw_conf {
|
||||
my ($filename) = @_;
|
||||
|
||||
@ -2969,7 +2944,7 @@ sub remove_pvefw_chains {
|
||||
}
|
||||
|
||||
sub update {
|
||||
my ($start, $verbose) = @_;
|
||||
my ($verbose) = @_;
|
||||
|
||||
my $code = sub {
|
||||
|
||||
@ -2978,9 +2953,7 @@ sub update {
|
||||
|
||||
my $enable = $cluster_options->{enable};
|
||||
|
||||
my $status = read_pvefw_status();
|
||||
|
||||
die "Firewall is disabled - cannot start\n" if !$enable && $start;
|
||||
die "Firewall is disabled - cannot start\n" if !$enable;
|
||||
|
||||
if (!$enable) {
|
||||
PVE::Firewall::remove_pvefw_chains();
|
||||
@ -2992,14 +2965,7 @@ sub update {
|
||||
|
||||
my ($ruleset, $ipset_ruleset) = compile($cluster_conf, $hostfw_conf);
|
||||
|
||||
if ($start || $status eq 'active') {
|
||||
|
||||
save_pvefw_status('active') if ($status ne 'active');
|
||||
|
||||
apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $verbose);
|
||||
} else {
|
||||
print "Firewall not active (status = $status)\n" if $verbose;
|
||||
}
|
||||
apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $verbose);
|
||||
};
|
||||
|
||||
run_locked($code);
|
||||
|
412
src/pve-firewall
Executable file
412
src/pve-firewall
Executable file
@ -0,0 +1,412 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use PVE::SafeSyslog;
|
||||
use POSIX ":sys_wait_h";
|
||||
use Fcntl ':flock';
|
||||
use Getopt::Long;
|
||||
use Time::HiRes qw (gettimeofday);
|
||||
use PVE::Tools qw(dir_glob_foreach file_read_firstline);
|
||||
use PVE::INotify;
|
||||
use PVE::Cluster qw(cfs_read_file);
|
||||
use PVE::RPCEnvironment;
|
||||
use PVE::CLIHandler;
|
||||
use PVE::Firewall;
|
||||
|
||||
use base qw(PVE::CLIHandler);
|
||||
|
||||
my $pve_firewall_pidfile = "/var/run/pve-firewall.pid";
|
||||
|
||||
$SIG{'__WARN__'} = sub {
|
||||
my $err = $@;
|
||||
my $t = $_[0];
|
||||
chomp $t;
|
||||
print "$t\n";
|
||||
syslog('warning', "WARNING: %s", $t);
|
||||
$@ = $err;
|
||||
};
|
||||
|
||||
initlog('pve-firewall');
|
||||
|
||||
$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
|
||||
|
||||
die "please run as root\n" if $> != 0;
|
||||
|
||||
PVE::INotify::inotify_init();
|
||||
|
||||
my $rpcenv = PVE::RPCEnvironment->init('cli');
|
||||
|
||||
$rpcenv->init_request();
|
||||
$rpcenv->set_language($ENV{LANG});
|
||||
$rpcenv->set_user('root@pam');
|
||||
|
||||
my $commandline = [$0, @ARGV];
|
||||
|
||||
$0 = "pve-firewall";
|
||||
|
||||
sub restart_server {
|
||||
my ($waittime) = @_;
|
||||
|
||||
syslog('info', "server shutdown (restart)");
|
||||
|
||||
$ENV{RESTART_PVE_FIREWALL} = 1;
|
||||
|
||||
sleep($waittime) if $waittime; # avoid high server load due to restarts
|
||||
|
||||
exec (@$commandline);
|
||||
exit (-1); # never reached?
|
||||
}
|
||||
|
||||
sub cleanup {
|
||||
unlink "$pve_firewall_pidfile.lock";
|
||||
unlink $pve_firewall_pidfile;
|
||||
}
|
||||
|
||||
sub lockpidfile {
|
||||
my $pidfile = shift;
|
||||
my $lkfn = "$pidfile.lock";
|
||||
|
||||
if (!open (FLCK, ">>$lkfn")) {
|
||||
my $msg = "can't aquire lock on file '$lkfn' - $!";
|
||||
syslog ('err', $msg);
|
||||
die "ERROR: $msg\n";
|
||||
}
|
||||
|
||||
if (!flock (FLCK, LOCK_EX|LOCK_NB)) {
|
||||
close (FLCK);
|
||||
my $msg = "can't aquire lock '$lkfn' - $!";
|
||||
syslog ('err', $msg);
|
||||
die "ERROR: $msg\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub writepidfile {
|
||||
my $pidfile = shift;
|
||||
|
||||
if (!open (PIDFH, ">$pidfile")) {
|
||||
my $msg = "can't open pid file '$pidfile' - $!";
|
||||
syslog ('err', $msg);
|
||||
die "ERROR: $msg\n";
|
||||
}
|
||||
print PIDFH "$$\n";
|
||||
close (PIDFH);
|
||||
}
|
||||
|
||||
my $restart_request = 0;
|
||||
my $next_update = 0;
|
||||
|
||||
my $cycle = 0;
|
||||
my $updatetime = 10;
|
||||
|
||||
my $initial_memory_usage;
|
||||
|
||||
sub run_server {
|
||||
my ($param) = @_;
|
||||
|
||||
# try to get the lock
|
||||
lockpidfile($pve_firewall_pidfile);
|
||||
|
||||
# run in background
|
||||
my $spid;
|
||||
|
||||
my $restart = $ENV{RESTART_PVE_FIREWALL};
|
||||
|
||||
delete $ENV{RESTART_PVE_FIREWALL};
|
||||
|
||||
if (!$param->{debug}) {
|
||||
open STDIN, '</dev/null' || die "can't read /dev/null";
|
||||
open STDOUT, '>/dev/null' || die "can't write /dev/null";
|
||||
}
|
||||
|
||||
if (!$restart && !$param->{debug}) {
|
||||
$spid = fork();
|
||||
if (!defined ($spid)) {
|
||||
my $msg = "can't put server into background - fork failed";
|
||||
syslog('err', $msg);
|
||||
die "ERROR: $msg\n";
|
||||
} elsif ($spid) { # parent
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
writepidfile($pve_firewall_pidfile);
|
||||
|
||||
open STDERR, '>&STDOUT' || die "can't close STDERR\n";
|
||||
|
||||
$SIG{INT} = $SIG{TERM} = $SIG{QUIT} = sub {
|
||||
syslog('info' , "server closing");
|
||||
|
||||
$SIG{INT} = 'DEFAULT';
|
||||
|
||||
# wait for children
|
||||
1 while (waitpid(-1, POSIX::WNOHANG()) > 0);
|
||||
|
||||
syslog('info' , "clear firewall rules");
|
||||
eval { PVE::Firewall::remove_pvefw_chains(); die "STOP";};
|
||||
warn $@ if $@;
|
||||
|
||||
cleanup();
|
||||
|
||||
exit (0);
|
||||
};
|
||||
|
||||
$SIG{HUP} = sub {
|
||||
# wake up process, so this forces an immediate firewall rules update
|
||||
syslog('info' , "received signal HUP (restart)");
|
||||
$restart_request = 1;
|
||||
};
|
||||
|
||||
if ($restart) {
|
||||
syslog('info' , "restarting server");
|
||||
} else {
|
||||
syslog('info' , "starting server");
|
||||
}
|
||||
|
||||
for (;;) { # forever
|
||||
|
||||
eval {
|
||||
|
||||
local $SIG{'__WARN__'} = 'IGNORE'; # do not fill up logs
|
||||
|
||||
$next_update = time() + $updatetime;
|
||||
|
||||
my ($ccsec, $cusec) = gettimeofday ();
|
||||
eval {
|
||||
PVE::Cluster::cfs_update();
|
||||
PVE::Firewall::update();
|
||||
};
|
||||
my $err = $@;
|
||||
|
||||
if ($err) {
|
||||
syslog('err', "status update error: $err");
|
||||
}
|
||||
|
||||
my ($ccsec_end, $cusec_end) = gettimeofday ();
|
||||
my $cptime = ($ccsec_end-$ccsec) + ($cusec_end - $cusec)/1000000;
|
||||
|
||||
syslog('info', sprintf("firewall update time (%.3f seconds)", $cptime))
|
||||
if ($cptime > 5);
|
||||
|
||||
$cycle++;
|
||||
|
||||
my $mem = PVE::ProcFSTools::read_memory_usage();
|
||||
|
||||
if (!defined($initial_memory_usage) || ($cycle < 10)) {
|
||||
$initial_memory_usage = $mem->{resident};
|
||||
} else {
|
||||
my $diff = $mem->{resident} - $initial_memory_usage;
|
||||
if ($diff > 5*1024*1024) {
|
||||
syslog ('info', "restarting server after $cycle cycles to " .
|
||||
"reduce memory usage (free $mem->{resident} ($diff) bytes)");
|
||||
restart_server();
|
||||
}
|
||||
}
|
||||
|
||||
my $wcount = 0;
|
||||
while ((time() < $next_update) &&
|
||||
($wcount < $updatetime) && # protect against time wrap
|
||||
!$restart_request) { $wcount++; sleep (1); };
|
||||
|
||||
restart_server() if $restart_request;
|
||||
};
|
||||
|
||||
my $err = $@;
|
||||
|
||||
if ($err) {
|
||||
syslog ('err', "ERROR: $err");
|
||||
restart_server(5);
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'start',
|
||||
path => 'start',
|
||||
method => 'POST',
|
||||
description => "Start the Proxmox VE firewall service.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
debug => {
|
||||
description => "Debug mode - stay in foreground",
|
||||
type => "boolean",
|
||||
optional => 1,
|
||||
default => 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
returns => { type => 'null' },
|
||||
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
run_server($param);
|
||||
|
||||
return undef;
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'stop',
|
||||
path => 'stop',
|
||||
method => 'POST',
|
||||
description => "Stop firewall. This will remove all rules installed by this script. The host is unprotected afterwards.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {},
|
||||
},
|
||||
returns => { type => 'null' },
|
||||
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
my $pid = int(PVE::Tools::file_read_firstline($pve_firewall_pidfile) || 0);
|
||||
|
||||
if ($pid) {
|
||||
if (PVE::ProcFSTools::check_process_running($pid)) {
|
||||
kill(15, $pid); # send TERM signal
|
||||
# give max 5 seconds to shut down
|
||||
for (my $i = 0; $i < 5; $i++) {
|
||||
last if !PVE::ProcFSTools::check_process_running($pid);
|
||||
sleep (1);
|
||||
}
|
||||
|
||||
# to be sure
|
||||
kill(9, $pid);
|
||||
waitpid($pid, 0);
|
||||
}
|
||||
if (-f $pve_firewall_pidfile) {
|
||||
# try to get the lock
|
||||
lockpidfile($pve_firewall_pidfile);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
return undef;
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'status',
|
||||
path => 'status',
|
||||
method => 'GET',
|
||||
description => "Get firewall status.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {},
|
||||
},
|
||||
returns => {
|
||||
type => 'object',
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
status => {
|
||||
type => 'string',
|
||||
enum => ['unknown', 'stopped', 'active'],
|
||||
},
|
||||
changes => {
|
||||
description => "Set when there are pending changes.",
|
||||
type => 'boolean',
|
||||
optional => 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog
|
||||
|
||||
my $code = sub {
|
||||
|
||||
my $pid = int(PVE::Tools::file_read_firstline($pve_firewall_pidfile) || 0);
|
||||
my $running = PVE::ProcFSTools::check_process_running($pid);
|
||||
|
||||
my $status = $running ? 'active' : 'stopped';
|
||||
|
||||
my $res = { status => $status };
|
||||
if ($status eq 'active') {
|
||||
my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile();
|
||||
|
||||
my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset);
|
||||
my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset);
|
||||
|
||||
$res->{changes} = ($ipset_changes || $ruleset_changes) ? 1 : 0;
|
||||
}
|
||||
|
||||
return $res;
|
||||
};
|
||||
|
||||
return PVE::Firewall::run_locked($code);
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'compile',
|
||||
path => 'compile',
|
||||
method => 'POST',
|
||||
description => "Compile amd print firewall rules. This is only for testing.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {},
|
||||
},
|
||||
returns => { type => 'null' },
|
||||
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog
|
||||
|
||||
my $code = sub {
|
||||
my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile();
|
||||
|
||||
my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, 1);
|
||||
my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset, 1);
|
||||
if ($ipset_changes || $ruleset_changes) {
|
||||
print "detected changes\n";
|
||||
} else {
|
||||
print "no changes\n";
|
||||
}
|
||||
};
|
||||
|
||||
PVE::Firewall::run_locked($code);
|
||||
|
||||
return undef;
|
||||
}});
|
||||
|
||||
my $nodename = PVE::INotify::nodename();
|
||||
|
||||
my $cmddef = {
|
||||
start => [ __PACKAGE__, 'start', []],
|
||||
stop => [ __PACKAGE__, 'stop', []],
|
||||
compile => [ __PACKAGE__, 'compile', []],
|
||||
status => [ __PACKAGE__, 'status', [], undef, sub {
|
||||
my $res = shift;
|
||||
if ($res->{changes}) {
|
||||
print "Status: $res->{status} (pending changes)\n";
|
||||
} else {
|
||||
print "Status: $res->{status}\n";
|
||||
}
|
||||
}],
|
||||
};
|
||||
|
||||
my $cmd = shift;
|
||||
|
||||
PVE::CLIHandler::handle_cmd($cmddef, $0, $cmd, \@ARGV, undef, $0);
|
||||
|
||||
exit (0);
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
pvestatd - PVE Firewall Daemon
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
pve-firewall
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This service updates iptables rules periodically.
|
||||
|
||||
|
||||
|
||||
|
242
src/pvefw
242
src/pvefw
@ -1,242 +0,0 @@
|
||||
#!/usr/bin/perl -T
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use lib qw(.);
|
||||
use PVE::Firewall;
|
||||
|
||||
use PVE::SafeSyslog;
|
||||
use PVE::Cluster;
|
||||
use PVE::INotify;
|
||||
use PVE::RPCEnvironment;
|
||||
|
||||
use PVE::JSONSchema qw(get_standard_option);
|
||||
|
||||
use PVE::CLIHandler;
|
||||
use PVE::API2::Firewall::Groups;
|
||||
|
||||
use base qw(PVE::CLIHandler);
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
|
||||
|
||||
initlog ('pvefw');
|
||||
|
||||
die "please run as root\n" if $> != 0;
|
||||
|
||||
PVE::INotify::inotify_init();
|
||||
|
||||
my $rpcenv = PVE::RPCEnvironment->init('cli');
|
||||
|
||||
$rpcenv->init_request();
|
||||
$rpcenv->set_language($ENV{LANG});
|
||||
$rpcenv->set_user('root@pam');
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'compile',
|
||||
path => 'compile',
|
||||
method => 'POST',
|
||||
description => "Compile amd print firewall rules. This is only for testing.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
verbose => {
|
||||
description => "Verbose output.",
|
||||
type => "boolean",
|
||||
optional => 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
returns => { type => 'null' },
|
||||
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
my $rpcenv = PVE::RPCEnvironment::get();
|
||||
|
||||
$param->{verbose} = 1
|
||||
if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
|
||||
|
||||
my $code = sub {
|
||||
my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile();
|
||||
|
||||
if ($param->{verbose}) {
|
||||
my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset, 1);
|
||||
my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset, 1);
|
||||
if ($ipset_changes || $ruleset_changes) {
|
||||
print "detected changes\n";
|
||||
} else {
|
||||
print "no changes\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PVE::Firewall::run_locked($code);
|
||||
|
||||
return undef;
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'status',
|
||||
path => 'status',
|
||||
method => 'GET',
|
||||
description => "Get firewall status.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {},
|
||||
},
|
||||
returns => {
|
||||
type => 'object',
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
status => {
|
||||
type => 'string',
|
||||
enum => ['unknown', 'stopped', 'active'],
|
||||
},
|
||||
changes => {
|
||||
description => "Set when there are pending changes.",
|
||||
type => 'boolean',
|
||||
optional => 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
my $rpcenv = PVE::RPCEnvironment::get();
|
||||
|
||||
$param->{verbose} = 1
|
||||
if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
|
||||
|
||||
my $code = sub {
|
||||
my $status = PVE::Firewall::read_pvefw_status();
|
||||
|
||||
my $res = { status => $status };
|
||||
if ($status eq 'active') {
|
||||
my ($ruleset, $ipset_ruleset) = PVE::Firewall::compile();
|
||||
|
||||
my (undef, undef, $ipset_changes) = PVE::Firewall::get_ipset_cmdlist($ipset_ruleset);
|
||||
my (undef, $ruleset_changes) = PVE::Firewall::get_ruleset_cmdlist($ruleset);
|
||||
# fixme: ipset changes
|
||||
$res->{changes} = ($ipset_changes || $ruleset_changes) ? 1 : 0;
|
||||
}
|
||||
|
||||
return $res;
|
||||
};
|
||||
|
||||
return PVE::Firewall::run_locked($code);
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'start',
|
||||
path => 'start',
|
||||
method => 'POST',
|
||||
description => "Start (or simply update if already active) firewall.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
verbose => {
|
||||
description => "Verbose output.",
|
||||
type => "boolean",
|
||||
optional => 1,
|
||||
default => 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
returns => { type => 'null' },
|
||||
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
PVE::Firewall::update(1, $param->{verbose});
|
||||
|
||||
return undef;
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'update',
|
||||
path => 'update',
|
||||
method => 'POST',
|
||||
description => "Check firewall rules. Then update the rules if the firewall is active.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {
|
||||
verbose => {
|
||||
description => "Verbose output.",
|
||||
type => "boolean",
|
||||
optional => 1,
|
||||
default => 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
returns => { type => 'null' },
|
||||
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
PVE::Firewall::update(0, $param->{verbose});
|
||||
|
||||
return undef;
|
||||
}});
|
||||
|
||||
__PACKAGE__->register_method ({
|
||||
name => 'stop',
|
||||
path => 'stop',
|
||||
method => 'POST',
|
||||
description => "Stop firewall. This will remove all rules installed by this script. The host is then unprotected.",
|
||||
parameters => {
|
||||
additionalProperties => 0,
|
||||
properties => {},
|
||||
},
|
||||
returns => { type => 'null' },
|
||||
|
||||
code => sub {
|
||||
my ($param) = @_;
|
||||
|
||||
my $code = sub {
|
||||
PVE::Firewall::remove_pvefw_chains();
|
||||
PVE::Firewall::save_pvefw_status('stopped');
|
||||
};
|
||||
|
||||
PVE::Firewall::run_locked($code);
|
||||
|
||||
return undef;
|
||||
}});
|
||||
|
||||
my $nodename = PVE::INotify::nodename();
|
||||
|
||||
my $cmddef = {
|
||||
compile => [ __PACKAGE__, 'compile', []],
|
||||
start => [ __PACKAGE__, 'start', []],
|
||||
update => [ __PACKAGE__, 'update', []],
|
||||
status => [ __PACKAGE__, 'status', [], undef, sub {
|
||||
my $res = shift;
|
||||
if ($res->{changes}) {
|
||||
print "Status: $res->{status} (pending changes)\n";
|
||||
} else {
|
||||
print "Status: $res->{status}\n";
|
||||
}
|
||||
}],
|
||||
stop => [ __PACKAGE__, 'stop', []],
|
||||
|
||||
# This is for debugging
|
||||
listgroups => [ 'PVE::API2::Firewall::Groups', 'list', [],
|
||||
{ node => $nodename }, sub {
|
||||
my $res = shift;
|
||||
print Dumper($res);
|
||||
}],
|
||||
grouprules => [ 'PVE::API2::Firewall::Groups', 'get_rules', ['group'],
|
||||
{ node => $nodename }, sub {
|
||||
my $res = shift;
|
||||
print Dumper($res);
|
||||
}],
|
||||
};
|
||||
|
||||
my $cmd = shift;
|
||||
|
||||
PVE::CLIHandler::handle_cmd($cmddef, "pvefw", $cmd, \@ARGV, undef, $0);
|
||||
|
||||
exit(0);
|
||||
|
@ -807,9 +807,8 @@ main(int argc, char *argv[])
|
||||
g_io_add_watch(nflog_ch, G_IO_IN, nflog_read_cb, NULL);
|
||||
|
||||
GIOChannel *sig_ch = g_io_channel_unix_new(sigfd);
|
||||
printf("TEST0: %p %d\n", sig_ch, sigfd);
|
||||
if (!g_io_add_watch(sig_ch, G_IO_IN, signal_read_cb, NULL)) {
|
||||
printf("TEST1\n"); exit(-1);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
GThread *wthread = g_thread_new("log_writer_thread", log_writer_thread, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user