Commit 42f191ba authored by tbrehm's avatar tbrehm

Implemented support for UFW firewall (FS#1757 - New IPTables firewall script for IPv4 and IPv6)

parent ee0bc768
......@@ -470,6 +470,15 @@ class installer_base {
if(!$this->dbmaster->query($query)) {
$this->warning('Unable to set rights of user in master database: '.$value['db']."\n Query: ".$query."\n Error: ".$this->dbmaster->errorMessage);
}
$query = "GRANT SELECT, UPDATE ON ".$value['db'].".`aps_instances` TO '".$value['user']."'@'".$host."' ";
if ($verbose){
echo $query ."\n";
}
if(!$this->dbmaster->query($query)) {
$this->warning('Unable to set rights of user in master database: '.$value['db']."\n Query: ".$query."\n Error: ".$this->dbmaster->errorMessage);
}
}
/*
......
......@@ -11,6 +11,7 @@ netmask=255.255.255.0
gateway=192.168.0.1
hostname=server1.domain.tld
nameservers=192.168.0.1,192.168.0.2
firewall=bastille
loglevel=2
backup_dir=/var/backup
backup_mode=rootgz
......
......@@ -61,7 +61,7 @@ class ApsCrawler extends ApsBase
// Check if the cURL module is available
if(!function_exists('curl_version')) throw new Exception('cURL is not available');
// Check if used folders are writable (chmod 777)
// Check if used folders are writable
if($this->interface_mode)
{
if(!is_writable($this->interface_pkg_dir))
......
......@@ -97,6 +97,14 @@ $form["tabs"]['server'] = array(
'width' => '15',
'maxlength' => '255'
),
'firewall' => array(
'datatype' => 'VARCHAR',
'formtype' => 'SELECT',
'default' => 'bastille',
'value' => array('bastille' => 'bastille', 'ufw' => 'ufw'),
'width' => '40',
'maxlength' => '255'
),
'hostname' => array(
'datatype' => 'VARCHAR',
'formtype' => 'TEXT',
......
......@@ -162,4 +162,5 @@ $wb["permissions_txt"] = 'Permissions';
$wb["php_settings_txt"] = 'PHP Settings';
$wb["apps_vhost_settings_txt"] = 'Apps Vhost Settings';
$wb["awstats_settings_txt"] = 'AWStats Settings';
$wb["firewall_txt"] = 'Firewall';
?>
\ No newline at end of file
......@@ -33,6 +33,12 @@
<p class="formHint">{tmpl_var name='nameservers_hint_txt'}</p>
</div>
<div class="ctrlHolder">
<label for="firewall">{tmpl_var name='firewall_txt'}</label>
<select name="firewall" id="firewall" class="selectInput">
{tmpl_var name='firewall'}
</select>
</div>
<div class="ctrlHolder">
<label for="loglevel">{tmpl_var name='loglevel_txt'}</label>
<select name="loglevel" id="loglevel" class="selectInput">
{tmpl_var name='loglevel'}
......
......@@ -1271,6 +1271,16 @@ class system{
}
}
//* Check if a application is installed
function is_installed($appname) {
exec('which '.escapeshellcmd($appname).' 2> /dev/null',$out,$returncode);
if(isset($out[0]) && stristr($out[0],$appname) && $returncode == 0) {
return true;
} else {
return false;
}
}
}
?>
......@@ -30,12 +30,12 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class firewall_plugin {
var $plugin_name = 'firewall_plugin';
var $class_name = 'firewall_plugin';
private $plugin_name = 'firewall_plugin';
private $class_name = 'firewall_plugin';
//* This function is called during ispconfig installation to determine
// if a symlink shall be created for this plugin.
function onInstall() {
public function onInstall() {
global $conf;
if($conf['bastille']['installed'] = true && $conf['services']['firewall'] == true) {
......@@ -51,7 +51,7 @@ class firewall_plugin {
This function is called when the plugin is loaded
*/
function onLoad() {
public function onLoad() {
global $app;
/*
......@@ -62,51 +62,182 @@ class firewall_plugin {
$app->plugins->registerEvent('firewall_insert',$this->plugin_name,'insert');
$app->plugins->registerEvent('firewall_update',$this->plugin_name,'update');
$app->plugins->registerEvent('firewall_delete',$this->plugin_name,'delete');
}
public function insert($event_name,$data) {
global $app, $conf;
$this->update($event_name,$data);
}
public function update($event_name,$data) {
global $app, $conf;
//* load the server configuration options
$app->uses('getconf');
$server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
if($server_config['firewall'] == 'ufw') {
$this->ufw_update($event_name,$data);
} else {
$this->bastille_update($event_name,$data);
}
}
function insert($event_name,$data) {
public function delete($event_name,$data) {
global $app, $conf;
$this->update($event_name,$data);
//* load the server configuration options
$app->uses('getconf');
$server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
if($server_config['firewall'] == 'ufw') {
$this->ufw_delete($event_name,$data);
} else {
$this->bastille_delete($event_name,$data);
}
}
function update($event_name,$data) {
private function ufw_update($event_name,$data) {
global $app, $conf;
$tcp_ports = '';
$udp_ports = '';
$app->uses('system');
$ports = explode(',',$data['new']['tcp_port']);
if(is_array($ports)) {
foreach($ports as $p) {
if(strstr($p,':')) {
$p_parts = explode(':',$p);
$p_clean = intval($p_parts[0]).':'.intval($p_parts[1]);
} else {
$p_clean = intval($p);
}
$tcp_ports .= $p_clean . ' ';
if(!$app->system->is_installed('ufw')) {
$app->log('UFW Firewall is not installed',LOGLEVEL_WARN);
return false;
}
exec('ufw --version',$out);
$parts = explode(' ',$out[0]);
$ufwversion = $parts[1];
unset($parts);
unset($out);
if(version_compare ( $ufwversion , '0.30') < 0) {
$app->log('The installed UFW Firewall version is too old. Minimum required version 0.30',LOGLEVEL_WARN);
return false;
}
//* Basic firewall setup when the firewall is added the first time
if($event_name == 'firewall_insert') {
exec('ufw --force disable');
exec('ufw --force reset');
exec('ufw default deny incoming');
exec('ufw default allow outgoing');
}
$tcp_ports_new = $this->clean_ports($data['new']['tcp_port'],',');
$tcp_ports_old = $this->clean_ports($data['old']['tcp_port'],',');
$udp_ports_new = $this->clean_ports($data['new']['udp_port'],',');
$udp_ports_old = $this->clean_ports($data['old']['udp_port'],',');
$tcp_ports_new_array = explode(',',$tcp_ports_new);
$tcp_ports_old_array = explode(',',$tcp_ports_old);
$udp_ports_new_array = explode(',',$udp_ports_new);
$udp_ports_old_array = explode(',',$udp_ports_old);
//* add tcp ports
foreach($tcp_ports_new_array as $port) {
if(!in_array($port,$tcp_ports_old_array) && $port > 0) {
exec('ufw allow '.$port.'/tcp');
$app->log('ufw allow '.$port.'/tcp',LOGLEVEL_DEBUG);
sleep(1);
}
}
$tcp_ports = trim($tcp_ports);
$ports = explode(',',$data['new']['udp_port']);
if(is_array($ports)) {
foreach($ports as $p) {
if(strstr($p,':')) {
$p_parts = explode(':',$p);
$p_clean = intval($p_parts[0]).':'.intval($p_parts[1]);
} else {
$p_clean = intval($p);
}
$udp_ports .= $p_clean . ' ';
//* remove tcp ports
foreach($tcp_ports_old_array as $port) {
if(!in_array($port,$tcp_ports_new_array) && $port > 0) {
exec('ufw delete allow '.$port.'/tcp');
$app->log('ufw delete allow '.$port.'/tcp',LOGLEVEL_DEBUG);
sleep(1);
}
}
//* add udp ports
foreach($udp_ports_new_array as $port) {
if(!in_array($port,$udp_ports_old_array) && $port > 0) {
exec('ufw allow '.$port.'/udp');
$app->log('ufw allow '.$port.'/udp',LOGLEVEL_DEBUG);
sleep(1);
}
}
//* remove udp ports
foreach($udp_ports_old_array as $port) {
if(!in_array($port,$udp_ports_new_array) && $port > 0) {
exec('ufw delete allow '.$port.'/udp');
$app->log('ufw delete allow '.$port.'/udp',LOGLEVEL_DEBUG);
sleep(1);
}
}
/*
if($tcp_ports_new != $tcp_ports_old) {
exec('ufw allow to any proto tcp port '.$tcp_ports_new);
$app->log('ufw allow to any proto tcp port '.$tcp_ports_new,LOGLEVEL_DEBUG);
if($event_name == 'firewall_update') {
exec('ufw delete allow to any proto tcp port '.$tcp_ports_old);
$app->log('ufw delete allow to any proto tcp port '.$tcp_ports_old,LOGLEVEL_DEBUG);
}
}
if($udp_ports_new != $udp_ports_old) {
exec('ufw allow to any proto udp port '.$udp_ports_new);
$app->log('ufw allow to any proto udp port '.$udp_ports_new,LOGLEVEL_DEBUG);
if($event_name == 'firewall_update') {
exec('ufw delete allow to any proto udp port '.$udp_ports_old);
$app->log('ufw delete allow to any proto udp port '.$udp_ports_old,LOGLEVEL_DEBUG);
}
}
*/
if($data['new']['active'] == 'y') {
if($data['new']['active'] == $data['old']['active']) {
exec('ufw reload');
$app->log('Reloading the firewall',LOGLEVEL_DEBUG);
} else {
//* Ensure that bastille firewall is stopped
exec($conf['init_scripts'] . '/' . 'bastille-firewall stop');
if(@is_file('/etc/debian_version')) exec('update-rc.d -f bastille-firewall remove');
//* Start ufw firewall
exec('ufw --force enable');
$app->log('Starting the firewall',LOGLEVEL_DEBUG);
}
} else {
exec('ufw disable');
$app->log('Stopping the firewall',LOGLEVEL_DEBUG);
}
}
private function ufw_delete($event_name,$data) {
global $app, $conf;
$app->uses('system');
if(!$app->system->is_installed('ufw')) {
$app->log('UFW Firewall is not installed',LOGLEVEL_DEBUG);
return false;
}
$udp_ports = trim($udp_ports);
exec('ufw --force reset');
exec('ufw disable');
$app->log('Stopping the firewall',LOGLEVEL_DEBUG);
}
private function bastille_update($event_name,$data) {
global $app, $conf;
$app->uses('system');
$tcp_ports = $this->clean_ports($data['new']['tcp_port'],' ');
$udp_ports = $this->clean_ports($data['new']['udp_port'],' ');
$app->load('tpl');
$tpl = new tpl();
......@@ -120,6 +251,10 @@ class firewall_plugin {
unset($tpl);
if($data['new']['active'] == 'y') {
//* ensure that ufw firewall is disabled in case both firewalls are installed
if($app->system->is_installed('ufw')) {
exec('ufw disable');
}
exec($conf['init_scripts'] . '/' . 'bastille-firewall restart');
if(@is_file('/etc/debian_version')) exec('update-rc.d bastille-firewall defaults');
$app->log('Restarting the firewall',LOGLEVEL_DEBUG);
......@@ -132,7 +267,7 @@ class firewall_plugin {
}
function delete($event_name,$data) {
private function bastille_delete($event_name,$data) {
global $app, $conf;
exec($conf['init_scripts'] . '/' . 'bastille-firewall stop');
......@@ -142,6 +277,34 @@ class firewall_plugin {
}
private function clean_ports($portlist,$spacer) {
$ports = explode(',',$portlist);
$ports_out = '';
if(is_array($ports)) {
foreach($ports as $p) {
$p_clean = '';
if(strstr($p,':')) {
$p_parts = explode(':',$p);
$tmp_lower = intval($p_parts[0]);
$tmp_higher = intval($p_parts[1]);
if($tmp_lower > 0 && $tmp_lower <= 65535 && $tmp_higher > 0 && $tmp_higher <= 65535 && $tmp_lower < $tmp_higher) {
$p_clean = $tmp_lower.':'.$tmp_higher;
}
} else {
$tmp = intval($p);
if($tmp > 0 && $tmp <= 65535) {
$p_clean = $tmp;
}
}
if($p_clean != '') $ports_out .= $p_clean . $spacer;
}
}
return substr($ports_out,0,strlen($spacer)*-1);
}
} // end class
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment