]>
git.proxmox.com Git - pve-firewall.git/blob - src/pve-firewall
6 use POSIX
":sys_wait_h";
9 use Time
::HiRes qw
(gettimeofday
);
10 use PVE
::Tools
qw(dir_glob_foreach file_read_firstline);
12 use PVE
::Cluster
qw(cfs_read_file);
13 use PVE
::RPCEnvironment
;
17 use base
qw(PVE::CLIHandler);
19 my $pve_firewall_pidfile = "/var/run/pve-firewall.pid";
21 $SIG{'__WARN__'} = sub {
26 syslog
('warning', "WARNING: %s", $t);
30 initlog
('pve-firewall');
32 $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
34 die "please run as root\n" if $> != 0;
36 PVE
::INotify
::inotify_init
();
38 my $rpcenv = PVE
::RPCEnvironment-
>init('cli');
40 $rpcenv->init_request();
41 $rpcenv->set_language($ENV{LANG
});
42 $rpcenv->set_user('root@pam');
44 my $commandline = [$0, @ARGV];
51 syslog
('info', "server shutdown (restart)");
53 $ENV{RESTART_PVE_FIREWALL
} = 1;
55 sleep($waittime) if $waittime; # avoid high server load due to restarts
58 exit (-1); # never reached?
62 unlink "$pve_firewall_pidfile.lock";
63 unlink $pve_firewall_pidfile;
68 my $lkfn = "$pidfile.lock";
70 if (!open (FLCK
, ">>$lkfn")) {
71 my $msg = "can't aquire lock on file '$lkfn' - $!";
76 if (!flock (FLCK
, LOCK_EX
|LOCK_NB
)) {
78 my $msg = "can't aquire lock '$lkfn' - $!";
87 if (!open (PIDFH
, ">$pidfile")) {
88 my $msg = "can't open pid file '$pidfile' - $!";
96 my $restart_request = 0;
102 my $initial_memory_usage;
107 # try to get the lock
108 lockpidfile
($pve_firewall_pidfile);
113 my $restart = $ENV{RESTART_PVE_FIREWALL
};
115 delete $ENV{RESTART_PVE_FIREWALL
};
117 PVE
::Cluster
::cfs_update
();
119 PVE
::Firewall
::init
();
121 if (!$param->{debug
}) {
122 open STDIN
, '</dev/null' || die "can't read /dev/null";
123 open STDOUT
, '>/dev/null' || die "can't write /dev/null";
126 if (!$restart && !$param->{debug
}) {
128 if (!defined ($spid)) {
129 my $msg = "can't put server into background - fork failed";
132 } elsif ($spid) { # parent
137 writepidfile
($pve_firewall_pidfile);
139 open STDERR
, '>&STDOUT' || die "can't close STDERR\n";
141 $SIG{INT
} = $SIG{TERM
} = $SIG{QUIT
} = sub {
142 syslog
('info' , "server closing");
144 $SIG{INT
} = 'DEFAULT';
147 1 while (waitpid(-1, POSIX
::WNOHANG
()) > 0);
149 syslog
('info' , "clear firewall rules");
150 eval { PVE
::Firewall
::remove_pvefw_chains
(); die "STOP";};
159 # wake up process, so this forces an immediate firewall rules update
160 syslog
('info' , "received signal HUP (restart)");
161 $restart_request = 1;
165 syslog
('info' , "restarting server");
167 syslog
('info' , "starting server");
174 local $SIG{'__WARN__'} = 'IGNORE'; # do not fill up logs
176 $next_update = time() + $updatetime;
178 my ($ccsec, $cusec) = gettimeofday
();
180 PVE
::Cluster
::cfs_update
();
181 PVE
::Firewall
::update
();
186 syslog
('err', "status update error: $err");
189 my ($ccsec_end, $cusec_end) = gettimeofday
();
190 my $cptime = ($ccsec_end-$ccsec) + ($cusec_end - $cusec)/1000000;
192 syslog
('info', sprintf("firewall update time (%.3f seconds)", $cptime))
197 my $mem = PVE
::ProcFSTools
::read_memory_usage
();
199 if (!defined($initial_memory_usage) || ($cycle < 10)) {
200 $initial_memory_usage = $mem->{resident
};
202 my $diff = $mem->{resident
} - $initial_memory_usage;
203 if ($diff > 5*1024*1024) {
204 syslog
('info', "restarting server after $cycle cycles to " .
205 "reduce memory usage (free $mem->{resident} ($diff) bytes)");
211 while ((time() < $next_update) &&
212 ($wcount < $updatetime) && # protect against time wrap
213 !$restart_request) { $wcount++; sleep (1); };
215 restart_server
() if $restart_request;
221 syslog
('err', "ERROR: $err");
228 __PACKAGE__-
>register_method ({
232 description
=> "Start the Proxmox VE firewall service.",
234 additionalProperties
=> 0,
237 description
=> "Debug mode - stay in foreground",
244 returns
=> { type
=> 'null' },
254 __PACKAGE__-
>register_method ({
258 description
=> "Stop firewall. This removes all Proxmox VE related iptable rules. The host is unprotected afterwards.",
260 additionalProperties
=> 0,
263 returns
=> { type
=> 'null' },
268 my $pid = int(PVE
::Tools
::file_read_firstline
($pve_firewall_pidfile) || 0);
271 if (PVE
::ProcFSTools
::check_process_running
($pid)) {
272 kill(15, $pid); # send TERM signal
273 # give max 5 seconds to shut down
274 for (my $i = 0; $i < 5; $i++) {
275 last if !PVE
::ProcFSTools
::check_process_running
($pid);
283 if (-f
$pve_firewall_pidfile) {
284 # try to get the lock
285 lockpidfile
($pve_firewall_pidfile);
293 __PACKAGE__-
>register_method ({
297 description
=> "Get firewall status.",
299 additionalProperties
=> 0,
304 additionalProperties
=> 0,
308 enum
=> ['unknown', 'stopped', 'active'],
311 description
=> "Set when there are pending changes.",
320 local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog
324 my $pid = int(PVE
::Tools
::file_read_firstline
($pve_firewall_pidfile) || 0);
325 my $running = PVE
::ProcFSTools
::check_process_running
($pid);
327 my $status = $running ?
'active' : 'stopped';
329 my $res = { status
=> $status };
330 if ($status eq 'active') {
331 my ($ruleset, $ipset_ruleset) = PVE
::Firewall
::compile
();
333 my (undef, undef, $ipset_changes) = PVE
::Firewall
::get_ipset_cmdlist
($ipset_ruleset);
334 my (undef, $ruleset_changes) = PVE
::Firewall
::get_ruleset_cmdlist
($ruleset);
336 $res->{changes
} = ($ipset_changes || $ruleset_changes) ?
1 : 0;
342 return PVE
::Firewall
::run_locked
($code);
345 __PACKAGE__-
>register_method ({
349 description
=> "Compile and print firewall rules. This is useful for testing.",
351 additionalProperties
=> 0,
354 returns
=> { type
=> 'null' },
359 local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog
362 my ($ruleset, $ipset_ruleset) = PVE
::Firewall
::compile
();
364 my (undef, undef, $ipset_changes) = PVE
::Firewall
::get_ipset_cmdlist
($ipset_ruleset, 1);
365 my (undef, $ruleset_changes) = PVE
::Firewall
::get_ruleset_cmdlist
($ruleset, 1);
366 if ($ipset_changes || $ruleset_changes) {
367 print "detected changes\n";
369 print "no changes\n";
373 PVE
::Firewall
::run_locked
($code);
378 my $nodename = PVE
::INotify
::nodename
();
381 start
=> [ __PACKAGE__
, 'start', []],
382 stop
=> [ __PACKAGE__
, 'stop', []],
383 compile
=> [ __PACKAGE__
, 'compile', []],
384 status
=> [ __PACKAGE__
, 'status', [], undef, sub {
386 if ($res->{changes
}) {
387 print "Status: $res->{status} (pending changes)\n";
389 print "Status: $res->{status}\n";
396 PVE
::CLIHandler
::handle_cmd
($cmddef, $0, $cmd, \
@ARGV, undef, $0);
404 pve-firewall - PVE Firewall Daemon
412 This service updates iptables rules periodically.
414 =include pve_copyright