Viewing File: /usr/local/cpanel/whostmgr/docroot/cgi/addon_hgfirewall.cgi
#!/usr/local/cpanel/3rdparty/bin/perl
# Source: /usr/local/cpanel/whostmgr/cgi/addon_hgfirewall.cgi
# Date: 10/15/13
# Revision: 2.0
# Author: Matthew Harris
# Hostgator.com LLC
#WHMADDON:hgfire:HG Firewall Administration:hgfire.gif
use lib '/usr/local/cpanel';
use strict;
use warnings;
use Whostmgr::ACLS();
use Whostmgr::HTMLInterface;
use File::Copy;
use File::Basename;
use Carp;
use CGI;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
# Because its how the internet works
print "Content-type: text/html\n\n";
# Check if the user has root
Whostmgr::ACLS::init_acls();
if ( !Whostmgr::ACLS::checkacl('all') ) {
print 'Access Denied.';
exit;
}
# Subroutine definitions
sub error_check; # Shared check, Firewall installed, Etc
sub open_file; # Open files
sub append_file; # Append to file
sub write_file; # Write a file
sub draw_forms; # Draw data tables
sub draw_controls; # Draw controls
sub modify_file; # Remove line from file
sub handle_ajax; # Ajax all the things
# Handle ajax calls first
handle_ajax;
# Define the header
Whostmgr::HTMLInterface::defheader("HG Firewall Administration");
# Load CSS for x theme
print
qq{<link href="/cPanel_magic_revision_1314914829/themes/x/style_optimized.css" type="text/css" rel="stylesheet">};
print
qq{<link href="//code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" type="text/css" rel="stylesheet">};
# Inline CSS to keep it all in one file
print <<'CSS';
<style>
h1{margin-left:10px; display:inline;}
#help_firewall{margin-left:5px; color:#5388F2;}
p{display:inline;}
.left{float:left; width:30%; margin-left:30px !important;}
.cbox{float:left; width:30%; margin-left:30px !important; margin-bottom:20px; margin-top:20px;}
.row:hover{background-color:#FFB2B2;}
#custom_rules{clear:both;}
#manage_div{width:95%; margin:0 auto;}
#control_box{width:100%; margin:0 auto; clear:both;}
</style>
CSS
# Start Draw
error_check;
draw_controls;
draw_forms;
# JS @ the bottom
print <<'JS';
<script src="//code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
<script src="//cdn.jsdelivr.net/noty/2.1.0/jquery.noty.js"></script>
<script src="//cdn.jsdelivr.net/noty/2.1.0/layouts/top.js"></script>
<script src="//cdn.jsdelivr.net/noty/2.1.0/themes/default.js"></script>
<script type="text/javascript">
$(document).ready(function() {
function ajaxRequest(query, callback) {
$.ajax({
type: "POST",
data: query,
url: "addon_hgfirewall.cgi",
success: callback,
});
}
function successMsg(msg) {
var n = noty({
text: msg,
type: 'success',
layout: 'top',
timeout: '2000',
});
}
function failureMsg(msg) {
var n = noty({
text: msg,
type: 'error',
layout: 'top',
timeout: '2000',
});
}
// Load Data Tables
var cr = $("#custom_rules").dataTable({
"oLanguage": {
"sEmptyTable": "No custom rules setup.",
},
"bInfo": false,
"bFilter": false,
"bPaginate": false,
"fnInitComplete": function() {
$(this).on('dblclick', '.row', rm_cr);
},
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td:eq(0)', nRow).addClass('row');
},
});
var i_p = $("#in_ports").dataTable({
"oLanguage": {
"sEmptyTable": "No inbound ports.",
},
"bInfo": false,
"bFilter": false,
"bPaginate": false,
"fnInitComplete": function() {
$(this).on('dblclick', '.row', rm_ip);
},
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td:eq(0)', nRow).addClass('row');
},
});
var o_p = $("#out_ports").dataTable({
"oLanguage": {
"sEmptyTable": "No inbound ports.",
},
"bInfo": false,
"bFilter": false,
"bPaginate": false,
"fnInitComplete": function() {
$(this).on('dblclick', '.row', rm_op);
},
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td:eq(0)', nRow).addClass('row');
},
});
var bip = $("#ips").dataTable({
"oLanguage": {
"sEmptyTable": "No blocked IPs.",
},
"bInfo": false,
"bFilter": false,
"bPaginate": false,
"fnInitComplete": function() {
$(this).on('dblclick', '.row', rm_bip);
},
"fnRowCallback": function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td:eq(0)', nRow).addClass('row');
},
});
function rm_cr() {
var line = $('p', this).text();
var query = "func=remove_rule&line=" + line;
ajaxRequest(query, function(data) {
successMsg("Custom Rule Removed!");
});
var row = $(this).closest('tr')[0];
cr.fnDeleteRow(row);
}
function rm_ip() {
var line = $('p', this).text();
var query = "func=remove_iport&line=" + line;
ajaxRequest(query, function(data) {
successMsg("Closed port: " + line);
});
var row = $(this).closest('tr')[0];
i_p.fnDeleteRow(row);
}
function rm_op() {
var line = $('p', this).text();
var query = "func=remove_oport&line=" + line;
ajaxRequest(query, function(data) {
successMsg("Closed port: " + line);
});
var row = $(this).closest('tr')[0];
o_p.fnDeleteRow(row);
}
function rm_bip() {
var line = $('p', this).text();
var query = "func=remove_ip&line=" + line;
ajaxRequest(query, function(data) {
successMsg("Unblocked IP: " + line);
});
var row = $(this).closest('tr')[0];
bip.fnDeleteRow(row);
}
function validateIP(ip) {
// ipv4
if(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/.test(ip)) {
return true;
// ipv4 cidr
} else if (/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(\d|[1-2]\d|3[0-2]))$/.test(ip)) {
return true;
// ipv6
} else if (/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*/.test(ip)) {
return true;
} else {
return false;
}
}
function validatePort(port) {
if(/^\d{1,6}$/.test(port)) {
return true;
} else {
return false;
}
}
function validateRule(rule) {
if(/^iptables/.test(rule)) {
return rule;
} else {
rule = "iptables " + rule;
return rule;
}
}
$("#help_firewall").tooltip({
show: { effect: "slideDown", delay: 250 },
content: '<div id="instruction_box"><strong>Remove Item:</strong> Double-click Item<br/><strong>Add Item:</strong> Use Forms Below<br/><br/><em>Backups are created for each change.</em><br/><strong>Restore Backup:</strong> Contact Support<br/><br/><strong><em>In order for changes to take affect you must restart the firewall</em></strong></div>',
items: "span",
});
$("#add_ip").click(function() {
var ip = $("#in_ip").val();
if ( ip ) {
if ( validateIP(ip) ) {
var query = "func=add_ip&line=" + ip;
ajaxRequest(query, function(data) {
cr.fnAddData([
'iptables -I INPUT -s ' + ip + ' -j ACCEPT',
]);
successMsg("Whitelisted IP: " + ip);
$("#in_ip").val('');
});
} else {
failureMsg("Please enter a valid IP or range.");
}
} else {
failureMsg("Missing required field");
}
});
$("#block_ip").click(function() {
var ip = $("#b_ip").val();
if ( ip ) {
if ( validateIP(ip) ) {
var query = "func=block_ip&line=" + ip;
ajaxRequest(query, function(data) {
bip.fnAddData([
'<p>' + ip + '</p>',
]);
successMsg("Blacklisted IP: " + ip);
$("#b_ip").val('');
});
} else {
failureMsg("Please enter a valid IP or range.");
}
} else {
failureMsg("Missing required field");
}
});
$("#add_rule").click(function() {
var rule = $("#add_custom_rule").val();
if ( rule ) {
rule = validateRule(rule);
var query = "func=add_rule&line=" + rule;
ajaxRequest(query, function(data) {
cr.fnAddData([
rule,
]);
successMsg("Added Rule: " + rule);
$("#add_custom_rule").val('');
});
} else {
failureMsg("Missing required field");
}
});
$("#open_out_port").click(function() {
var port = $("#open_outbound").val();
if ( port ) {
if ( validatePort(port) ) {
var query = "func=open_out_port&line=" + port;
ajaxRequest(query, function(data) {
o_p.fnAddData([
'<p>' + port + '</p>',
]);
successMsg("Opened Port " + port + " Outbound");
$("#open_outbound").val('');
});
} else {
failureMsg("Please enter a valid port.");
}
} else {
failureMsg("Missing required field");
}
});
$("#open_in_port").click(function() {
var port = $("#open_inbound").val();
if ( port ) {
if ( validatePort(port) ) {
var query = "func=open_in_port&line=" + port;
ajaxRequest(query, function(data) {
i_p.fnAddData([
'<p>' + port + '</p>',
]);
successMsg("Opened Port " + port + " Inbound");
$("#open_inbound").val('');
});
} else {
failureMsg("Please enter a valid port.");
}
} else {
failureMsg("Missing required field");
}
});
$("#stop_firewall").click(function() {
var query = "func=stop_firewall";
ajaxRequest(query, function(data) {
successMsg("Stopped Firewall");
});
});
$("#start_firewall").click(function() {
var query = "func=start_firewall";
ajaxRequest(query, function(date) {
successMsg("Started Firewall");
});
});
$("#restart_firewall").click(function() {
var query = "func=restart_firewall";
ajaxRequest(query, function(data) {
successMsg("Restarted Firewall");
});
});
});
</script>
JS
Whostmgr::HTMLInterface::deffooter();
# Subroutine Bodies
sub error_check {
croak "This is a shared server." if -f '/admin/hgbackupdir/restore.pl';
croak "This is an old shared server." if -f '/home/hgbackupdir/restore.pl';
croak "Firewall not installed." if !-f '/usr/sbin/firewall';
}
sub open_file {
my $file = shift;
open my $fh, '<', $file or croak "Cannot read file : $file";
my @contents = <$fh>;
close $fh;
return \@contents;
}
sub append_file {
my ( $file, $line ) = @_;
open my $fh, '>>', $file or croak "Cannot append to file : $file";
print {$fh} "$line\n";
close $fh;
}
sub write_file {
my ( $file, @content ) = @_;
open my $fh, '>', $file or croak "Cannot write file: $file";
print {$fh} @content;
close $fh;
}
sub backup_file {
my $file = shift;
my $date = time();
my $base = basename($file);
mkdir '/etc/firewall/whm-backup', 0755 if !-d '/etc/firewall/whm-backup';
copy( $file, "/etc/firewall/whm-backup/$base-$date" );
}
sub draw_forms {
# START Custom Rules Table
my $content = open_file('/etc/firewall/INCLUDE');
print
qq{<table border=1 class="datatable brick" id="custom_rules" align=center width=90% cellpadding=5>};
print qq{<thead><tr><th>Custom Firewall Rules</th></tr></thead>};
print qq{<tbody>};
# Print rows of iptables rules from /etc/firewall/INCLUDE
foreach my $line (@$content) {
if ( $line !~ /^#/ and $line !~ /^$/ and $line ) {
print qq{<tr>};
print qq{<td class="row"><p>$line</p></td>};
print qq{</tr>};
}
}
print qq{</tbody>};
print qq{</table>};
# END Custom Rules Table
print qq{<br/><br/>};
print qq{<div id="manage_div">};
# START Port Management
# INBOUND
$content = open_file('/etc/firewall/INPUT');
print
qq{<table border=1 class="datatable brick left" id="in_ports" align=center border=0 cellpadding=5>};
print qq{<thead><th>Inbound Ports</th></thead>};
print qq{<tbody>};
foreach my $line (@$content) {
if ( $line !~ /^#/ and $line !~ /^$/ ) {
print qq{<tr><td><p>$line</p></td></tr>};
}
}
print qq{</tbody>};
print qq{</table>};
# OUTBOUND
$content = open_file('/etc/firewall/OUTPUT');
print
qq{<table border=1 class="datatable brick left" id="out_ports" align=center border=0 cellpadding=5>};
print qq{<thead><th>Outbound Ports</th></thead>};
print qq{<tbody>};
foreach my $line (@$content) {
if ( $line !~ /^#/ and $line !~ /^$/ ) {
print qq{<tr><td><p>$line</p></td></tr>};
}
}
print qq{</tbody>};
print qq{</table>};
# END Port Management
# BLOCKED IPS
my $file = '/etc/firewall/IPDROP_GLOBAL';
$file = '/etc/firewall/GLOBAL_DROP' if ! -f $file;
$content = open_file($file);
print
qq{<table border=1 class="datatable brick left" id="ips" align=center border=0 cellpadding=5>};
print qq{<thead><th>Blocked IP's</th></thead>};
print qq{<tbody>};
foreach my $line (@$content) {
if ( $line !~ /^#/ and $line !~ /^$/ ) {
print qq{<tr><td><p>$line</p></td></tr>};
}
}
print qq{</tbody>};
print qq{</table>};
# END IP Management
print qq{</div>};
}
sub draw_controls {
print qq{<div id="control_box">};
print qq{<div class="cbox">};
print qq{<p><em>Add a custom iptables rule to a chain.</em></p><br/>};
print
qq{<input type="text" id="add_custom_rule"/><input type="submit" id="add_rule" value="Add Rule"/>};
print qq{</div>};
print qq{<div class="cbox">};
print qq{<p><em>Open an outbound port.</em></p><br/>};
print
qq{<input type="text" id="open_outbound"/><input type="submit" id="open_out_port" value="Open Port"/>};
print qq{</div>};
print qq{<div class="cbox">};
print qq{<p><em>Open an inbound port.</em></p><br/>};
print
qq{<input type="text" id="open_inbound"/><input type="submit" id="open_in_port" value="Open Port"/>};
print qq{</div>};
print qq{<div class="cbox">};
print qq{<p><em>Whitelist an IP address.</em></p><br/>};
print
qq{<input type="text" id="in_ip"/><input type="submit" id="add_ip" value="Add IP"/>};
print qq{</div>};
print qq{<div class="cbox">};
print qq{<p><em>Blacklist an IP address.</em></p><br/>};
print
qq{<input type="text" id="b_ip"/><input type="submit" id="block_ip" value="Block IP"/>};
print qq{</div>};
print qq{<div class="cbox">};
print qq{<p><em>Manage Firewall Service</em></p><br/>};
print qq{<input type="submit" id="stop_firewall" value="Stop"/>};
print qq{<input type="submit" id="start_firewall" value="Start"/>};
print qq{<input type="submit" id="restart_firewall" value="Restart"/>};
print qq{</div>};
print qq{</div>};
}
sub modify_file {
my ( $file, $line ) = @_;
my $content = open_file($file);
backup_file($file);
my @new_content;
print "Line: '$line'\n";
foreach (@$content) {
chomp;
print "SL: '$_'\n";
if ( $_ ne $line ) {
push @new_content, "$_\n";
}
}
write_file( $file, @new_content );
}
sub handle_ajax {
# Handle AJAX
my $cgi = CGI->new;
my $num_params = $cgi->param();
if ($num_params) {
my $function = $cgi->param('func');
my $line = $cgi->param('line');
chomp($line);
print "\n\n\nFUNCTION: $function\nLINE: $line\n\n\n";
if($function eq "remove_rule") {
modify_file( '/etc/firewall/INCLUDE', $line );
} elsif($function eq "remove_iport") {
modify_file( '/etc/firewall/INPUT', $line );
} elsif($function eq "remove_oport") {
modify_file( '/etc/firewall/OUTPUT', $line );
} elsif($function eq "remove_ip") {
my $file = '/etc/firewall/IPDROP_GLOBAL';
$file = '/etc/firewall/GLOBAL_DROP' if ! -f $file;
modify_file( $file, $line );
} elsif($function eq "add_rule") {
append_file( '/etc/firewall/INCLUDE', $line );
} elsif($function eq "open_out_port") {
append_file( '/etc/firewall/OUTPUT', $line );
} elsif($function eq "open_in_port") {
append_file( '/etc/firewall/INPUT', $line );
} elsif($function eq "add_ip") {
$line = "iptables -I INPUT -s $line -j ACCEPT\n";
append_file( '/etc/firewall/INCLUDE', $line );
} elsif($function eq "block_ip") {
my $file = '/etc/firewall/IPDROP_GLOBAL';
$file = '/etc/firewall/GLOBAL_DROP' if ! -f $file;
append_file( $file, $line );
} elsif($function eq "stop_firewall") {
system("/etc/init.d/firewall stop > /dev/null");
} elsif($function eq "start_firewall") {
system("/etc/init.d/firewall start > /dev/null");
} elsif($function eq "restart_firewall") {
system("/etc/init.d/firewall restart > /dev/null");
}
exit;
}
}
Back to Directory
File Manager