Sophie

Sophie

distrib > Mandriva > mes5 > x86_64 > by-pkgid > 45723c51178a73df679c2a8284d8eeff > files > 25

shorewall-doc-4.0.15-0.2mdvmes5.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Manual Chains</title><link rel="stylesheet" href="html.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /></head><body><div class="article" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="id257527"></a>Manual Chains</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Tom</span> <span class="surname">Eastep</span></h3></div></div></div><div><p class="copyright">Copyright © 2007 Thomas M. Eastep</p></div><div><div class="legalnotice"><a id="id292634"></a><p>Permission is granted to copy, distribute and/or modify this
      document under the terms of the GNU Free Documentation License, Version
      1.2 or any later version published by the Free Software Foundation; with
      no Invariant Sections, with no Front-Cover, and with no Back-Cover
      Texts. A copy of the license is included in the section entitled
      “<span class="quote"><a class="ulink" href="GnuCopyright.htm" target="_self">GNU Free Documentation
      License</a></span>”.</p></div></div><div><p class="pubdate">2008/12/15</p></div></div><hr /></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="#Intro">Introduction</a></span></dt><dt><span class="section"><a href="#Example">Example</a></span></dt></dl></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="Intro"></a>Introduction</h2></div></div></div><p>Manual chains were introduced in Shorewall-perl 4.0.6; for Perl
    programmers, manual chains provide an alternative to Actions with
    extension scripts. Manual chains are chains which you create and populate
    yourself using the low-level functions in Shorewall::Chains.</p><p>Manual chains work in conjunction with the
    <em class="firstterm">compile</em> <a class="ulink" href="shorewall_extension_scripts.htm" target="_self">extension script</a> and <a class="ulink" href="configuration_file_basics.html#Embedded" target="_self">Embedded PERL
    scripts</a>. The general idea is like this:</p><div class="itemizedlist"><ul type="disc"><li><p>In the compile extension script, you define functions that you
        can call later using Embedded PERL. These functions create a
        <em class="firstterm">manual chain</em> using
        Shorewall::Chains::new_manual_chain() and populate it with rules using
        Shorewall::Chains::add_rule().</p></li><li><p>The functions also call Shorewall::Config::shorewall() to create
        and pass a rule to Shorewall. The TARGET in that rule is the name of
        the chain just created.</p></li><li><p>The functions defined in the compile script are called by
        embedded PERL statements. The arguments to those calls define the
        contents of the manual chains and the rule(s) passed back to Shorewall
        for normal processing.</p></li></ul></div></div><div class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="Example"></a>Example</h2></div></div></div><p>This example provides an alternative to the <a class="ulink" href="PortKnocking.html" target="_self">Port Knocking</a> example.</p><p>In this example, a Knock.pm module is created and placed in
    /etc/shorewall:</p><pre class="programlisting">package Knock;

use strict;
use warnings;
use base qw{Exporter};
use Carp;
use Shorewall::Chains;
use Scalar::Util qw{reftype};
use Shorewall::Config qw{shorewall};

our @EXPORT = qw{Knock};

my %recent_names;
my %chains_created;

sub scalar_or_array {
  my $arg = shift;
  my $name = shift;
  return () unless defined $arg;
  return ($arg) unless reftype($arg);
  return @$arg if reftype($arg) eq 'ARRAY';
  croak "Expecting argument '$name' to be scalar or array ref";
}

sub Knock {
  my $src = shift;
  my $dest = shift;
  my $args = shift;

  my $proto = $args-&gt;{proto} || 'tcp';
  my $seconds = $args-&gt;{seconds} || 60;
  my $original_dest = $args-&gt;{original_dest} || '-';
  my @target = scalar_or_array($args-&gt;{target}, 'target');
  my @knocker_ports = scalar_or_array($args-&gt;{knocker}, 'knocker');
  my @trap_ports = scalar_or_array($args-&gt;{trap}, 'trap');

  if (not defined $args-&gt;{name}) {
    # If you don't supply a name, then this must be the single-call
    # variant, so you have to specify all the arguments
    unless (scalar @target) {
      croak "No 'target' ports specified";
    }

    unless (scalar @knocker_ports) {
      croak "No 'knock' ports specified";
    }
  }

  # We'll need a unique name for the recent match list. Construct one
  # from the port and a serial number, if the user didn't supply one.
  my $name = $args-&gt;{name} || ($target[0] . '_' . ++$recent_names{$target[0]});
  $name = 'Knock' . $name;

  # We want one chain for all Knock rules that share a 'name' field
  my $chainref = $chains_created{$name};
  unless (defined $chainref) {
    $chainref = $chains_created{$name} = new_manual_chain($name);
  }
  
  # Logging
  if ($args-&gt;{log_level}) {
    foreach my $port (@target) {
      log_rule_limit($args-&gt;{log_level},
                     $chainref,
                     'Knock',
                     'ACCEPT',
                     '',
                     $args-&gt;{log_tag} || '',
                     'add',
                     "-p $proto --dport $port -m recent --rcheck --name $name"
                    );

      log_rule_limit($args-&gt;{log_level},
                     $chainref,
                     'Knock',
                     'DROP',
                     '',
                     $args-&gt;{log_tag} || '',
                     'add',
                     "-p $proto --dport ! $port"
                    );
    }
  }

  # Add the recent match rules to the manual chain
  foreach my $knock (@knocker_ports) {
    add_rule($chainref, "-p $proto --dport $knock -m recent --name $name --set -j DROP");
  }

  foreach my $trap (@trap_ports) {
    add_rule($chainref, "-p $proto --dport $trap -m recent --name $name --remove -j DROP");
  }

  foreach my $port (@target) {
    add_rule($chainref, "-p $proto --dport $port -m recent --rcheck --seconds $seconds --name $name -j ACCEPT");
  }

  # And add a rule to the main chain(s) to jump into the manual chain at the appropriate points
  my $all_dest_ports = join(',', @target, @knocker_ports, @trap_ports);
  shorewall "$chainref-&gt;{name} $src $dest $proto $all_dest_ports - $original_dest";

  return 1;
}

1;</pre><p>This simplifies /etc/shorewall/compile:</p><pre class="programlisting">use Knock;
1;</pre><p>The rule from the Port Knocking article:</p><pre class="programlisting">#ACTION          SOURCE            DEST           PROTO       DEST PORT(S)
SSHKnock         net               $FW            tcp         22,1599,1600,1601
</pre><p>becomes:</p><pre class="programlisting">PERL Knock 'net', 'loc:192.168.1.5', {target =&gt; 22, knocker =&gt; 1600, trap =&gt; [1599, 1601]};</pre><p>Similarly</p><pre class="programlisting">#ACTION          SOURCE            DEST            PROTO       DEST PORT(S)  SOURCE      ORIGINAL
#                                                                            PORT(S)     DEST
DNAT-            net               loc:192.168.1.5 tcp         22            -           206.124.146.178
SSHKnock         net               $FW             tcp         1599,1600,1601
SSHKnock         net               loc:192.168.1.5 tcp         22            -           206.124.146.178</pre><p>becomes:</p><pre class="programlisting">#ACTION          SOURCE            DEST            PROTO       DEST PORT(S)  SOURCE      ORIGINAL
#                                                                            PORT(S)     DEST
DNAT-            net               loc:192.168.1.5 tcp         22            -           206.124.146.178

PERL Knock 'net', '$FW', {name =&gt; 'SSH', knocker =&gt; 1600, trap =&gt; [1599, 1601]};
PERL Knock 'net', 'loc:192.168.1.5', {name =&gt; 'SSH', target =&gt; 22, original_dest =&gt; '206.124.136.178'};</pre></div></div></body></html>