荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: georgehill (清风浮云 人生), 信区: Linux
标  题: ipfilter-howto(7-15)(转寄)
发信站: BBS 荔园晨风站 (Thu Nov  2 23:07:31 2000), 站内信件

【 以下文字转载自 georgehill 的信箱 】
【 原文由 georgehill.bbs@smth.org 所发表 】
发信人: snofe ([听潮阁主人]), 信区: FreeBSD
标  题: ipfilter-howto(7-15)(转寄)
发信站: BBS 水木清华站 (Tue Oct 31 13:45:20 2000)

                             -7-


Compare this to our previous rule:

    block in quick from 192.168.0.0/16 to any
    pass  in       all

The old way, all traffic from 192.168.0.0/16, regardless  of
interface,  was  completely  blocked.  The new way, using on
tun0 means that it's only blocked if it comes in on the tun0
interface.   If  a  packet arrived on the xl0 interface from
192.168.0.0/16, it would be passed.

     At this point you can build a fairly extensive  set  of
definitive  addresses  which  are  passed or blocked.  Since
we've already started blocking private  address  space  from
entering tun0, lets take care of the rest of it:

    block in quick on tun0 from 192.168.0.0/16 to any
    block in quick on tun0 from 172.16.0.0/12 to any
    block in quick on tun0 from 10.0.0.0/8 to any
    block in quick on tun0 from 127.0.0.0/8 to any
    pass  in       all

You've  already seen the first 3 blocks, but not the fourth.
The fourth is a largely  wasted  class-A  network  used  for
loopback.    Much   software  communicates  with  itself  on
127.0.0.1 so blocking it from an external source is  a  good
idea.

     There's  a very important principle in packet filtering
which has only been alluded  to  with  the  private  network
blocking  and  that  is  this: When you know there's certain
types of data that only comes from certain places, you setup
the  system  to  only  allow  that  kind  of data from those
places.  In the case of the unroutable addresses,  you  know
that  nothing  from  10.0.0.0/8  should  be arriving on tun0
because you have no way to reply to it.  It's  an  illegiti-
mate  packet.   The  same  goes for the other unroutables as
well as 127.0.0.0/8.

     Many pieces of software  do  all  their  authentication
based  upon  the  packet's originating IP address.  When you
have an internal network, say 20.20.20.0/24, you  know  that
the  only traffic for that internal network is going to come
off the local ethernet.  Should a packet from  20.20.20.0/24
arrive  over a PPP dialup, it's perfectly reasonable to drop
it on the floor, or put it in a dark room for interrogation.
It  should by no means be allowed to get to its final desti-
nation.  You can accomplish this  particularly  easily  with
what you already know of IPF.  The new ruleset would be:

    block in quick on tun0 from 192.168.0.0/16 to any
    block in quick on tun0 from 172.16.0.0/12 to any
    block in quick on tun0 from 10.0.0.0/8 to any
    block in quick on tun0 from 127.0.0.0/8 to any









                             -8-


    block in quick on tun0 from 20.20.20.0/24 to any
    pass  in       all

2.7.  Bi-Directional Filtering; The "out" Keyword

     Up  until  now,  we've been passing or blocking inbound
traffic.  To clarify, inbound traffic is  all  traffic  that
enters  the firewall on any interface.  Conversely, outbound
traffic is all traffic that leaves on any interface (whether
locally  generated  or  simply passing through).  This means
that all packets coming in are not  only  filtered  as  they
enter  the  firewall,  they're  also  filtered as they exit.
Thusfar there's been an implied pass out all that may or may
not  be  desirable.  Just as you may pass and block incoming
traffic, you may do the same with outgoing traffic.

     Now that we know there's a way to filter outbound pack-
ets  just  like inbound, it's up to us to find a concievable
use for such a thing.  One possible use of this idea  is  to
keep spoofed packets from exiting your own network.  Instead
of passing any traffic out the  router,  you  could  instead
limit   permitted   traffic   to   packets   originating  at
20.20.20.0/24.  You might do it like this:

    pass  out quick on tun0 from 20.20.20.0/24 to any
    block out quick on tun0 from any to any

If a packet comes from 20.20.20.1/32, it gets  sent  out  by
the  first  rule.  If a packet comes from 1.2.3.4/32 it gets
blocked by the second.

     You can also make  similar  rules  for  the  unroutable
addresses.   If some machine tries to route a packet through
IPF with a destination in 192.168.0.0/16, why not  drop  it?
The worst that can happen is that you'll spare yourself some
bandwidth:

    block out quick on tun0 from any to 192.168.0.0/16
    block out quick on tun0 from any to 172.16.0.0/12
    block out quick on tun0 from any to 10.0.0.0/8

In the narrowest viewpoint, this doesn't enhance your  secu-
rity.   It  enhances everybody else's security, and that's a
nice thing to do.  As another viewpoint, one  might  suppose
that because nobody can send spoofed packets from your site,
that your site has less value as a relay for  crackers,  and
as such is less of a target.

     You'll  likely  find a number of uses for blocking out-
bound packets.  One thing to always keep in mind is that  in
-----------
 This can, of course, be changed by using -DIPFIL-
TER_DEFAULT_BLOCK  when compiling ipfilter on your
system.









                             -9-


and  out directions are in reference to your firewall, never
any other machine.

2.8.  Logging What Happens; The "log" Keyword

     Up to this point, all blocked and passed  packets  have
been silently blocked and silently passed.  Usually you want
to know if you're being attacked rather than wonder if  that
firewall  is  really buying you any added benefits.  While I
wouldn't want to log every passed packet, and in some  cases
every blocked packet, I would want to know about the blocked
packets from 20.20.20.0/24.  To do this, we add the log key-
word:

    block in     quick on tun0 from 192.168.0.0/16 to any
    block in     quick on tun0 from 172.16.0.0/12 to any
    block in     quick on tun0 from 10.0.0.0/8 to any
    block in     quick on tun0 from 127.0.0.0/8 to any
    block in log quick on tun0 from 20.20.20.0/24 to any
    pass  in       all

So far, our firewall is pretty good at blocking packets com-
ing to it from suspect places, but there's still more to  be
done.   For one thing, we're accepting packets destined any-
where.  One thing we ought to do is  make  sure  packets  to
20.20.20.0/32  and 20.20.20.255/32 get dropped on the floor.
To do otherwise opens  the  internal  network  for  a  smurf
attack.  These two lines would prevent our hypothetical net-
work from being used as a smurf relay:

    block in log quick on tun0 from any to 20.20.20.0/32
    block in log quick on tun0 from any to 20.20.20.255/32

This brings our total ruleset to look something like this:

    block in     quick on tun0 from 192.168.0.0/16 to any
    block in     quick on tun0 from 172.16.0.0/12 to any
    block in     quick on tun0 from 10.0.0.0/8 to any
    block in     quick on tun0 from 127.0.0.0/8 to any
    block in log quick on tun0 from 20.20.20.0/24 to any
    block in log quick on tun0 from any to 20.20.20.0/32
    block in log quick on tun0 from any to 20.20.20.255/32
    pass  in       all

2.9.  Complete Bi-Directional Filtering By Interface

     So far we have only presented fragments of  a  complete
ruleset.   When  you're  actually creating your ruleset, you
should setup rules for every direction and every  interface.
The  default state of ipfilter is to pass packets.  It is as
though there were an invisible rule at the  beginning  which
states  pass  in  all and pass out all.  Rather than rely on
some default behaviour, make everything as specific as  pos-
sible,  interface by interface, until every base is covered.









                            -10-


     First we'll start with the lo0 interface,  which  wants
to  run  wild and free.  Since these are programs talking to
other on the local  system,  go  ahead  and  keep  it  unre-
stricted:

    pass out quick on lo0
    pass in  quick on lo0

Next, there's the xl0 interface.  Later on we'll begin plac-
ing restrictions on the xl0 interface, but  to  start  with,
we'll  act  as  though  everything  on  our local network is
trustworthy and give it much the same treatment as lo0:

    pass out quick on xl0
    pass in  quick on xl0

Finally, there's the tun0 interface, which we've been  half-
filtering with up until now:

    block out quick on tun0 from any to 192.168.0.0/16
    block out quick on tun0 from any to 172.16.0.0/12
    block out quick on tun0 from any to 10.0.0.0/8
    pass  out quick on tun0 from 20.20.20.0/24 to any
    block out quick on tun0 from any to any

    block in     quick on tun0 from 192.168.0.0/16 to any
    block in     quick on tun0 from 172.16.0.0/12 to any
    block in     quick on tun0 from 10.0.0.0/8 to any
    block in     quick on tun0 from 127.0.0.0/8 to any
    block in log quick on tun0 from 20.20.20.0/24 to any
    block in log quick on tun0 from any to 20.20.20.0/32
    block in log quick on tun0 from any to 20.20.20.255/32
    pass  in     all

This  is  a  pretty significant amount of filtering already,
protecting 20.20.20.0/24 from being spoofed  or  being  used
for  spoofing.   Future  examples will continue to show one-
sideness, but keep in mind that it's for brevity's sake, and
when  setting  up  your  own ruleset, adding rules for every
direction and every interface is necessary.


2.10.  Controlling Specific Protocols; The "proto" Keyword

     Denial of Service attacks  are  as  rampant  as  buffer
overflow  exploits.   Many denial of service attacks rely on
glitches in the OS's TCP/IP  stack.   Frequently,  this  has
come  in  the  form  of  ICMP  packets.   Why not block them
entirely?

    block in log quick on tun0 proto icmp from any to any

Now any ICMP traffic coming in from tun0 will be logged  and
discarded.









                            -11-


2.11.   Filtering ICMP with the "icmp-type" Keyword; Merging
Rulesets

     Of course, dropping all ICMP isn't really an ideal sit-
uation.   Why  not drop all ICMP?  Well, because it's useful
to have partially enabled.  So maybe you want to  keep  some
types  of  ICMP  traffic  and drop other kinds.  If you want
ping and traceroute to work, you need to let in ICMP types 0
and  11.   Strictly speaking, this might not be a good idea,
but if you need to weigh security against  convenience,  IPF
lets you do it.

    pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
    pass in quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11

Remember that ruleset order is important.  Since we're doing
everything quick we must have our passes before our  blocks,
so we really want the last three rules in this order:

    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11
    block in log quick on tun0 proto icmp from any to any

Adding  these  3  rules  to the anti-spoofing rules is a bit
tricky.  One error might be to put the new ICMP rules at the
beginning:

    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11
    block in log quick on tun0 proto icmp from any to any
    block in     quick on tun0 from 192.168.0.0/16 to any
    block in     quick on tun0 from 172.16.0.0/12 to any
    block in     quick on tun0 from 10.0.0.0/8 to any
    block in     quick on tun0 from 127.0.0.0/8 to any
    block in log quick on tun0 from 20.20.20.0/24 to any
    block in log quick on tun0 from any to 20.20.20.0/32
    block in log quick on tun0 from any to 20.20.20.255/32
    pass  in       all

The  problem  with  this  is that an ICMP type 0 packet from
192.168.0.0/16 will get passed by the first rule, and  never
blocked  by the fourth rule.  Also, since we quickly pass an
ICMP ECHO_REPLY (type 0) to 20.20.20.0/24, we've just opened
ourselves  back  up  to  a  nasty smurf attack and nullified
those last two block rules.  Oops.  To avoid this, we  place
the ICMP rules after the anti-spoofing rules:

    block in     quick on tun0 from 192.168.0.0/16 to any
    block in     quick on tun0 from 172.16.0.0/12 to any
    block in     quick on tun0 from 10.0.0.0/8 to any
    block in     quick on tun0 from 127.0.0.0/8 to any
    block in log quick on tun0 from 20.20.20.0/24 to any
    block in log quick on tun0 from any to 20.20.20.0/32
    block in log quick on tun0 from any to 20.20.20.255/32









                            -12-


    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11
    block in log quick on tun0 proto icmp from any to any
    pass  in       all

Because  we  block spoofed traffic before the ICMP rules are
processed, a spoofed packet never makes it to the ICMP rule-
set.   It's  very  important to keep such situations in mind
when merging rules.

2.12.  TCP and UDP Ports; The "port" Keyword

     Now that we've started blocking packets based on proto-
col, we can start blocking packets based on specific aspects
of each protocol.  The most frequently used of these aspects
is  the port number.  Services such as rsh, rlogin, and tel-
net are all very convenient  to  have,  but  also  hideously
insecure  against  network sniffing and spoofing.  One great
compromise is to only allow the services to run  internally,
then  block  them  externally.   This  is easy to do because
rlogin, rsh, and telnet use specific TCP  ports  (513,  514,
and 23 respectively).  As such, creating rules to block them
is easy:

    block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 513
    block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 514
    block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 23

Make sure all 3 are before the pass in all  and  they'll  be
closed  off  from  the  outside  (leaving  out  spoofing for
brevity's sake):

    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 0
    pass  in     quick on tun0 proto icmp from any to 20.20.20.0/24 icmp-type 11
    block in log quick on tun0 proto icmp from any to any
    block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 513
    block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 514
    block in log quick on tun0 proto tcp from any to 20.20.20.0/24 port = 23
    pass  in     all

You might also want to block 514/udp  (syslog),   111/tcp  &
111/udp  (portmap),  515/tcp  (lpd),  2049/tcp  and 2049/udp
(NFS), 6000/tcp (X11) and so on and so forth.  You can get a
complete  listing  of  the  ports being listened to by using
netstat -a (or lsof -i, if you have it installed).

     Blocking UDP instead of  TCP  only  requires  replacing
proto tcp with proto udp.  The rule for syslog would be:

    block in log quick on tun0 proto udp from any to 20.20.20.0/24 port = 514

IPF  also  has  a shorthand way to write rules that apply to
both proto tcp and proto udp  at  the  same  time,  such  as
portmap or NFS.  The rule for portmap would be:









                            -13-


    block in log quick on tun0 proto tcp/udp from any to 20.20.20.0/24 port =
111




3.  Advanced Firewalling Introduction

     This  section  is  designed as an immediate followup to
the basic section.  Contained below are  both  concepts  for
advanced  firewall  design,  and advanced features contained
only within ipfilter.  Once you are  comfortable  with  this
section, you should be able to build a very strong firewall.

3.1.  Rampant Paranoia; or The Default-Deny Stance

     There's a big problem with  blocking  services  by  the
port:  sometimes they move.  RPC based programs are terrible
about this, lockd, statd, even  nfsd  listens  places  other
than  2049.  It's awfully hard to predict, and even worse to
automate adjusting all the time.  What if you  miss  a  ser-
vice?   Instead  of dealing with all that hassle, lets start
over with a clean slate.  The  current  ruleset  looks  like
this:




     Yes, we really are starting over.  The first rule we're
going to use is this:

    block in all

No network traffic gets through. None. Not a  peep.   You're
rather  secure  with  this  setup.  Not terribly useful, but
quite secure.  The great thing is that it doesn't take  much
more  to  make your box rather secure, yet useful too.  Lets
say the machine this is running on is a web server,  nothing
more,  nothing  less.   It  doesn't even do DNS lookups.  It
just wants to take connections on 80/tcp and that's it.   We
can  do  that.   We  can do that with a second rule, and you
already know how:

    block in       on tun0 all
    pass  in quick on tun0 proto tcp from any to 20.20.20.1/32 port = 80

This machine will pass in port 80  traffic  for  20.20.20.1,
and  deny  everything  else.  For basic firewalling, this is
all one needs.

3.2.  Implicit Allow; The "keep state" Rule

     The job of your firewall is to prevent unwanted traffic
getting  to  point  B  from  point A.  We have general rules
which say "as long as this packet is to port 23, it's okay."









                            -14-


We  have general rules which say "as long as this packet has
its FIN flag set, it's okay."  Our firewalls don't know  the
beginning, middle, or end of any TCP/UDP/ICMP session.  They
merely have vague rules that are  applied  to  all  packets.
We're  left  to  hope  that the packet with its FIN flag set
isn't really a FIN scan, mapping our services.  We hope that
the  packet to port 23 isn't an attempted hijack of our tel-
net session.  What if there was a way to identify and autho-
rize  individual  TCP/UDP/ICMP sessions and distinguish them
from port scanners and DoS attacks?  There is  a  way,  it's
called keeping state.

     We  want convenience and security in one.  Lots of peo-
ple do, that's why Ciscos have an "established" clause  that
lets  established  tcp sessions go through.  Ipfw has estab-
lished.  Ipfwadm has setup/established.  They all have  this
feature, but the name is very misleading.  When we first saw
it, we thought it meant our packet filter was keeping  track
of  what  was  going  on,  that  it knew if a connection was
really established or not.  The fact is, they're all  taking
the  packet's  word for it from a part of the packet anybody
can lie about.  They read the TCP packet's flags section and
there's the reason UDP/ICMP don't work with it, they have no
such thing.  Anybody who can  create  a  packet  with  bogus
flags can get by a firewall with this setup.

     Where  does  IPF  come in to play here, you ask?  Well,
unlike the other firewalls, IPF really  can  keep  track  of
whether or not a connection is established.  And it'll do it
with TCP, UDP and ICMP, not just TCP.  Ipf calls it  keeping
state.  The keyword for the ruleset is keep state.

     Up until now, we've told you that packets come in, then
the ruleset gets checked; packets go out, then  the  ruleset
gets  checked.   Actually,  what happens is packets come in,
the state table gets checked, then *maybe* the inbound rule-
set  gets  checked;  packets  go  out,  the state table gets
checked, then *maybe* the  outbound  ruleset  gets  checked.
The  state table is a list of TCP/UDP/ICMP sessions that are
unquestionadely passed through the  firewall,  circumventing
the  entire  ruleset.   Sound  like a serious security hole?
Hang on, it's the best thing  that  ever  happened  to  your
firewall.

     All  TCP/IP sessions have a start, a middle, and an end
(even though they're sometimes all in the same packet).  You
can't have an end without a middle and you can't have a mid-
dle without a start.  This means that all you really need to
filter  on  is  the beginning of a TCP/UDP/ICMP session.  If
the beginning of the session is  allowed  by  your  firewall
rules,  you really want the middle and end to be allowed too
(lest your IP stack should overflow and your machines become
useless).  Keeping state allows you to ignore the middle and
end and simply focus on blocking/passing new  sessions.   If









                            -15-


the  new  session is passed, all its subsequent packets will
be allowed through.  If it's blocked, none of its subsequent
packets will be allowed through.  Here's an example for run-
ning an ssh server (and nothing but an ssh server):

    block out quick on tun0 all
    pass  in  quick on tun0 proto tcp from any to 20.20.20.1/32 port = 22 keep
state

The first thing you might notice is that  there's  no  "pass
out"  provision.   In  fact,  there's  only an all-inclusive
"block out" rule.  Despite this, the  ruleset  is  complete.
This is because by keeping state, the entire ruleset is cir-
cumvented.  Once the first SYN packet hits the  ssh  server,
state  is  created  and  the remainder of the ssh session is
allowed to take place without interference  from  the  fire-
wall.  Here's another example:

    block in  quick on tun0 all
    pass  out quick on tun0 proto tcp from 20.20.20.1/32 to any keep state

In  this  case,  the server is running no services.  Infact,
it's not a server, it's a client.  And this  client  doesn't
want  unauthorized  packets  entering  its  IP stack at all.
However, the client wants full access to  the  internet  and
the  reply packets that such privledge entails.  This simple
ruleset creates state entries for  every  new  outgoing  TCP
session.   Again,  since a state entry is created, these new
TCP sessions are free to talk back and forth as they  please
without  the  hinderance or inspection of the firewall rule-
set.  We mentioned that this also works for UDP and ICMP:

    block in  quick on tun0 all
    pass  out quick on tun0 proto tcp  from 20.20.20.1/32 to any keep state
    pass  out quick on tun0 proto udp  from 20.20.20.1/32 to any keep state
    pass  out quick on tun0 proto icmp from 20.20.20.1/32 to any keep state

Yes Virginia, we can ping.  Now we're keeping state on  TCP,
UDP,  ICMP.   Now we can make outgoing connections as though
there's no firewall at all, yet would-be attackers can't get
back  in.   This  is  very  handy because there's no need to
track down what ports we're listening to, only the ports  we
want people to be able to get to.

     State is pretty handy, but it's also a bit tricky.  You
can shoot yourself in the foot  in  strange  and  mysterious
ways.  Consider the following ruleset:

     pass  in  quick on tun0 proto tcp from any to 20.20.20.1/32 port = 23
     pass  out quick on tun0 proto tcp from any to any keep state
     block in  quick all
     block out quick all

At  first  glance,  this seems to be a good setup.  We allow
incoming  sessions  to  port  23,  and   outgoing   sessions

--

※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.199.66.62]
--
※ 转载:·BBS 荔园晨风站 bbs.szu.edu.cn·[FROM: 192.168.1.115]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店