Forum Discussion

Gabor_Torok_937's avatar
Gabor_Torok_937
Icon for Nimbostratus rankNimbostratus
Feb 08, 2006

Blacklisting with iRule + iControl

Hi,

 

 

We'd like to introduce a blacklisting feature on our redundant F5 devices as follows:

 

- We've created an external data group that can be updated whenever the content of blacklist has changed,

 

- We've added an iRule to our virtual server that does the following:

 

. It gets triggered when CLIENTSSL_HANDSHAKE,

 

. It checks if the certificate serial number of the clien is on the blacklist

 

. If it's on the blacklist it rejects the connection,

 

. If it's not on the blacklist it does nothing.

 

- We're planning to use upload_file method from System/ConfigSync interface for updating the blacklist.

 

 

I have two questions:

 

1.) We've noticed that using the aforementioned method is not considered as a configuration change. Consequently, the data group content is not read by F5 system automatically. How can we let the system know that it's time to re-read the content of an external data group so that our iRule will always have an up-to-date array of certificate serial numbers?

 

 

2.) How can we sync the two devices when updating the data group only on one of them? Is there such an API that makes it possible? Remember, uploading a file is seemingly not treated as a configuration change. Or shall we use brute force and upload the file to both devices? That doesn't sound a nice solution, though seems to be efficient.

 

 

Thanks for your help in advance,

 

 

Tote

5 Replies

  • You are correct that the file upload command will not signal a reload of the configuration. You'll have to make one more call to tell the configuration to reload the file. Once you have reloaded the file, just use the LocalLB::Class::set_external_file_name() method with the existing file name. This will signal the internal system to reload the contents of the file.

     

     

    As for your question about syncing the files, I'll have to check on that one for you and let you know.

     

     

    Here's some perl code that I used to verify the reloading of the class. Hope it helps.

     

     

    !/usr/bin/perl
    ----------------------------------------------------------------------------
     File: pingClass.pl
    ----------------------------------------------------------------------------
     The contents of this file are subject to the iControl Public License
     Version 4.5 (the "License"); you may not use this file except in
     compliance with the License. You may obtain a copy of the License at
     http://www.f5.com/.
     Software distributed under the License is distributed on an "AS IS"
     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
     the License for the specific language governing rights and limitations
     under the License.
     The Original Code is iControl Code and related documentation
     distributed by F5.
     The Initial Developer of the Original Code is F5 Networks,
     Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2003 F5 Networks,
     Inc. All Rights Reserved.  iControl (TM) is a registered trademark of F5 Networks, Inc.
     Alternatively, the contents of this file may be used under the terms
     of the GNU General Public License (the "GPL"), in which case the
     provisions of GPL are applicable instead of those above.  If you wish
     to allow use of your version of this file only under the terms of the
     GPL and not to allow others to use your version of this file under the
     License, indicate your decision by deleting the provisions above and
     replace them with the notice and other provisions required by the GPL.
     If you do not delete the provisions above, a recipient may use your
     version of this file under either the License or the GPL.
    ----------------------------------------------------------------------------
    use SOAP::Lite + trace => qw(method debug);
    use SOAP::Lite;
    ----------------------------------------------------------------------------
     Validate Arguments
    ----------------------------------------------------------------------------
    my $sHost = $ARGV[0];
    my $sPort = $ARGV[1];
    my $sUID = $ARGV[2];
    my $sPWD = $ARGV[3];
    my $sClass = $ARGV[4];
    my $sProtocol = "https";
    sub usage()
    {
      die ("Usage: pingClass.pl host port uid pwd [classname] \n");
    }
    if ( ($sHost eq "") or ($sPort eq "") or ($sUID eq "") or ($sPWD eq "") )
    {
      usage();
    }
    if ( ("80" eq $sPort) or ("8080" eq $sPort) )
    {
      $sProtocol = "http";
    }
    ----------------------------------------------------------------------------
     Transport Information
    ----------------------------------------------------------------------------
    sub SOAP::Transport::HTTP::Client::get_basic_credentials
    {
      return "$sUID" => "$sPWD";
    }
    ----------------------------------------------------------------------------
     support for custom enum types
    ----------------------------------------------------------------------------
    sub SOAP::Deserializer::typecast
    {
      my ($self, $value, $name, $attrs, $children, $type) = @_;
      my $retval = undef;
      if ( "{urn:iControl}Class.ClassType" == $type )
      {
        $retval = $value;
      }
      return $retval;
    }
    $Class = SOAP::Lite
      -> uri('urn:iControl:LocalLB/Class')
      -> readable(1)
      -> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi");
    ----------------------------------------------------------------------------
     Main program logic
    ----------------------------------------------------------------------------
    if ( "" eq $sClass )
    {
      &listClasses();
    }
    else
    {
      &pingClass($sClass);
    }
    ----------------------------------------------------------------------------
     sub listClasses
    ----------------------------------------------------------------------------
    sub listClasses()
    {
      $soapResponse = $Class->get_external_class_list();
      &checkResponse($soapResponse);
      @MetaInformationList = @{$soapResponse->result};
      foreach $MetaInformation (@MetaInformationList)
      {
        $class_name = $MetaInformation->{"class_name"};
        $class_type = $MetaInformation->{"class_type"};
        $file_name = $MetaInformation->{"file_name"};
        $file_mode = $MetaInformation->{"file_mode"};
        $file_format = $MetaInformation->{"file_format"};
        print "Class Name: $class_name\n";
        print "      Type: $class_type\n";
        print "      File: $file_name\n";
        print "      Mode: $file_mode\n";
        print "    Format: $file_format\n";
      }
    }
    ----------------------------------------------------------------------------
     sub pingClass
    ----------------------------------------------------------------------------
    sub pingClass()
    {
      ($class) = (@_);
      
      $file_name = &getFileNameFromClass($class);
      if ( "" ne $file_name )
      {
        $soapResponse = $Class->set_external_class_file_name
        (
          SOAP::Data->name(class_names => [$class]),
          SOAP::Data->name(file_names => [$file_name])
        );
        &checkResponse($soapResponse);
        print "class $class successfully pinged\n";
      }
      else
      {
        print "Invalid class: $class\n";
      }
    }
    ----------------------------------------------------------------------------
     sub getFileNameFromClass
    ----------------------------------------------------------------------------
    sub getFileNameFromClass()
    {
      ($class) = (@_);
      $soapResponse = $Class->get_external_class_file_name
      (
        SOAP::Data->name(class_names => [$class])
      );
      &checkResponse($soapResponse);
      
      @file_names = @{$soapResponse->result};
      $file_name = @file_names[0];
      return $file_name;
    }
    ----------------------------------------------------------------------------
     checkResponse makes sure the error isn't a SOAP error
    ----------------------------------------------------------------------------
    sub checkResponse()
    {
      my ($soapResponse) = (@_);
      if ( $soapResponse->fault )
      {
        print $soapResponse->faultcode, " ", $soapResponse->faultstring, "\n";
        exit();
      }
    }

     

     

    -Joe
  • Thanks Joe! Did you have time to find out how we could sync our two F5s after updating the blacklist?

     

     

    Tote
  • Fine. We can do that, it's hopefully not a too big "penalty" for us.

     

     

    Btw, we store our file in neither aforementioned directory. Instead, we've created our own dir in the root that contains the file. Does it have any impact on the use of set_external_file_name method? I mean if this method presumes that the file to be reloaded is under /var/class/ directory, then we should rather put our file there.

     

     

    Thanks,

     

     

    Tote
  • I believe that the configuration won't load a class pointing to an external file unless it is present in either the "/config" or "/var/class" directories.

     

     

    -Joe
  • Okay. Just for safety's sake, let's put everything clear. Joe (or anyone else), would you please confirm that my assumptions are correct and I have not misunderstood anything from your responses.

     

     

    1.) Even though we could keep our external data group virtually everywhere, in order for uploading work it should be put under /var/class directory.

     

     

    2.) Joe, you were referring to a non-existing method name, set_external_file_name. I've checked the iControl SDK and I found a method named set_external_class_file_name. Note the word in bold. I guess it's the one we should use in our system, right?

     

     

    3.) Finally, the directory, /var/class, does not yet exist. I can naturally create this directory and put our data group file here, just want to be sure that it's not a problem.

     

     

    Thanks,

     

     

    Tote