Adding fwconsole commands and hooking them to framework functions

Hello,

After reading @jfinstrom’s article (http://wiki.freepbx.org/display/FOP/Adding+fwconsole+commands, I started to build a small additional fwconsole command.

The purpose:

  1. fix my predefined iptables rules and fail2ban settings as the freepbx start/stop functions flushes them.
  2. run this fwconsole command after the start/stop/restart functions (fwconsole start/stop/restart).

My first try was to write a hook to the start function (really simple and no fancy stuff).

The process itself:

  1. make a directory in your modules directory for your new command:
    mkdir /var/www/html/admin/modules/fixiptables

  2. make a Console sub directory in your fixiptables directory:
    mkdir /var/www/html/admin/modules/fixiptables/Console.

  3. prepapre your module.xml file in the module directory:
    <module> <rawname>fixiptables</rawname> <repo>standard</repo> <name>Fix Iptables Rules</name> <hooks> <framework class="Start" namespace="FreePBX\Console\Command"> <method callingMethod="postAsteriskHooks" class="Fixiptables">postAsteriskHooks</method> </framework> </hooks> </module>

  4. make your class file in the Console directory (Fixiptables.class.php):
    <?php //Namespace should be FreePBX\Console\Command namespace FreePBX\Console\Command; //Symfony stuff all needed add these use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; //progress bar use Symfony\Component\Console\Helper\ProgressBar; //Start class. Class name should be same as file name. Fixiptables.class.php class Fixiptables extends Command { //Declare component and your options. protected function configure(){ $this->setName('fixiptables') ->setDescription('Fixes the iptables rules') ->setHelp('Fixes the iptables rules'); } protected function execute(InputInterface $input, OutputInterface $output){ system('service iptables restart > /dev/null 2>&1'); system('service fail2ban restart > /dev/null 2>&1'); $output->writeln('iptables and fail2ban have been fixed'); } public function postAsteriskHooks($output) { system('service iptables restart > /dev/null 2>&1'); system('service fail2ban restart > /dev/null 2>&1'); $output->writeln('iptables and fail2ban have been fixed'); } } ?>

  5. Install the module: fwconsole ma install fixiptables

  6. verify that I can see my command: fwconsole | grep fixiptables.

  7. run the command manually: fwconsole fixiptables.

Everything works great when I run the new fwconsole command: fwconsole fixiptables.

My problem is that for some reason (I must be missing something) I cannot hook it to the start function of the fwconsole.
I tried implementing the code sample itself directly, but with no luck either hooking it to the start/stop functions.

Can you help me to hook it to the start/stop/restart framework functions?

Thank you,

Daniel Friedman
Trixton LTD.

That is because the module.xml is looking for the start/stop in the module class not the module’s console class.

1 Like

Hello @GameGamer43,

Thank you for your prompt response, but I fail to understand what do I need to do now in the module.xml file. I changed the namespace of the postasterisk hooks to this:

    <module>
    <rawname>fixiptables</rawname>
    <repo>standard</repo>
    <name>Fix Iptables Rules</name>

    <hooks>
            <framework class="Start" namespace="FreePBX\Console\Command">
                    <method callingMethod="postAsteriskHooks" class="Fixiptables" namespace="Freepbx\modules">postAsteriskHooks</method>
            </framework>
    </hooks>

    </module>

Do I need to write another class that implements the BMO class? or can I still use the class that I declared in my Console directory?

Thank you,

Daniel Friedman
Trixton LTD.

Hello @GameGamer43,

I wrote another class in the module directory that implements the BMO module. The Console class file is working as I need. Here is the module.xml that hooks to the start/stop framework functions:

module.xml

<module>
<rawname>fixiptables</rawname>
<repo>standard</repo>
<name>Fix Iptables Rules</name>

<hooks>
        <framework class="Start" namespace="FreePBX\Console\Command">
                <method callingMethod="postAsteriskHooks" class="Fixiptables" namespace="Freepbx\modules">startAsteriskHooks</method>
        </framework>
        <framework class="Stop" namespace="FreePBX\Console\Command">
                <method callingMethod="postAsteriskHooks" class="Fixiptables" namespace="Freepbx\modules">stopAsteriskHooks</method>
        </framework>
</hooks>

</module>

Here is the Fixiptables.class.php (the hook to the start/stop framework functions)

<?php
namespace FreePBX\modules;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
//progress bar
use Symfony\Component\Console\Helper\ProgressBar;

class Fixiptables implements \BMO {

public function __construct($freepbx = null) {
                if ($freepbx == null) {
                        throw new \Exception("Not given a FreePBX Object");
                }
                $this->freepbx = $freepbx;
                $this->db = $freepbx->Database;
                $this->userman = $freepbx->Userman;
  }


public function install() {
  }

public function uninstall() {
  }

public function backup() {
  return false;
  }

public function restore($backup=null) {
  return false;
  }

public function startAsteriskHooks($output=null) {
  $pid_fail2ban = system("pidof -x fail2ban-server &");
  system("kill -9 $pid_fail2ban");
  system("nohup service iptables restart > /dev/null 2>&1 && wait");
  system("nohup service fail2ban start > /dev/null 2>&1");
  $output->writeln('Module Start: iptables and fail2ban have been fixed');
  return false;
  }

public function stopAsteriskHooks($output=null) {
  $pid_fail2ban = system("pidof -x fail2ban-server &");
  system("kill -9 $pid_fail2ban");
  system("iptables-restore < /etc/sysconfig/iptables > /dev/null 2>&1");
  system("service fail2ban start > /dev/null 2>&1");
  $output->writeln('Module Stop: iptables and fail2ban have been fixed');
  return false;
  }

}

?>

Here is the Fixiptables.class.php file in the Console directory:

<?php
//Namespace should be FreePBX\Console\Command
namespace FreePBX\Console\Command;
//Symfony stuff all needed add these
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

//Start class. Class name should be same as file name. Fixiptables.class.php
class Fixiptables extends Command {
  //Declare component and your options.
  protected function configure(){
  $this->setName('fixiptables')
  ->setDescription('Fixes the iptables rules')
  ->setHelp('Fixes the iptables rules');
  }

protected function execute(InputInterface $input, OutputInterface $output){
  system('service iptables restart > /dev/null 2>&1');
  system('service fail2ban restart > /dev/null 2>&1');
  $output->writeln('Console: iptables and fail2ban have been fixed');
  }

}
?>

Everything is working quite well now, but my problem is that I want to run this hook as the last action. How can I loop through all the regular start/stop hooks to run the fixiptables hook as the last one?

Thank you,

Daniel Friedman
Trixton LTD.

<module>
<rawname>fixiptables</rawname>
<repo>standard</repo>
<name>Fix Iptables Rules</name>

<hooks>
        <framework class="Start" namespace="FreePBX\Console\Command" priority="900">
                <method callingMethod="postAsteriskHooks" class="Fixiptables" namespace="Freepbx\modules">startAsteriskHooks</method>
        </framework>
        <framework class="Stop" namespace="FreePBX\Console\Command"  priority="900">
                <method callingMethod="postAsteriskHooks" class="Fixiptables" namespace="Freepbx\modules">stopAsteriskHooks</method>
        </framework>
</hooks>

</module>

Hello @tm1000,

The priority attribute solved my problem. Now the module is hooked up to the start/stop framework functions and it is running at the end of the other functions.

Thank you,

Daniel Friedman
Trixon LTD.

Hello everyone,

I am attaching the fixiptables module if anyone would like to use it.

you can use if manually: fwconsole fixiptables or use it with the fwconsole start/stop/restart

You can download it from the web if you want to install it through the local modules management section.
This is the link to it: http://www.3xton.com/freepbx-modules/fixiptables.tar.gz

Thank you,

Daniel Friedman
Trixton LTD.

1 Like

If your goal is to share your effort with other users, then it really needs licensing details included in the tarball. Also it is conventional to put work like this on github where it can be searched and found by users who can use it, as opposed to a tarball on an obscure website.

2 Likes

I have removed the module link as there is no licensing.

Hello @tm1000,

This module is intended to be an open source module (AGPLv3).
I added the License info to the module (<license>AGPLv3</license>).
If this is satisfying, please put back my link to my post. You can check my module.xml in the same link.

Thank you,

Daniel Friedman
Trixton LTD.

1 Like

Done…