]> git.proxmox.com Git - pve-firewall.git/blob - src/pvefw
ifupdown.sh: correctly use ifup instead of ifconfig
[pve-firewall.git] / src / pvefw
1 #!/usr/bin/perl -T
2
3 use strict;
4 use warnings;
5
6 use lib qw(.);
7 use PVE::Firewall;
8
9 use PVE::SafeSyslog;
10 use PVE::Cluster;
11 use PVE::INotify;
12 use PVE::RPCEnvironment;
13
14 use PVE::JSONSchema qw(get_standard_option);
15
16 use PVE::CLIHandler;
17
18 use base qw(PVE::CLIHandler);
19
20 $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
21
22 initlog ('pvefw');
23
24 die "please run as root\n" if $> != 0;
25
26 PVE::INotify::inotify_init();
27
28 my $rpcenv = PVE::RPCEnvironment->init('cli');
29
30 $rpcenv->init_request();
31 $rpcenv->set_language($ENV{LANG});
32 $rpcenv->set_user('root@pam');
33
34 __PACKAGE__->register_method ({
35 name => 'compile',
36 path => 'compile',
37 method => 'POST',
38 description => "Compile amd print firewall rules. This is only for testing.",
39 parameters => {
40 additionalProperties => 0,
41 properties => {
42 verbose => {
43 description => "Verbose output.",
44 type => "boolean",
45 optional => 1,
46 },
47 },
48 },
49 returns => { type => 'null' },
50
51 code => sub {
52 my ($param) = @_;
53
54 my $rpcenv = PVE::RPCEnvironment::get();
55
56 $param->{verbose} = 1
57 if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
58
59 my $code = sub {
60 my $ruleset = PVE::Firewall::compile();
61 PVE::Firewall::get_ruleset_status($ruleset, 1) if $param->{verbose};
62 };
63
64 PVE::Firewall::run_locked($code);
65
66 return undef;
67 }});
68
69 __PACKAGE__->register_method ({
70 name => 'status',
71 path => 'status',
72 method => 'GET',
73 description => "Get firewall status.",
74 parameters => {
75 additionalProperties => 0,
76 properties => {},
77 },
78 returns => {
79 type => 'object',
80 additionalProperties => 0,
81 properties => {
82 status => {
83 type => 'string',
84 enum => ['unknown', 'stopped', 'active'],
85 },
86 changes => {
87 description => "Set when there are pending changes.",
88 type => 'boolean',
89 optional => 1,
90 }
91 },
92 },
93 code => sub {
94 my ($param) = @_;
95
96 my $rpcenv = PVE::RPCEnvironment::get();
97
98 $param->{verbose} = 1
99 if !defined($param->{verbose}) && ($rpcenv->{type} eq 'cli');
100
101 my $code = sub {
102 my $status = PVE::Firewall::read_pvefw_status();
103
104 my $res = { status => $status };
105 if ($status eq 'active') {
106 my $ruleset = PVE::Firewall::compile();
107 my $cmdlist = PVE::Firewall::get_rulset_cmdlist($ruleset);
108
109 if ($cmdlist ne "*filter\nCOMMIT\n") {
110 $res->{changes} = 1;
111 }
112 }
113
114 return $res;
115 };
116
117 return PVE::Firewall::run_locked($code);
118 }});
119
120 __PACKAGE__->register_method ({
121 name => 'start',
122 path => 'start',
123 method => 'POST',
124 description => "Start (or simply update if already active) firewall.",
125 parameters => {
126 additionalProperties => 0,
127 properties => {
128 verbose => {
129 description => "Verbose output.",
130 type => "boolean",
131 optional => 1,
132 default => 0,
133 },
134 },
135 },
136 returns => { type => 'null' },
137
138 code => sub {
139 my ($param) = @_;
140
141 PVE::Firewall::update(1, $param->{verbose});
142
143 return undef;
144 }});
145
146 __PACKAGE__->register_method ({
147 name => 'update',
148 path => 'update',
149 method => 'POST',
150 description => "Check firewall rules. Then update the rules if the firewall is active.",
151 parameters => {
152 additionalProperties => 0,
153 properties => {
154 verbose => {
155 description => "Verbose output.",
156 type => "boolean",
157 optional => 1,
158 default => 0,
159 },
160 },
161 },
162 returns => { type => 'null' },
163
164 code => sub {
165 my ($param) = @_;
166
167 PVE::Firewall::update(0, $param->{verbose});
168
169 return undef;
170 }});
171
172 __PACKAGE__->register_method ({
173 name => 'stop',
174 path => 'stop',
175 method => 'POST',
176 description => "Stop firewall. This will remove all rules installed by this script. The host is then unprotected.",
177 parameters => {
178 additionalProperties => 0,
179 properties => {},
180 },
181 returns => { type => 'null' },
182
183 code => sub {
184 my ($param) = @_;
185
186 my $code = sub {
187
188 my $chash = PVE::Firewall::iptables_get_chains();
189 my $cmdlist = "*filter\n";
190 my $rule = "INPUT -j PVEFW-INPUT";
191 if (PVE::Firewall::iptables_rule_exist($rule)) {
192 $cmdlist .= "-D $rule\n";
193 }
194 $rule = "OUTPUT -j PVEFW-OUTPUT";
195 if (PVE::Firewall::iptables_rule_exist($rule)) {
196 $cmdlist .= "-D $rule\n";
197 }
198
199 $rule = "FORWARD -j PVEFW-FORWARD";
200 if (PVE::Firewall::iptables_rule_exist($rule)) {
201 $cmdlist .= "-D $rule\n";
202 }
203
204 foreach my $chain (keys %$chash) {
205 $cmdlist .= "-F $chain\n";
206 }
207 foreach my $chain (keys %$chash) {
208 $cmdlist .= "-X $chain\n";
209 }
210 $cmdlist .= "COMMIT\n";
211
212 PVE::Firewall::iptables_restore_cmdlist($cmdlist);
213
214 PVE::Firewall::save_pvefw_status('stopped');
215 };
216
217 PVE::Firewall::run_locked($code);
218
219 return undef;
220 }});
221
222 my $nodename = PVE::INotify::nodename();
223
224 my $cmddef = {
225 compile => [ __PACKAGE__, 'compile', []],
226 start => [ __PACKAGE__, 'start', []],
227 update => [ __PACKAGE__, 'update', []],
228 status => [ __PACKAGE__, 'status', [], undef, sub {
229 my $res = shift;
230 if ($res->{changes}) {
231 print "Status: $res->{status} (pending changes)\n";
232 } else {
233 print "Status: $res->{status}\n";
234 }
235 }],
236 stop => [ __PACKAGE__, 'stop', []],
237 };
238
239 my $cmd = shift;
240
241 PVE::CLIHandler::handle_cmd($cmddef, "pvefw", $cmd, \@ARGV, undef, $0);
242
243 exit(0);
244