+__PACKAGE__->register_method ({
+ name => 'localnet',
+ path => 'localnet',
+ method => 'GET',
+ description => "Print information about local network.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {},
+ },
+ returns => { type => 'null' },
+ code => sub {
+ my ($param) = @_;
+
+ local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog
+
+ my $nodename = PVE::INotify::nodename();
+ print "local hostname: $nodename\n";
+
+ my $ip = PVE::Cluster::remote_node_ip($nodename);
+ print "local IP address: $ip\n";
+
+ my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
+
+ my $localnet = PVE::Firewall::local_network() || '127.0.0.0/8';
+ print "network auto detect: $localnet\n";
+ if ($cluster_conf->{aliases}->{local_network}) {
+ print "using user defined local_network: $cluster_conf->{aliases}->{local_network}->{cidr}\n";
+ } else {
+ print "using detected local_network: $localnet\n";
+ }
+
+ return undef;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'simulate',
+ path => 'simulate',
+ method => 'GET',
+ description => "Simulate firewall rules. This does not simulate kernel 'routing' table. Instead, this simply assumes that routing from source zone to destination zone is possible.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ verbose => {
+ description => "Verbose output.",
+ type => 'boolean',
+ optional => 1,
+ default => 0,
+ },
+ from => {
+ description => "Source zone.",
+ type => 'string',
+ pattern => '(host|outside|vm\d+|ct\d+|vmbr\d+/\S+)',
+ optional => 1,
+ default => 'outside',
+ },
+ to => {
+ description => "Destination zone.",
+ type => 'string',
+ pattern => '(host|outside|vm\d+|ct\d+|vmbr\d+/\S+)',
+ optional => 1,
+ default => 'host',
+ },
+ protocol => {
+ description => "Protocol.",
+ type => 'string',
+ pattern => '(tcp|udp)',
+ optional => 1,
+ default => 'tcp',
+ },
+ dport => {
+ description => "Destination port.",
+ type => 'integer',
+ minValue => 1,
+ maxValue => 65535,
+ optional => 1,
+ },
+ sport => {
+ description => "Source port.",
+ type => 'integer',
+ minValue => 1,
+ maxValue => 65535,
+ optional => 1,
+ },
+ source => {
+ description => "Source IP address.",
+ type => 'string', format => 'ipv4',
+ optional => 1,
+ },
+ dest => {
+ description => "Destination IP address.",
+ type => 'string', format => 'ipv4',
+ optional => 1,
+ },
+ },
+ },
+ returns => { type => 'null' },
+ code => sub {
+ my ($param) = @_;
+
+ local $SIG{'__WARN__'} = 'DEFAULT'; # do not fill up syslog
+
+ my ($ruleset, $ipset_ruleset, $rulesetv6) = PVE::Firewall::compile(undef, undef, undef, $param->{verbose});
+
+ PVE::FirewallSimulator::debug($param->{verbose} || 0);
+
+ my $host_ip = PVE::Cluster::remote_node_ip($nodename);
+
+ PVE::FirewallSimulator::reset_trace();
+ print Dumper($ruleset) if $param->{verbose};
+
+ my $test = {
+ from => $param->{from},
+ to => $param->{to},
+ proto => $param->{protocol} || 'tcp',
+ source => $param->{source},
+ dest => $param->{dest},
+ dport => $param->{dport},
+ sport => $param->{sport},
+ };
+
+ if (!defined($test->{to})) {
+ $test->{to} = 'host';
+ PVE::FirewallSimulator::add_trace("Set Zone: to => '$test->{to}'\n");
+ }
+ if (!defined($test->{from})) {
+ $test->{from} = 'outside',
+ PVE::FirewallSimulator::add_trace("Set Zone: from => '$test->{from}'\n");
+ }
+
+ my $vmdata = PVE::Firewall::read_local_vm_config();
+
+ print "Test packet:\n";
+
+ foreach my $k (qw(from to proto source dest dport sport)) {
+ printf(" %-8s: %s\n", $k, $test->{$k}) if defined($test->{$k});
+ }
+
+ $test->{action} = 'QUERY';
+
+ my $res = PVE::FirewallSimulator::simulate_firewall($ruleset, $ipset_ruleset,
+ $host_ip, $vmdata, $test);
+
+ print "ACTION: $res\n";
+
+ return undef;
+ }});