Writing a simple plugin (fail2ban integration)

Discussion in 'Developers' Forum' started by phry, Sep 8, 2012.

  1. phry

    phry New Member

    Heyo,
    I wanted to log wrong logins into syslog so that fail2ban can parse it and ban the attacker's IP.
    - Yes, I know, ISPConfig has a similar feature but I want to do this nonetheless.
    - Yes, I know, ISPConfig logs wrong logins too, but only on DEBUG Level and I don't want the clutter. Neither do I want to change ispconfig files.

    So I wrote a quick plugin:
    /usr/local/ispconfig/server/plugins-available/login_fail2ban_plugin.inc.php
    PHP:
    <?php

    class login_fail2ban_plugin {

            var 
    $plugin_name 'login_fail2ban_plugin';
            var 
    $class_name  'login_fail2ban_plugin';

            
    //* This function is called during ispconfig installation to determine
            //  if a symlink shall be created for this plugin.
            
    function onInstall() {

                    return 
    true;

            }


            
    /*
                    This function is called when the plugin is loaded
            */

            
    function onLoad() {
                    global 
    $app;

                    
    /*
                    Register for the events
                    */
                    
    $app->plugins->registerEvent('login_failed',$this->plugin_name,'log_fail');
            }

            function 
    log_failed($event_name,$data) {
            
    openlog("ispconfig"LOG_PID LOG_PERRORLOG_LOCAL0);
            
    syslog(LOG_WARNING"Login failed for user $_POST['username'] on IP $_SERVER['REMOTE_ADDR']");
            }




    // end class

    ?>
    and then I created a symlink in /usr/local/ispconfig/server/plugins-enabled
    lrwxrwxrwx 1 ispconfig ispconfig 75 Sep 8 17:39 login_fail2ban_plugin.inc.php -> /usr/local/ispconfig/server/plugins-available/login_fail2ban_plugin.inc.php*

    But here's the catch: it doesn't load. I tried writing stuff into the onLoad function, too - is doesn't execute.
    Permissions and owner are set correctly, too:
    -rwxr-x--- 1 ispconfig ispconfig 766 Sep 8 17:29 plugins-available/login_fail2ban_plugin.inc.php

    Did I miss anything?
     
  2. till

    till Super Moderator Staff Member ISPConfig Developer

    You mix up the uspconfig server and the ispconfig interface. What you wrote above is a ispconfig server plugin, server plugins are used to configure services like apache, postfix etc. When you login to ispconfig, then you interact with the ispconfig interface and not the server, so if you want to react on failed logins, you will have tp write code for the interface and not the server. So your plugin can not work form a logical standpoint and it will never catch a interface event on the server.

    If you want to log actions of the interface, take a look at the ispconfig svn to see how the login function that you want to replicate is implemented there.
     
  3. phry

    phry New Member

    Oh, so I plugged into the wrong backend xD

    My attempt in itself (if it had been in the right place) should have been correct as login/index.php is raising the event:

    PHP:
          182                         //* Incorrect login - Username and password incorrect
          
    183                         $error $app->lng('error_user_password_incorrect');
          
    184                         if($app->db->errorMessage != ''$error .= '<br />'.$app->db->errorMessage != '';
          
    185
          186                         $app
    ->plugin->raiseEvent('login_failed',$this);
    Seems I just need another place to call my registerEvent.
    I tried it in ~ispconfig/interface/lib/plugins - but that also seems to be a wrong choice.

    Do you have any pointers for me?
     
  4. till

    till Super Moderator Staff Member ISPConfig Developer

    No, its not as the interface events are completely different from server events and what you wrote is a server plugin and not a interface plugin.

    Interface plugins are written differntly and ue different functions any libraries for the events, take a look at the files in ispconfig/interface/lib/plugins/ to get an idea how they work.
     
  5. phry

    phry New Member

    Umh, sorry, but see
    ~ispconfig/interface/lib/plugins/mail_user_filter_plugin.inc.php (that IS the folder you're pointing to?)

    PHP:
    <?php
    [...]
    class 
    mail_user_filter_plugin {

            var 
    $plugin_name 'mail_user_filter_plugin';
            var 
    $class_name 'mail_user_filter_plugin';

            
    /*
                    This function is called when the plugin is loaded
            */

            
    function onLoad() {
                    global 
    $app;

                    
    /*
                    Register for the events
                    */

                    
    [...]
                    
    $app->plugin->registerEvent('mail:mail_user_filter:on_after_update','mail_user_filter_plugin','mail_user_filter_edit');
                    [...]

            }

            function 
    mail_user_filter_edit($event_name,$page_form) {
                    global 
    $app$conf;
                [...]
     
            }

        [...]
    }
    I might be suffering from tunnel vision but that is the same as I'm doing with the same syntax within (now) the same path?
     
  6. phry

    phry New Member

    Oh, FFS, got my error.

    In server, it's $app->plugins->registerEvent
    In interface, it's $app->plugin->registerEvent

    And in case someone else wants to go on plugins: ispconfig stores your plugins in the session, onLoad will only be called once per session.
    That's quite a useful piece of information - happy cookie deleting!
     
  7. phry

    phry New Member

    And here's the final code if anyone wants to do the same:

    ~ispconfig/interface/lib/plugins/login_fail2ban_plugin.inc.php
    PHP:
    class login_fail2ban_plugin {

            var 
    $plugin_name 'login_fail2ban_plugin';
            var 
    $class_name  'login_fail2ban_plugin';

            
    /*
                    This function is called when the plugin is loaded
            */

            
    function onLoad() {
                    global 
    $app;
                    
    /*
                    Register for the events
                    */

                    
    $app->plugin->registerEvent('login_failed',$this->plugin_name,'log_fail');

            }

            function 
    log_fail($event_name,$data) {
                    
    openlog("ispconfig"LOG_PID LOG_PERRORLOG_LOCAL0);
                    
    syslog(LOG_WARNING"Login failed for user ".$_POST['username']." on IP ".$_SERVER['REMOTE_ADDR']);
            }




    // end class
    /etc/rsyslog.d/12-ispconfig.conf
    Code:
    if $programname == 'ispconfig' then /var/log/ispconfig.log
    
    restart rsyslog
    Code:
    service rsyslog restart
    
    /etc/fail2ban/filter.d/ispconfig.conf
    Code:
    [Definition]
    failregex = (.*) Login failed for user (.*) on IP <HOST>
    ignoreregex =
    

    test it
    Code:
    fail2ban-regex /var/log/ispconfig.log /etc/fail2ban/filter.d/ispconfig.conf
    
    and add a jail to your /etc/fail2ban/jail.conf:
    Code:
    [ispconfig]
    enabled  = true
    port     = http,https
    filter   = ispconfig
    logpath  = /var/log/ispconfig.log
    
    restart fail2ban

    Code:
    service fail2ban restart
    
    and be happy :)
     
    Last edited: Sep 9, 2012

Share This Page