[Précédent (date)] [Suivant (date)] [Précédent (sujet)] [Suivant (sujet)] [Index par date] [Index par sujet]

Re: Firewall sous Mandrake 7.2



Bonjour groupuscule :),

> J'ai besoin d'aide concernant l'installation et la configuration d'un
> firewall sous Linux (Mandrake 7.2). Mon modem-câble a été détecté et
> tout fonctionne bien. Cependant, j'avais un firewall (ZoneAlarm) qui
> fonctionnait très bien sous Windows, comment puis-je avoir la même
> sécurité sous Linux.
>
> Merci
> Franco

Voici un script mettant en place des règles de firewall sur lequel je
travaille depuis un bout de temps. Il me semble assez sécuritaire. Il
pourra vous servir de point de départ pour le votre. J'y ai mis beaucoup
de commentaires afin de permettre les modifications facilement. Les
commentaires sont en anglais, désolé pour ceux qui ne la lisent pas!

Dépendemment de votre distribution, il suffit de l'exécuter au démarrage
en le mettant dans /etc/init.d (au équiv.) et de créer un lien
symbolique dans le répertoire /etc/rc2.d (ou equiv. pour le "runlevel"
par défaut). Optionnellement, vous pouvez augmenter la sécurité encore
plus en mettant à jour le firewall pour rejeter tous les paquets qui ne
sont pas pour votre adresse IP (qui ne devrait jamais se rendre là de
toute façon à moins d'erreur de routage) et exécutant le script avec
l'option "update" après l'établissement de la connection ppp ou la
négociation dhcp.

C'est un fichier texte... lisez et vous verrez :) Je reste disponible
pour de petites questions ou commentaires, mais je ne vais pas tout
débugger pour votre machine :) 

Mathieu
-- 
         \|||/   Mathieu Dubé-Dallaire   +----------------------------------+
        ( o o )                          | [email protected]
+--.oooO--(_)--Oooo.---+-----------------+----------------------------------+
                       +- Génie mécanique - École Polytechnique de Montréal



#!/bin/sh
# Simple but efficient firewall and masquerading setup using ipchains
#
# By Mathieu Dubé-Dallaire <[email protected]>
# Created:  April 20th 2000
# Modified: September 30th 2000
#
# (c) Copyright 2000  Mathieu Dubé-Dallaire
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for educational, research, private and non-profit purposes,
# without fee, and without a written agreement is hereby granted. 
# This software is provided as an example and basis for individual firewall
# development.  This software is provided without warranty.
#
# Any material furnished by Mathieu Dubé-Dallaire is furnished on an 
# "as is" basis.  He makes no warranties of any kind, either expressed 
# or implied as to any matter including, but not limited to, warranty 
# of fitness for a particular purpose, exclusivity or results obtained
# from use of the material.
#

# Set this to false if you don't want progress reports.
#
verbose=true

# We should use our local IP address instead of 0.0.0.0/0 to be more secure.
# But since it is dynamic, 0.0.0.0/0 will do for now. Once the interface is up,
# a firewall update (calling this script with the "update" parameter) should be
# done to deny anything that is not destined to the actual IP address. This
# should be run right after pppd and/or dhcpd.
#
ext_if=ppp0
ext_ip=0.0.0.0/0

int_if="eth0 lo"
int_ip="192.168.0.0/16 127.0.0.0/8"

any_ip=0.0.0.0/0

# See how we are called
case "$1" in

 start)
    #-------------------------------------------------------------------------#
    $verbose && echo "firewall: initiating kernel level protection."

      # Initiate IP forwarding
      echo 1 > /proc/sys/net/ipv4/ip_forward

      # Enable IP spoofing protection (source address verification)
      for file in /proc/sys/net/ipv4/conf/*/rp_filter; do
        echo 1 > $file;
      done

      # Disable ICMP Redirect Acceptance
      for file in /proc/sys/net/ipv4/conf/*/accept_redirects; do
        echo 0 > $file
      done

      # Disable Source Routed Packets
      for file in /proc/sys/net/ipv4/conf/*/accept_source_route; do
        echo 0 > $file
      done

    #-------------------------------------------------------------------------#
    $verbose && echo "firewall: setting basic policies and rules."

      # Set default policies for input, output and forward chains
      ipchains -P input REJECT
      ipchains -P output REJECT
      ipchains -P forward REJECT
      # Flush all rules in input, output and forward chains
      ipchains -F input
      ipchains -F output
      ipchains -F forward

      # Packets from the external interface destined to the external IP
      # (as it should) will pass through the net_in chain. Packets to
      # the outside interface pass through the net_out chain.
      ipchains -N net_in
      ipchains -N net_out
      #
      ipchains -A input   -d $ext_ip -i $ext_if -j net_in
      ipchains -A output  -s $ext_ip -i $ext_if -j net_out

      # Packets from the internal interface(s) will pass through the loc_in
      # chain. Packets to the internal interface pass through the loc_out
      # chain.
      ipchains -N loc_in
      ipchains -N loc_out
      #
      for i in $int_if; do
        ipchains -A input            -i $i      -j loc_in
        ipchains -A output           -i $i      -j loc_out
      done

      # Packets that fall off the *_in and *_out rules and the ones that are
      # not treated are simply handed to the default policy. We add catch all
      # rules here to log those packets.
      ipchains -A input   -l -j REJECT
      ipchains -A output  -l -j REJECT

    #-------------------------------------------------------------------------#
    $verbose && echo -n "firewall: loading modules: "

      # Set masquerade timeout to   2 hours for tcp connections
      # Set masquerade timeout to  10 sec for tcp/ip "FIN" packet is received
      # Set masquerade timeout to 160 sec for UDP traffic (Imp for ICQ users)
      ipchains -M -S 7200 10 160

      modprobe ip_masq_ftp;    $verbose && echo -n "ftp "
      modprobe ip_masq_raudio; $verbose && echo -n "realaudio "
      modprobe ip_masq_irc;    $verbose && echo "irc."

    #-------------------------------------------------------------------------#
    $verbose && echo -n "firewall: building chains: loc_in"

      # General---------------------------------------------------------------#

        # This is a very simple rule. We allow everything from our local
        # interface. This is safe as long as you trust everyone on the local
        # network (it's my case but may not be yours... check it out!)
        ipchains -A loc_in -j ACCEPT

      # Forwarding------------------------------------------------------------#

        # Masquerade all machines on the local network who want to go outside
        # (the -i switch gives us the destination interface, so we rely on the
        # IP addresses for the source) and allow forwarding for local-local
        # packets.
        for i in $int_ip; do
          ipchains -A forward -s $i          -i $ext_if -j MASQ
          ipchains -A forward -s $i                     -j ACCEPT 
        done

      # Everything Else------------------------------------------------------#

        # Everything else that does not match the previous rules will be caught
        # by the input chain's policy (which should be DENY or REJECT).
    
    #-------------------------------------------------------------------------#
    $verbose && echo -n " net_in"

      # Because these rules apply in the input chain, we haven't demasqueraded
      # anything yet. So, everything coming into this chain from our outside
      # interface should be for our external IP address. We use $any_ip for the
      # destination parameter here instead of $ext_ip because this way we won't
      # have to rewrite all the rules each time the address changes, only the
      # entry condition (see the input chain).

      # Servers (TCP)---------------------------------------------------------#
  
        # Open some privileged tcp ports - for local tcp SERVERS
        services="ssh ident"  # smtp www ftp ftp-data ...
        for port in $services; do
          ipchains -A net_in -d $any_ip $port  -p tcp  -j ACCEPT
        done

      # Servers (UDP)---------------------------------------------------------#
  
        # Open some privileged udp ports - for local udp SERVERS
        #services="domain"
        #for port in $services; do
        #  ipchains -A net_in -d $any_ip $port  -p udp  -j ACCEPT
        #done

      # Clients (TCP)---------------------------------------------------------#

        # Open all unprivileged ports on the firewall. This is so remote
        # servers can answer our local client request, but can't connect (! -y)
        # which is good :).
        ipchains -A net_in -s $any_ip     -d $any_ip 1024:    ! -y -p tcp -j ACCEPT
  
        # We need this next line to allow our ftp clients to work in active
        # mode where the server initiates a connection back to us for data
        # transfers.
        ipchains -A net_in -s $any_ip 20  -d $any_ip 1024:      -y -p tcp -j ACCEPT

        # Open privileged ports 513:1023 on the firewall for our ssh clients
        # only. ssh uses ports from 1023 downto 513 to connect to remote hosts.
        # ssh is good and we want that :)
        ipchains -A net_in -s $any_ip ssh -d $any_ip 513:1023 ! -y -p tcp -j ACCEPT

      # Clients (UDP)---------------------------------------------------------#

        # Since we can't restrict connections with UDP because UDP is a
        # connectionless protocol and thus doesn't a SYN flag to watch for, we
        # must use a different approach. We will open the firewall only for
        # udp services we need. Since there are only a few, we are ok. We could
        # be even more secure by allowing replies only from our trusted servers
        # by changing $any_ip to the address of our dns|ntp|icq servers since
        # normally we only communicate with a particular server.

        # remote dns replies to our local dns and to local clients.
        #   if we use a caching nameserver on the localhost
        #ipchains -A net_in -s $any_ip domain -d $any_ip 53         -p udp -j ACCEPT
        #   if dns requests from our clients go directly to the external dns
        ipchains -A net_in -s $any_ip domain -d $any_ip 1024:      -p udp -j ACCEPT

        # remote time server replies to our to local clients
        ipchains -A net_in -s $any_ip ntp    -d $any_ip ntp        -p udp -j ACCEPT

        # remote icq server replies to our to local clients
        ipchains -A net_in -s $any_ip 4000   -d $any_ip 1024:      -p udp -j ACCEPT

      # ICMP -----------------------------------------------------------------#

        # Deny ICMP fragments (we don't need no stinkin' fragments :)
        ipchains -A net_in -p icmp -f -j DENY

        # Allow but log ICMP echo requests from the outside (pings)
        ipchains -A net_in -p icmp --icmp-type echo-request -l -j ACCEPT

        # Allow other ICMP packets
        ipchains -A net_in -p icmp    -j ACCEPT

      # Everything else ------------------------------------------------------#

        # Deny and log all other packets
        ipchains -A net_in         -l -j DENY

      # Forwarding--------------------------------------------------------------#

        # There is nothing to explicitely forward to a masqueraded local
        # network, so we let the forwarding policy do the work (should be DENY
        # or REJECT).

    #-------------------------------------------------------------------------#
    $verbose && echo -n " loc_out"

      # Priorities------------------------------------------------------------#
      
        # As of this time, I have found nothing usefull to put here :) except
        # to allow everything

        # If we made it into this chain, we deserve to be accepted :)
        ipchains -A loc_out -j ACCEPT

    #-------------------------------------------------------------------------#
    $verbose && echo -n " net_out"

      # Priorities------------------------------------------------------------#

        # This section is basically to prioritize the packets. It is especially
        # usefull on a slow (modem) connection.

        # Minimum delay for telnet, ssh and web trafic.
        ipchains -A net_out -d $any_ip telnet    -p tcp -t 0x01 0x10
        ipchains -A net_out -d $any_ip ssh       -p tcp -t 0x01 0x10
        ipchains -A net_out -d $any_ip www       -p tcp -t 0x01 0x10

        # Low cost for ftp-data, nntp and pop-3.
        ipchains -A net_out -d $any_ip ftp-data  -p tcp -t 0x01 0x02
        ipchains -A net_out -d $any_ip nntp      -p tcp -t 0x01 0x02
        ipchains -A net_out -d $any_ip pop-3     -p tcp -t 0x01 0x02

      # Restraints------------------------------------------------------------#

        # I don't like advertising banners much, so I block outgoing www
        # requests to their domain.
        
        #- doubleclick.net
        #ipchains -A net_out -d 199.95.207.0/24  www  -p tcp -j REJECT
        #ipchains -A net_out -d 199.95.208.0/24  www  -p tcp -j REJECT
        #ipchains -A net_out -d 204.253.104.0/24 www  -p tcp -j REJECT
        #ipchains -A net_out -d 205.138.3.0/24   www  -p tcp -j REJECT
        #ipchains -A net_out -d 208.184.29.0/24  www  -p tcp -j REJECT
        #ipchains -A net_out -d 208.32.211.0/24  www  -p tcp -j REJECT
        #ipchains -A net_out -d 209.67.38.0/24   www  -p tcp -j REJECT

        # If we made it into this chain, we deserve to be accepted :)
        ipchains -A net_out -j ACCEPT

ipchains -A forward  -l -j REJECT

    $verbose && echo "."
    ;;

 stop)
    #-------------------------------------------------------------------------#
    $verbose && echo "firewall: stoping firewall."

      # Stop IP forwarding
      echo 0 > /proc/sys/net/ipv4/ip_forward

      # Set default policies for input, output and forward chains
      ipchains -P input DENY
      ipchains -P output DENY
      ipchains -P forward DENY

      # Flush all rules in input, output and forward chains
      ipchains -F input
      ipchains -F output
      ipchains -F forward

      # Flush all rules and delete all created chains
      ipchains -F net_in;      ipchains -X net_in
      ipchains -F net_out;     ipchains -X net_out
      ipchains -F loc_in;      ipchains -X loc_in
      ipchains -F loc_out;     ipchains -X loc_out
    ;;

 restart)
    #-------------------------------------------------------------------------#
    $verbose && echo "firewall: restarting firewall."

      $0 stop
      $0 start
    ;;

 update)
    #-------------------------------------------------------------------------#
    $verbose && echo "firewall: updating firewall."

      # By calling this option, we can set the entry condition for the net_in
      # chain to be destined directly to our actual IP address. And for the
      # net_out chain to originate from that same IP address. Although using
      # the $any_ip mask is not to much of a risk, it is preferable to restrict
      # the access even further. Note that all the other packets entering our
      # external interface WILL be dropped. If the selected external interface
      # is unavailable, we default to $any_ip.
      
      # NOTE: This is only allowable for a masqueraded internal network. If this
      # is not the case, all packets from and to other internal machines will BE
      # dropped because the IP addresses won't match this machine's. Check the
      # loc_in chain to make sure we masquerade.

      ext_ip=`ifconfig $ext_if 2> /dev/null | grep 'inet addr:' | awk '{print $2}' | sed -e 's/.*://'`
      if [ "$ext_ip" = "" ]; then ext_ip=$any_ip; fi;
      ipchains -R input  1 -d $ext_ip  -i $ext_if -j net_in
      ipchains -R output 1 -s $ext_ip  -i $ext_if -j net_out
    ;;

 status)
    #-------------------------------------------------------------------------#
    $verbose && echo "firewall: firewall transfer summary."

      # This option is just to show that the net_in and net_out jump points
      # can be used as accounting rules for the calculation of used bandwidth
      #
      echo "`date +'%D %T'` - Summary for $ext_if (external interface)"
      echo "   Bytes in:  `ipchains -L input  -n -v | grep net_in | awk '{print $2}'`"
      echo "   Bytes out: `ipchains -L output -n -v | grep net_out | awk '{print $2}'`"
    ;;

 *)
   echo "Usage: $0 {start|stop|restart|update|status}"
   exit 1
   ;;
   
esac