Changeset 1058

Show
Ignore:
Timestamp:
05/21/08 01:01:20 (6 months ago)
Author:
mbr
Message:

- Added two new port randomization options. The first instructs the

fwknop client to select a random port between 10,000 and 65,535 as the
destination port over which to send an SPA packet. This feature is
enabled with a new command line argument "--rand-port" like so:

$ fwknop -A tcp/22 --rand-port -R -D 11.1.1.1

On the fwknopd server side, the default PCAP_FILTER setting of "udp port
62201" should be changed to "udp dst portrange 10000-65535" so that
fwknopd can sniff SPA packets that are sent over randomized destination
ports. Randomizing the destination port makes it more difficult to
write IDS signatures to detect fwknop SPA communications.

The second port randomization technique uses a new SPA message type to
tell the fwknopd daemon to create a NAT rule for access to a local
socket via the iptables INPUT chain. This allows an SSH client to meet
the local SSHD daemon running on the fwknopd server system by SSH'ing to
the random port. This functionality is implemented via a new command
line argument "--Nat-access" on the fwknop command line.

- Bugfix to add a check for "keep-state" in ipfw policies in addition to

the existing "check-state" check (noticed by Sebastien Jeanquier).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • fwknop/trunk/ChangeLog

    r1046 r1058  
     1fwknop-1.9.4 (05//2008): 
     2    - Added the ability to specify the port that SPA packets are sent over 
     3      with the fwknop client by using the syntax "<host|IP>:<port>".  So, for 
     4      example, to have the client send an SPA packet to 11.1.1.1 over UDP port 
     5      12345 (instead of the default of 62201), one could use the following 
     6      command: 
     7 
     8      $ fwknop -A tcp/22 -R -D 11.1.1.1:12345 
     9 
     10    - Added two new port randomization options.  The first instructs the 
     11      fwknop client to select a random port between 10,000 and 65,535 as the 
     12      destination port over which to send an SPA packet.  This feature is 
     13      enabled with a new command line argument "--rand-port" like so: 
     14 
     15      $ fwknop -A tcp/22 --rand-port -R -D 11.1.1.1 
     16 
     17      On the fwknopd server side, the default PCAP_FILTER setting of "udp port 
     18      62201" should be changed to "udp dst portrange 10000-65535" so that 
     19      fwknopd can sniff SPA packets that are sent over randomized destination 
     20      ports.  Randomizing the destination port makes it more difficult to 
     21      write IDS signatures to detect fwknop SPA communications. 
     22 
     23      The second port randomization technique uses a new SPA message type to 
     24      tell the fwknopd daemon to create a NAT rule for access to a local 
     25      socket via the iptables INPUT chain.  This allows an SSH client to meet 
     26      the local SSHD daemon running on the fwknopd server system by SSH'ing to 
     27      the random port.  This functionality is implemented via a new command 
     28      line argument "--Nat-access" on the fwknop command line. 
     29 
     30    - Bugfix to add a check for "keep-state" in ipfw policies in addition to 
     31      the existing "check-state" check (noticed by Sebastien Jeanquier). 
     32    - Updated the install.pl script to try to determine the OS type as early 
     33      as possible during the install process. 
     34 
    135fwknop-1.9.3 (04/05/2008): 
    236    - Added MASQUERADE and SNAT support to complement inbound DNAT connections 
  • fwknop/trunk/fwknop

    r1046 r1058  
    100100my $pcap_sleep_interval  = 1;  ### seconds 
    101101my $knock_dst_pre_resolve = ''; 
     102my $rand_port     = 0;  ### for SPA packet destination port 
     103my $NAT_rand_port = 0;  ### for randomized access based on 
     104                        ### NAT rules (e.g. ssh -p <randport>). 
     105my $NAT_local = 0; ### Flag for forwarding a port to local socket. 
    102106 
    103107### User agent for contacting http://www.whatismyip.org/, (can 
     
    116120my $SPA_COMMAND_MODE = 0; 
    117121 
    118 ### FORWARD ACCESS message: 
     122### NAT ACCESS message: 
    119123###     random data : user : client_timestamp : client_version : \ 
    120124###     type (2) : access_request : NAT_info : message digest 
    121 my $SPA_FORWARD_ACCESS_MODE = 2; 
     125my $SPA_NAT_ACCESS_MODE = 2; 
    122126 
    123127### ACCESS message with client-defined firewall timeout: 
     
    126130my $SPA_CLIENT_TIMEOUT_ACCESS_MODE = 3; 
    127131 
    128 ### FORWARD ACCESS message with client-defined firewall timeout: 
     132### NAT ACCESS message with client-defined firewall timeout: 
    129133###     random data : user : client_timestamp : client_version : \ 
    130134###     type (4) : access_request : NAT_info : timeout : message digest 
    131 my $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE = 4; 
     135my $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE = 4; 
     136 
     137### local NAT ACCESS message: 
     138###     random data : user : client_timestamp : client_version : \ 
     139###     type (5) : access_request : NAT_info : message digest 
     140my $SPA_LOCAL_NAT_ACCESS_MODE = 5; 
     141 
     142### local NAT ACCESS message with client-defined firewall timeout: 
     143###     random data : user : client_timestamp : client_version : \ 
     144###     type (6) : access_request : NAT_info : timeout : message digest 
     145my $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE = 6; 
    132146 
    133147### default time values 
     
    141155my $digest_type = $SHA256_DIGEST; ### default 
    142156my $cmdl_digest_alg = ''; 
     157 
     158### default destination port; you can change with --Server-port, 
     159### --rand-port, or by appending the ":<port>" syntax to the 
     160## destination host 
     161my $DEFAULT_PORT = 62201; 
    143162 
    144163### default to root (client must run as root in this mode) 
     
    163182my $enc_rotate_proto  = 0; 
    164183my $get_key_file      = '';  ### get key from file 
    165 my $enc_pcap_port     = 62201;  ### default pcap port 
     184my $enc_pcap_port     = $DEFAULT_PORT; 
    166185my $access_str        = ''; 
    167 my $forward_access_str = '';  ### for access through the iptables FORWARD chain 
     186my $NAT_access_str = '';  ### for access through the iptables FORWARD chain 
    168187 
    169188### packet counters 
     
    217236    if ($spoof_src and $spa_established_tcp); 
    218237 
    219 die "[*] Server auth method not supported in FORWARD access mode.\n" 
    220     if $server_auth_method and $forward_access_str; 
     238die "[*] Server auth method not supported in NAT access mode.\n" 
     239    if $server_auth_method and $NAT_access_str; 
    221240 
    222241&set_digest_type() if $cmdl_digest_alg; 
     
    234253### save a copy 
    235254$knock_dst_pre_resolve = $knock_dst; 
     255 
     256if ($rand_port and $enc_pcap_port != $DEFAULT_PORT) { 
     257    die "[*] Cannot use --Server-port and --rand-port at the same time"; 
     258} 
     259 
     260### allow for ":<port>" extension to -D arg 
     261if ($knock_dst =~ /(.*):(\d+)/) { 
     262    $knock_dst     = $1; 
     263    $enc_pcap_port = $2; 
     264 
     265    die "[*] Cannot use --rand-port with a manually specified -D <host>:<port>" 
     266        if $rand_port; 
     267} 
     268 
     269if ($rand_port) { 
     270    ### send the SPA packet over a random port between 10,000 and 65535 
     271    $enc_pcap_port = &rand_port(); 
     272} 
    236273 
    237274if ($run_last_args or $show_last_cmd) { 
     
    270307 
    271308if ($debug) { 
    272     print "[+] ***DEBUG*** Starting fwknop client ($print_mode mode)...\n"; 
     309    print "\n[+] ***DEBUG*** Starting fwknop client ($print_mode mode)...\n"; 
    273310} else { 
    274     print "[+] Starting fwknop client ($print_mode mode)...\n" 
     311    print "\n[+] Starting fwknop client ($print_mode mode)...\n" 
    275312        unless $quiet; 
    276313} 
     
    291328 
    292329&validate_access_str() if $access_str; 
    293 &validate_forward_access_str() if $forward_access_str; 
     330&validate_NAT_access_str() if $NAT_access_str; 
    294331 
    295332if (lc($server_mode) eq 'pcap' or lc($server_mode) eq 'knock') { 
     
    400437    #    0 => command mode / command to execute 
    401438    #    1 => access mode / IP,proto,port 
    402     #    2 => forward access mode / IP,proto,port / internalIP,externalNATPort 
     439    #    2 => nat access mode / IP,proto,port / internalIP,externalNATPort 
    403440    #  (optional) server_auth (post 0.9.2 release) 
    404441    #  message digest (SHA256 / SHA1 / MD5 ) 
     
    431468    $msg .= &SPA_message(); 
    432469 
    433     ### append FORWARD access requirement (optional) 
    434     $msg .= &SPA_forward_access(); 
     470    ### append NAT access requirement (optional) 
     471    $msg .= &SPA_nat_access(); 
    435472 
    436473    ### append server authentication method (optional) 
     
    501538            unless $quiet; 
    502539        return ':' . $SPA_COMMAND_MODE; 
    503     } elsif ($forward_access_str) { 
    504         if ($cmdl_fw_timeout > 0) { 
    505             print "        Type:           " . 
    506                 "$SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE ", 
    507                 "(FORWARD client-timeout access mode)\n" unless $quiet; 
    508             return ':' . $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE; 
     540    } elsif ($NAT_access_str) { 
     541        if ($NAT_local) { 
     542            if ($cmdl_fw_timeout > 0) { 
     543                print "        Type:           " . 
     544                    "$SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE ", 
     545                    "(Local NAT client-timeout access mode)\n" unless $quiet; 
     546                return ':' . $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE; 
     547            } else { 
     548                print "        Type:           $SPA_LOCAL_NAT_ACCESS_MODE ", 
     549                    "(Local NAT access mode)\n" unless $quiet; 
     550                return ':' . $SPA_LOCAL_NAT_ACCESS_MODE; 
     551            } 
    509552        } else { 
    510             print "        Type:           $SPA_FORWARD_ACCESS_MODE ", 
    511                 "(FORWARD access mode)\n" unless $quiet; 
    512             return ':' . $SPA_FORWARD_ACCESS_MODE; 
     553            if ($cmdl_fw_timeout > 0) { 
     554                print "        Type:           " . 
     555                    "$SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE ", 
     556                    "(NAT client-timeout access mode)\n" unless $quiet; 
     557                return ':' . $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE; 
     558            } else { 
     559                print "        Type:           $SPA_NAT_ACCESS_MODE ", 
     560                    "(NAT access mode)\n" unless $quiet; 
     561                return ':' . $SPA_NAT_ACCESS_MODE; 
     562            } 
    513563        } 
    514564    } 
     
    563613} 
    564614 
    565 sub SPA_forward_access() { 
    566     if ($forward_access_str) { 
    567         print "        Forward access: $forward_access_str\n" 
     615sub SPA_nat_access() { 
     616    if ($NAT_access_str) { 
     617        print "        Forward access: $NAT_access_str\n" 
    568618            unless $quiet; 
    569         return ':' . encode_base64($forward_access_str, ''); 
     619        return ':' . encode_base64($NAT_access_str, ''); 
    570620    } 
    571621    return ''; 
     
    767817        print 
    768818"\n[+] Sending $msg_len byte message to $knock_dst over $spoof_proto", 
    769     "/$enc_pcap_port\n    (spoofed src ip: $spoof_src).\n" unless $quiet; 
     819    "/$enc_pcap_port\n    (spoofed src IP: $spoof_src).\n\n" unless $quiet; 
    770820        my $rand_src_port = int(rand(65535)); 
    771821        $rand_src_port = 65001 if $rand_src_port > 65535; 
     
    840890        if ($spa_established_tcp) {  ### useful for Tor 
    841891            print "\n[+] Sending $msg_len byte message to $knock_dst ", 
    842                 "over established tcp/$enc_pcap_port socket...\n
     892                "over established tcp/$enc_pcap_port socket...\n\n
    843893                unless $quiet; 
    844894 
     
    859909        } else { 
    860910            print "\n[+] Sending $msg_len byte message to $knock_dst ", 
    861                 "over udp/$enc_pcap_port...\n" unless $quiet; 
     911                "over udp/$enc_pcap_port...\n\n" unless $quiet; 
    862912 
    863913            if ($test_mode) { 
     
    13561406 
    13571407sub handle_command_line() { 
     1408 
    13581409    ### make Getopts case sensitive 
    13591410    Getopt::Long::Configure('no_ignore_case'); 
    13601411 
    1361     die "[-] Use --help for usage information.\n" unless GetOptions( 
     1412    die "[*] Use --help for usage information.\n" unless GetOptions( 
    13621413        'Server-port=i'  => \$enc_pcap_port, 
    13631414        'Server-mode=s'  => \$server_mode, 
     
    13661417        'Server-auth=s'  => \$server_auth_method, 
    13671418        'Spoof-src=s'    => \$spoof_src, 
     1419        'rand-port'      => \$rand_port, 
     1420        'NAT-rand-port'  => \$NAT_rand_port, 
     1421        'NAT-local'      => \$NAT_local, 
     1422        'NAT-access=s'   => \$NAT_access_str, 
    13681423        'Spoof-user=s'   => \$spoof_username, 
    13691424        'Spoof-proto=s'  => \$spoof_proto, 
     
    13821437        'gpg-agent-info=s'  => \$gpg_agent_info, 
    13831438        'quiet'             => \$quiet, 
    1384         'Forward-access=s'  => \$forward_access_str, 
     1439        'Forward-access=s'  => \$NAT_access_str, 
    13851440        'TCP-sock'       => \$spa_established_tcp, 
    13861441        'Access=s'       => \$access_str, 
     
    15091564} 
    15101565 
    1511 sub validate_forward_access_str() { 
    1512     $forward_access_str = lc($forward_access_str); 
    1513     unless ($forward_access_str =~ /^$ip_re,\d+$/) { 
    1514         die "[*] Must specify '<internal_IP>,<external_port>'"; 
     1566sub validate_NAT_access_str() { 
     1567    $NAT_access_str = lc($NAT_access_str); 
     1568 
     1569    if ($NAT_rand_port) { 
     1570        unless ($NAT_access_str =~ /^$ip_re$/) { 
     1571            die "[*] Must specify '<internal_IP>'"; 
     1572        } 
     1573 
     1574        ### append a random destination port (between 10,000 
     1575        ### and 65535); this is the port number that will be 
     1576        ### used on the SSH command line 
     1577        $NAT_access_str .= ',' . &rand_port(); 
     1578 
     1579    } else { 
     1580        unless ($NAT_access_str =~ /^$ip_re,\d+$/) { 
     1581            die "[*] Must specify '<internal_IP>,<external_port>'"; 
     1582        } 
    15151583    } 
    15161584    return; 
     
    15691637    print "\n"; 
    15701638    return; 
     1639} 
     1640 
     1641sub rand_port() { 
     1642    return 10000 + int(rand(55535)); 
    15711643} 
    15721644 
  • fwknop/trunk/fwknopd

    r1050 r1058  
    127127my $SPA_COMMAND_MODE = 0; 
    128128 
    129 ### FORWARD ACCESS message: 
     129### NAT ACCESS message: 
    130130###     random data :user : client_timestamp : client_version : \ 
    131131###     type (2) : access_request : NAT_info : digest 
    132 my $SPA_FORWARD_ACCESS_MODE = 2; 
     132my $SPA_NAT_ACCESS_MODE = 2; 
    133133 
    134134### ACCESS message with client-defined firewall timeout: 
     
    137137my $SPA_CLIENT_TIMEOUT_ACCESS_MODE = 3; 
    138138 
    139 ### FORWARD ACCESS message with client-defined firewall timeout: 
     139### NAT ACCESS message with client-defined firewall timeout: 
    140140###     random data :user : client_timestamp : client_version : \ 
    141141###     type (4) : access_request : NAT_info : timeout : digest 
    142 my $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE = 4; 
     142my $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE = 4; 
     143 
     144### local NAT ACCESS message: 
     145###     random data : user : client_timestamp : client_version : \ 
     146###     type (5) : access_request : NAT_info : message digest 
     147my $SPA_LOCAL_NAT_ACCESS_MODE = 5; 
     148 
     149### local NAT ACCESS message with client-defined firewall timeout: 
     150###     random data : user : client_timestamp : client_version : \ 
     151###     type (6) : access_request : NAT_info : timeout : message digest 
     152my $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE = 6; 
    143153 
    144154### minimum nummber of fields within a decrypted SPA packet 
     
    527537 
    528538            if ($msg_hr->{'action_type'} == $SPA_ACCESS_MODE 
    529                     or $msg_hr->{'action_type'} == $SPA_FORWARD_ACCESS_MODE 
    530                     or $msg_hr->{'action_type'} == $SPA_FORWARD_ACCESS_MODE 
    531                     or $msg_hr->{'action_type'} 
    532                         == $SPA_CLIENT_TIMEOUT_ACCESS_MODE 
    533                     or $msg_hr->{'action_type'} 
    534                         == $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE) { 
     539                    or $msg_hr->{'action_type'} == $SPA_NAT_ACCESS_MODE 
     540                    or $msg_hr->{'action_type'} == $SPA_LOCAL_NAT_ACCESS_MODE 
     541                    or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_ACCESS_MODE 
     542                    or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE 
     543                    or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE) { 
    535544 
    536545                if (&SPA_access($msg_hr, $src_ip, $decrypt_algo, 
     
    648657    } elsif ($msg_hr->{'action_type'} == $SPA_COMMAND_MODE) { 
    649658        print STDERR " (SPA_COMMAND_MODE)\n"; 
    650     } elsif ($msg_hr->{'action_type'} == $SPA_FORWARD_ACCESS_MODE) { 
    651         print STDERR " (SPA_FORWARD_ACCESS_MODE)\n"; 
     659    } elsif ($msg_hr->{'action_type'} == $SPA_NAT_ACCESS_MODE) { 
     660        print STDERR " (SPA_NAT_ACCESS_MODE)\n"; 
     661    } elsif ($msg_hr->{'action_type'} == $SPA_LOCAL_NAT_ACCESS_MODE) { 
     662        print STDERR " (SPA_LOCAL_NAT_ACCESS_MODE)\n"; 
    652663    } elsif ($msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_ACCESS_MODE) { 
    653664        print STDERR " (SPA_CLIENT_TIMEOUT_ACCESS_MODE)\n"; 
    654     } elsif ($msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE) { 
    655         print STDERR " (SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE)\n"; 
     665    } elsif ($msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE) { 
     666        print STDERR " (SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE)\n"; 
     667    } elsif ($msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE) { 
     668        print STDERR " (SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE)\n"; 
    656669    } 
    657670    printf STDERR "    %-16s %s\n", 
     
    659672 
    660673    if ($msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_ACCESS_MODE 
    661             or $msg_hr->{'action_type'} 
    662                 == $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE) { 
     674            or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE 
     675            or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE) { 
    663676        printf STDERR "    %-16s %s\n", 
    664677                'Client timeout:', $msg_hr->{'client_timeout'}; 
     
    671684            if ($debug) { 
    672685                printf STDERR "    %-16s %s", 'Server auth:', $server_auth_type; 
    673                 for (my $i=0; $i<length($server_auth_crypt_pw); $i++) { 
     686                for (my $i=0; $i < length($server_auth_crypt_pw); $i++) { 
    674687                    print STDERR '*'; 
    675688                } 
     
    678691        } 
    679692    } 
    680     if ($msg_hr->{'forward_info'}) { 
    681         printf STDERR "    %-16s %s\n", 'Forward info:', 
    682             $msg_hr->{'forward_info'}; 
     693    if ($msg_hr->{'nat_info'}) { 
     694        printf STDERR "    %-16s %s\n", 'NAT info:', 
     695            $msg_hr->{'nat_info'}; 
    683696    } 
    684697    printf STDERR "    %-16s %s\n", "$msg_hr->{'digest_str'} digest:", 
     
    750763        $digest, $access_hr) = @_; 
    751764 
    752     my $allow_src    = ''; 
    753     my %open_ports   = (); 
    754     my %forward_info = (); 
     765    my $allow_src  = ''; 
     766    my %open_ports = (); 
     767    my %nat_info  = (); 
    755768 
    756769    if ($access_hr->{'DISABLE_FW_ACCESS'}) { 
     
    762775 
    763776    if ($msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_ACCESS_MODE 
    764             or $msg_hr->{'action_type'} 
    765                 == $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE) { 
     777            or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE 
     778            or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE) { 
    766779 
    767780        if ($access_hr->{'PERMIT_CLIENT_TIMEOUT'}) { 
     
    857870 
    858871    ### handle SPA access through iptables FORWARD chain for 
    859     ### SPA_FORWARD_ACCESS_MODE messages 
     872    ### SPA_NAT_ACCESS_MODE messages (or through the INPUT chain for 
     873    ### SPA_LOCAL_NAT_ACCESS_MODE messages) 
    860874    ### iptables -t nat -A PREROUTING -p tcp -s <SPA_src> --dport 55000 \ 
    861875    ### -i eth0 -j DNAT --to 192.168.10.3:80 
    862     if ($msg_hr->{'forward_info'} 
    863                 and $msg_hr->{'forward_info'} =~ /($ip_re),(\d+)/) { 
     876    if ($msg_hr->{'nat_info'} 
     877                and $msg_hr->{'nat_info'} =~ /($ip_re),(\d+)/) { 
     878 
     879        %nat_info = ( 
     880            'internal_ip'   => $1, 
     881            'external_port' => $2, 
     882        ); 
     883 
    864884        unless ($config{'FIREWALL_TYPE'} eq 'iptables') { 
    865             &logr('[-]', "FORWARD access requested through non-iptables " . 
     885            &logr('[-]', "NAT access requested through non-iptables " . 
    866886                "firewall (SOURCE line num: ". 
    867887                "$access_hr->{'src_line_num'})", $NO_MAIL); 
    868888            return 0; 
    869889        } 
    870         unless ($access_hr->{'ENABLE_FORWARD_ACCESS'}) { 
    871             &logr('[-]', "FORWARD access requested through non-forward " . 
    872                 "access SOURCE block (SOURCE line num: ". 
    873                 "$access_hr->{'src_line_num'})", $NO_MAIL); 
    874             return 0; 
    875         } 
    876         %forward_info = ( 
    877             'internal_ip'   => $1, 
    878             'external_port' => $2, 
    879         ); 
    880  
    881         ### check to see if access is allowed to internal IP 
    882         unless (&is_ip_included($forward_info{'internal_ip'}, 
     890 
     891        if ($msg_hr->{'action_type'} == $SPA_NAT_ACCESS_MODE 
     892                or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE) { 
     893            unless ($access_hr->{'ENABLE_FORWARD_ACCESS'}) { 
     894                &logr('[-]', "FORWARD access requested through non-forward " . 
     895                    "access SOURCE block (SOURCE line num: ". 
     896                    "$access_hr->{'src_line_num'})", $NO_MAIL); 
     897                return 0; 
     898            } 
     899        } 
     900 
     901        ### check to see if access is allowed to internal IP (or a local IP 
     902        ### for NAT'd local connections) 
     903        unless (&is_ip_included($nat_info{'internal_ip'}, 
    883904                $access_hr->{'INTERNAL_NET_ACCESS'}, 
    884905                $access_hr->{'internal_net_exceptions'})) { 
    885             &logr('[-]', "FORWARD access to $forward_info{'internal_ip'} " . 
     906            &logr('[-]', "NAT access to $nat_info{'internal_ip'} " . 
    886907                "restricted (SOURCE line num: ". 
    887908                "$access_hr->{'src_line_num'})", $NO_MAIL); 
     
    940961 
    941962    ### grant access through the firewall 
    942     &grant_access($allow_src, \%forward_info, {}, \%open_ports, $access_hr); 
     963    &grant_access($allow_src, $msg_hr, \%nat_info, 
     964        {}, \%open_ports, $access_hr); 
    943965 
    944966    return 1; 
     
    11591181        'action'          => '', 
    11601182        'server_auth'     => '',  ### optional 
    1161         'forward_info'    => '',  ### optional 
     1183        'nat_info'        => '',  ### optional 
    11621184        'client_timeout'  => -1,  ### optional 
    11631185        'digest'          => '', 
     
    12231245        return 0, {} unless $fields[4] == $SPA_COMMAND_MODE 
    12241246                or $fields[4] == $SPA_ACCESS_MODE 
    1225                 or $fields[4] == $SPA_FORWARD_ACCESS_MODE 
     1247                or $fields[4] == $SPA_NAT_ACCESS_MODE 
    12261248                or $fields[4] == $SPA_CLIENT_TIMEOUT_ACCESS_MODE 
    1227                 or $fields[4] == $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE; 
     1249                or $fields[4] == $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE 
     1250                or $fields[4] == $SPA_LOCAL_NAT_ACCESS_MODE 
     1251                or $fields[4] == $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE; 
    12281252        $msg_hsh{'action_type'} = $fields[4]; 
    12291253    } else { 
     
    12421266        if ($msg_hsh{'numeric_version'} >= 190) { 
    12431267            my $found = 0; 
    1244             if ($msg_hsh{'action_type'} == $SPA_FORWARD_ACCESS_MODE) { 
     1268            if ($msg_hsh{'action_type'} == $SPA_NAT_ACCESS_MODE) { 
    12451269                if ($#fields == $SPA_MIN_PACKET_FIELDS+1) { 
    1246                     $msg_hsh{'forward_info'} = decode_base64($fields[6]); 
     1270                    $msg_hsh{'nat_info'} = decode_base64($fields[6]); 
    12471271                    $found = 1; 
    12481272                } 
     
    12531277                    $found = 1; 
    12541278                } elsif ($msg_hsh{'action_type'} 
    1255                             == $SPA_CLIENT_TIMEOUT_FORWARD_ACCESS_MODE) { 
     1279                            == $SPA_CLIENT_TIMEOUT_NAT_ACCESS_MODE) { 
    12561280                    $msg_hsh{'client_timeout'} = $fields[7]; 
    12571281                    $found = 1; 
     
    12871311            "$msg_hsh{'action'}"; 
    12881312 
    1289         if ($msg_hsh{'forward_info'}) { 
    1290             print STDERR ":$msg_hsh{'forward_info'}"; 
     1313        if ($msg_hsh{'nat_info'}) { 
     1314            print STDERR ":$msg_hsh{'nat_info'}"; 
    12911315        } 
    12921316 
     
    22922316 
    22932317sub grant_access() { 
    2294     my ($src, $forward_info_hr, $seq_hr, $open_ports_hr, $access_hr) = @_; 
     2318    my ($src, $nat_info_hr, $seq_hr, $open_ports_hr, $access_hr) = @_; 
    22952319 
    22962320    if ($config{'FIREWALL_TYPE'} eq 'iptables') { 
     
    22982322        ### iptables access; the destination IP is only used if access is 
    22992323        ### forwarded through the iptables policy 
    2300         &grant_ipt_access($src, $forward_info_hr, 
     2324        &grant_ipt_access($src, $nat_info_hr, 
    23012325                $seq_hr, $open_ports_hr, $access_hr); 
    23022326 
     
    23112335 
    23122336sub grant_ipt_access() { 
    2313     my ($src, $forward_info_hr, $seq_href, $open_ports_hr, $access_hr) = @_; 
     2337    my ($src, $msg_hr, $nat_info_hr, $seq_href, 
     2338            $open_ports_hr, $access_hr) = @_; 
    23142339 
    23152340    my @ipt_hrefs = (); 
    23162341    my $ipt = &get_iptables_chainmgr_obj(); 
    23172342 
    2318     if ($access_hr->{'ENABLE_FORWARD_ACCESS'}) { 
    2319         return unless defined $forward_info_hr->{'internal_ip'}; 
    2320         push @ipt_hrefs, \%ipt_forward; 
     2343    my $local_nat = 0; 
     2344    $local_nat = 1 if $msg_hr->{'action_type'} == $SPA_LOCAL_NAT_ACCESS_MODE 
     2345            or $msg_hr->{'action_type'} == $SPA_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MODE; 
     2346 
     2347    if ($access_hr->{'ENABLE_FORWARD_ACCESS'} or $local_nat) { 
     2348 
     2349        return unless defined $nat_info_hr->{'internal_ip'}; 
    23212350        push @ipt_hrefs, \%ipt_prerouting if %ipt_prerouting; 
    23222351        push @ipt_hrefs, \%ipt_postrouting if %ipt_postrouting; 
    2323         print STDERR localtime() . " [+] FORWARD access for $src ", 
    2324             "to internal IP: $forward_info_hr->{'internal_ip'}\n" 
    2325             if $debug; 
     2352 
     2353        if ($local_nat) { 
     2354            push @ipt_hrefs, \%ipt_input; 
     2355            print STDERR localtime() . " [+] INPUT NAT access for $src ", 
     2356                "to local IP: $nat_info_hr->{'internal_ip'}\n" 
     2357                if $debug; 
     2358        } else { 
     2359            push @ipt_hrefs, \%ipt_forward; 
     2360            print STDERR localtime() . " [+] FORWARD access for $src ", 
     2361                "to internal IP: $nat_info_hr->{'internal_ip'}\n" 
     2362                if $debug; 
     2363        } 
     2364 
    23262365    } else { 
    2327         return if defined $forward_info_hr->{'internal_ip'}; 
     2366        return if defined $nat_info_hr->{'internal_ip'}; 
    23282367        push @ipt_hrefs, \%ipt_input; 
    23292368        if ($access_hr->{'ENABLE_OUTPUT_ACCESS'}) { 
     
    23962435                    if ($target eq 'DNAT') { 
    23972436                        $extended_info{'to_ip'} 
    2398                             = $forward_info_hr->{'internal_ip'}; 
     2437                            = $nat_info_hr->{'internal_ip'}; 
    23992438                        $extended_info{'to_port'} = $dport; 
    24002439                        $extended_info{'d_port'} 
    2401                             = $forward_info_hr->{'external_port'}; 
    2402                         $nat_ip   = $forward_info_hr->{'internal_ip'}; 
     2440                            = $nat_info_hr->{'external_port'}; 
     2441                        $nat_ip   = $nat_info_hr->{'internal_ip'}; 
    24032442                        $nat_port = $dport; 
    2404                         $dport    = $forward_info_hr->{'external_port'}; 
     2443                        $dport    = $nat_info_hr->{'external_port'}; 
    24052444                    } elsif ($target eq 'SNAT') { 
    24062445                        $extended_info{'to_ip'} 
     
    25712610    while (<LIST>) { 
    25722611        if (/check-state/) { 
    2573             ### check-state means that ipfw builds "dynamic" rules against 
    2574             ### connections, and a subsequent rule can allow established 
    2575             ### connections to continue after the initial rule to accept 
    2576             ### an SSH connection is removed. 
     2612            ### from the ipfw man page: 
     2613            # check-state 
     2614            #    Checks the packet against the dynamic ruleset.  If a match is 
     2615            #    found, execute the action associated with the rule which gener- 
     2616            #    ated this dynamic rule, otherwise move to the next rule. 
     2617            #    Check-state rules do not have a body.  If no check-state rule is 
     2618            #    found, the dynamic ruleset is checked at the first keep-state or 
     2619            #    limit rule. 
    25772620            $found_state_rule = 1; 
    2578         } 
    2579         if (/allow.*to\s+any\s+established/) { 
     2621            last; 
     2622        } elsif (/keep-state/) { 
     2623            ### from the ipfw man page: 
     2624            # keep-state 
     2625            #    Upon a match, the firewall will create a dynamic rule, whose 
     2626            #    default behaviour is to match bidirectional traffic between 
     2627            #    source and destination IP/port using the same protocol.  The rule 
     2628            #    has a limited lifetime (controlled by a set of sysctl(8) vari- 
     2629            #    ables), and the lifetime is refreshed every time a matching 
     2630            #    packet is found. 
    25802631            $found_state_rule = 1; 
     2632            last; 
     2633        } elsif (/allow.*to\s+any\s+established/) { 
     2634            $found_state_rule = 1; 
     2635            last; 
    25812636        } 
    25822637    }