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