#!/usr/local/bin/perl
# index.cgi
# Display current iptables firewall configuration from save file
require './firewall-lib.pl';
&ReadParse();
if ($iptables_save_file) {
$desc = &text('index_editing', "$iptables_save_file");
}
&ui_print_header(undef, $text{'index_title'}, undef, "intro", 1, 1, 0,
&help_search_link("iptables", "man", "doc"), undef, undef, $desc);
# Check for iptables and iptables-restore commands
if ($c = &missing_firewall_commands()) {
print "
",&text('index_ecommand', "$c"),"
\n";
&ui_print_footer("/", $text{'index'});
exit;
}
# Check if the kernel supports iptables
$out = &backquote_command("iptables -n -t filter -L OUTPUT 2>&1");
if ($?) {
print "
",&text('index_ekernel', "
$out
"),"\n";
&ui_print_footer("/", $text{'index'});
exit;
}
# Check if the distro supports iptables
if (!$config{'direct'} && defined(&check_iptables) &&
($err = &check_iptables())) {
print "
$err
\n";
&ui_print_footer("/", $text{'index'});
exit;
}
# Check if firewall is being started at boot
if (!$config{'direct'} && &foreign_check("init")) {
$init_support++;
if (defined(&started_at_boot)) {
$atboot = &started_at_boot();
}
else {
&foreign_require("init", "init-lib.pl");
$atboot = &init::action_status("webmin-iptables") == 2;
}
}
# Check if the save file exists. If not, check for any existing firewall
# rules, and offer to create a save file from them
@livetables = &get_iptables_save("iptables-save 2>/dev/null |");
# Display warnings about active external firewalls!
&external_firewall_message(\@livetables);
if (!$config{'direct'} &&
(!-s $iptables_save_file || $in{'reset'}) && $access{'setup'}) {
@tables = @livetables;
foreach $t (@tables) {
$rules++ if (@{$t->{'rules'}});
foreach $c (keys %{$t->{'defaults'}}) {
$chains++ if ($t->{'defaults'}->{$c} ne 'ACCEPT');
}
$hastable{$t->{'name'}}++;
}
foreach $t (@known_tables) {
system("iptables -t $t -n -L >/dev/null") if (!$hastable{$t});
}
if (!$in{'reset'} && ($rules || $chains)) {
# Offer to save the current rules
print &ui_confirmation_form("convert.cgi",
&text('index_existing', $rules,
"$iptables_save_file"),
undef,
[ [ undef, $text{'index_saveex'} ] ],
$init_support && !$atboot ?
&ui_checkbox("atboot", 1, $text{'index_atboot'}, 0) :
"",
);
print &ui_table_start($text{'index_headerex'}, "width=100%", 2);
$out = &backquote_command("iptables-save 2>/dev/null");
print &ui_table_row(undef,
"".&html_escape($out)."
", 2);
print &ui_table_end();
}
else {
# Offer to set up a firewall
print &text($in{'reset'} ? 'index_rsetup' : 'index_setup',
"$iptables_save_file"),"\n";
print &ui_form_start("setup.cgi");
print &ui_hidden("reset", $in{'reset'});
print "
| \n";
print &ui_oneradio("auto", 0, $text{'index_auto0'}, 1)," \n";
foreach $a (1 .. 5) {
print &ui_oneradio("auto", $a,
$text{'index_auto'.$a}, 0)." ";
print &interface_choice("iface".$a)," \n";
}
print " |
\n";
print &ui_submit($text{'index_auto'}),"\n";
if ($init_support && !$atboot) {
print &ui_checkbox("atboot", 1,
$text{'index_atboot'}, 0);
}
print "
\n";
print &ui_form_end();
}
}
else {
$form = 0;
@tables = &get_iptables_save();
if (!$config{'direct'}) {
# Verify that all known tables exist, and if not add them to the
# save file
foreach $t (@tables) {
$hastable{$t->{'name'}}++;
}
foreach $t (@known_tables) {
if (!$hastable{$t}) {
local ($missing) = &get_iptables_save(
"iptables-save --table $t 2>/dev/null |");
if ($missing) {
delete($missing->{'line'});
&save_table($missing);
}
$need_reload++;
}
}
@tables = &get_iptables_save() if ($need_reload);
}
# Check if the current config is valid
if (!$config{'direct'}) {
my $err = &validate_iptables_config();
if ($err) {
print "",&text('index_evalid',
&html_escape($err)),"\n";
}
}
# Work out the default table
if (!defined($in{'table'})) {
foreach $t (@tables) {
if (@{$t->{'rules'}} && &can_edit_table($t->{'name'})) {
$in{'table'} = $t->{'index'};
last;
}
}
}
if (!defined($in{'table'})) {
foreach $t (@tables) {
if (&can_edit_table($t->{'name'})) {
$in{'table'} = $t->{'index'};
last;
}
}
}
$table = $tables[$in{'table'}];
# Allow selection of a table
print "
\n";
print "\n";
$form++;
if ($access{'newchain'}) {
# Show form to create a chain
print "\n";
print "
\n";
$form++;
}
# Display a table of rules for each chain
CHAIN:
foreach $c (sort by_string_for_iptables keys %{$table->{'defaults'}}) {
print &ui_hr();
@rules = grep { lc($_->{'chain'}) eq lc($c) }
@{$table->{'rules'}};
print "",$text{"index_chain_".lc($c)} ||
&text('index_chain', "$c"),"
\n";
# check if chain is filtered out
if ($config{'filter_chain'}) {
foreach $filter (split(',', $config{'filter_chain'})) {
if($c =~ /^$filter$/) {
# not managed by firewall, do not dispaly or modify
print "".$text{'index_filter_chain'}."
\n";
next CHAIN;
}
}
}
print "\n";
$form++;
}
# Show ipset overview if ipsets are availibe
# may need to check if they are used by firewall rules
@ipsets = &get_ipsets_active();
if (@ipsets) {
print &ui_hr();
print "$text{'index_ipset_title'}";
# Generate the header
local (@hcols, @tds);
push(@hcols, $text{'index_ipset'}, $text{'index_ipset_name'}, $text{'index_ipset_type'},
$text{'index_ipset_elem'}, $text{'index_ipset_size'});
push(@tds, "", "", "", "", "");
print &ui_columns_start(\@hcols, 100, 0, \@tds);
# Generate a row for each rule
foreach $s (@ipsets) {
local @cols;
push(@cols, "", "$s->{'Name'}", $s->{'Type'},$s->{'Number'},$s->{'Size'});
print &ui_columns_row(\@cols, \@tds);
}
print &ui_columns_end();
}
# Display buttons for applying and un-applying the configuration,
# and for creating an init script if possible
print &ui_hr();
print &ui_buttons_start();
if (!$config{'direct'}) {
# Buttons to apply and reset the config
if (&foreign_check("servers")) {
@servers = &list_cluster_servers();
}
if ($access{'apply'}) {
print &ui_buttons_row("apply.cgi",
$text{'index_apply'},
@servers ? $text{'index_applydesc2'}
: $text{'index_applydesc'},
[ [ "table", $in{'table'} ] ]);
}
if ($access{'unapply'}) {
print &ui_buttons_row("unapply.cgi",
$text{'index_unapply'},
$text{'index_unapplydesc'},
[ [ "table", $in{'table'} ] ]);
}
if ($init_support && $access{'bootup'}) {
print &ui_buttons_row("bootup.cgi",
$text{'index_bootup'},
$text{'index_bootupdesc'},
[ [ "table", $in{'table'} ] ],
&ui_yesno_radio("boot", $atboot));
}
if ($access{'setup'}) {
print &ui_buttons_row("index.cgi",
$text{'index_reset'}, $text{'index_resetdesc'},
[ [ "reset", 1 ] ]);
}
}
else {
# Button to save the live config in a file
if ($access{'unapply'}) {
print &ui_buttons_row("unapply.cgi",
$text{'index_unapply2'},
$text{'index_unapply2desc'},
[ [ "table", $in{'table'} ] ]);
}
}
# Show button for cluster page
if (&foreign_check("servers")) {
&foreign_require("servers", "servers-lib.pl");
@allservers = grep { $_->{'user'} }
&servers::list_servers();
}
if ($access{'cluster'} && @allservers) {
print &ui_buttons_row(
"cluster.cgi", $text{'index_cluster'},
$text{'index_clusterdesc'});
}
print &ui_buttons_end();
}
&ui_print_footer("/", $text{'index'});
sub external_firewall_message
{
local $fwname="";
local $fwconfig="$gconfig{'webprefix'}/config.cgi?firewall";
# detect external firewalls
local ($filter) = grep { $_->{'name'} eq 'filter' } @{$_[0]};
if ($filter->{'defaults'}->{'shorewall'}) {
$fwname+='shorewall ';
}
if ($filter->{'defaults'}->{'INPUT_ZONES'}) {
$fwname+='firewalld ';
}
if ($filter->{'defaults'} ~~ /^f2b-|^fail2ban-/) {
$fwname+='fail2ban ';
}
# warning about not using direct
if($fwname && !$config{'direct'}) {
print "",
&text('index_filter_nodirect', $fwconfig),
"\n";
}
# naming the detected firewall modules
foreach my $word (split ' ', $fwname) {
print "
",
&text("index_$word", "$gconfig{'webprefix'}/$word/", $fwconfig),
"\n";
}
}