<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<article>
  <!--$Id$-->

  <articleinfo>
    <title>Port Knocking and Other Uses of 'Recent Match'</title>

    <authorgroup>
      <author>
        <firstname>Tom</firstname>

        <surname>Eastep</surname>
      </author>
    </authorgroup>

    <pubdate><?dbtimestamp format="Y/m/d"?></pubdate>

    <copyright>
      <year>2005</year>

      <year>2006</year>

      <year>2009</year>

      <holder>Thomas M. Eastep</holder>
    </copyright>

    <legalnotice>
      <para>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
      <quote><ulink url="GnuCopyright.htm">GNU Free Documentation
      License</ulink></quote>.</para>
    </legalnotice>
  </articleinfo>

  <note>
    <para>The feature described in this article require '<ulink
    url="http://snowman.net/projects/ipt_recent/">Recent Match</ulink>' in
    your iptables and kernel. See the output of <command>shorewall show
    capabilities</command> to see if you have that match.</para>
  </note>

  <section id="What">
    <title>What is Port Knocking?</title>

    <para>Port knocking is a technique whereby attempting to connect to port A
    enables access to port B from that same host. For the example on which
    this article is based, see <ulink
    url="http://www.soloport.com/iptables.html">http://www.soloport.com/iptables.html</ulink>
    which should be considered to be part of this documentation.</para>
  </section>

  <section id="How">
    <title>Implementing Port Knocking in Shorewall</title>

    <para>In order to implement this solution, your iptables and kernel must
    support the 'recent match' extension (see <ulink url="FAQ.htm#faq42">FAQ
    42</ulink>).</para>

    <para>In this example:</para>

    <orderedlist>
      <listitem>
        <para>Attempting to connect to port 1600 enables SSH access. Access is
        enabled for 60 seconds.</para>
      </listitem>

      <listitem>
        <para>Attempting to connect to port 1601 disables SSH access (note
        that in the article linked above, attempting to connect to port 1599
        also disables access. This is an port scan defence as explained in the
        article).</para>
      </listitem>
    </orderedlist>

    <para>To implement that approach:</para>

    <orderedlist>
      <listitem>
        <para>Add an action named SSHKnock (see the <ulink
        url="Actions.html">Action documentation</ulink>). Leave the
        <filename>action.SSHKnock</filename> file empty.</para>
      </listitem>

      <listitem>
        <para>Create /etc/shorewall/SSHKnock with the following
        contents.<programlisting>use Shorewall::Chains;

if ( $level ) {
    log_rule_limit( $level, 
                    $chainref, 
                    'SSHKnock',
                    'ACCEPT',
                    '',
                    $tag,
                    'add',
                    '-p tcp --dport 22   -m recent --rcheck --name SSH ' );

    log_rule_limit( $level,
                    $chainref,
                    'SSHKnock',
                    'DROP',
                    '',
                    $tag,
                    'add',
                    '-p tcp ! --dport 22 ' );
}

add_rule( $chainref, '-p tcp --dport 22   -m recent --rcheck --seconds 60 --name SSH          -j ACCEPT' );
add_rule( $chainref, '-p tcp --dport 1599 -m recent                       --name SSH --remove -j DROP' );
add_rule( $chainref, '-p tcp --dport 1600 -m recent                       --name SSH --set    -j DROP' );
add_rule( $chainref, '-p tcp --dport 1601 -m recent                       --name SSH --remove -j DROP' );

1;</programlisting></para>
      </listitem>

      <listitem>
        <para>Now if you want to protect SSH access to the firewall from the
        Internet, add this rule in
        <filename>/etc/shorewall/rules</filename>:</para>

        <programlisting>#ACTION          SOURCE            DEST           PROTO       DEST PORT(S)
SSHKnock         net               $FW            tcp         22,1599,1600,1601</programlisting>

        <para>If you want to log the DROPs and ACCEPTs done by SSHKnock, you
        can just add a log level as in:</para>

        <programlisting>#ACTION          SOURCE            DEST           PROTO       DEST PORT(S)
SSHKnock:info    net               $FW            tcp         22,1599,1600,1601</programlisting>
      </listitem>

      <listitem>
        <para>Assume that you forward port 22 from external IP address
        206.124.146.178 to internal system 192.168.1.5. In
        /etc/shorewall/rules:</para>

        <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</programlisting>

        <note>
          <para>You can use SSHKnock with DNAT on earlier releases provided
          that you omit the ORIGINAL DEST entry on the second SSHKnock rule.
          This rule will be quite secure provided that you specify
          'routefilter' on your external interface and have
          NULL_ROUTE_RFC1918=Yes in
          <filename>shorewall.conf</filename>.</para>
        </note>
      </listitem>
    </orderedlist>

    <para>For another way to implement Port Knocking, see the <ulink
    url="ManualChains.html">Manual Chain</ulink> documentation.</para>
  </section>

  <section id="Limit">
    <title>Limiting Per-IP Connection Rate</title>

    <para>This information has been moved to the<ulink
    url="Actions.html#Limit"> Actions article</ulink>.</para>
  </section>
</article>