荔园在线

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

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


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

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

                            -16-


anywhere.   Naturally  packets  going  to  port 23 will have
reply packets, but the ruleset is setup in such a  way  that
the pass out rule will generate a state entry and everything
will work perfectly.  At least, you'd think so.

     The unfortunate truth is that after 60 seconds of  idle
time  the state entry will be closed (as opposed to the nor-
mal 5 days).  This is because the state  tracker  never  saw
the original SYN packet destined to port 23, it only saw the
SYN ACK.  IPF is very good about following TCP sessions from
start  to  finish,  but it's not very good about coming into
the middle of a connection, so rewrite the rule to look like
this:

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

The additional of this rule will enter the very first packet
into the state table and everything will work  as  expected.
Once  the  3-way  handshake  has  been  witness by the state
engine, it is marked in 4/4 mode, which means it's setup for
long-term data exchange until such time as the connection is
torn down (wherein the mode changes again.  You can see  the
current modes of your state table with ipfstat -s.

3.3.  Stateful UDP

     UDP is stateless so naturally it's a bit harder to do a
reliable job of keeping state on it.  Nonetheless, ipf  does
a  pretty  good  job.   When machine A sends a UDP packet to
machine B with source port X and  destination  port  Y,  ipf
will  allow  a reply from machine B to machine A with source
port Y and destination port Y.  This  is  is  a  short  term
state entry, a mere 60 seconds.

     Here's an example of what happens if we use nslookup to
get the IP address of www.3com.com:

    $ nslookup www.3com.com

  A DNS packet is generated:

    17:54:25.499852 20.20.20.1.2111 > 198.41.0.5.53: 51979+

The packet is  from  20.20.20.1,  port  2111,  destined  for
198.41.0.5,  port  53.   A 60 second state entry is created.
If a packet comes back from 198.41.0.5 port 53 destined  for
20.20.20.1  port  2111 within that period of time, the reply
packet will be let through.  As you  can  see,  milliseconds
later:

    17:54:25.501209 198.41.0.5.53 > 20.20.20.1.2111: 51979 q: www.3com.com









                            -17-


The  reply  packet  matches  the  state  criteria and is let
through.  At that same moment that packet  is  let  through,
the state gateway is closed and no new incoming packets will
be allowed in, even if they claim to be from the same place.

3.4.  Stateful ICMP

     IPFilter  handles  ICMP  states  in the manner that one
would expect from understanding how ICMP is  used  with  TCP
and  UDP,  and  with  your  understanding  of how keep state
works.  There  are  two  general  types  of  ICMP  messages;
requests and replies.   When you write a rule such as:

    pass out on tun0 proto icmp from any to any icmp-type 8 keep state

to allow outbound echo requests (a typical ping), the resul-
tant icmp-type 0 packet that comes back will be allowed  in.
This  state entry has a default timeout of an incomplete 0/0
state of 60 seconds.   Thus, if you are keeping state on any
outbound  icmp  message  that will elicit an icmp message in
reply, you need a proto icmp [...] keep state rule.

     However, the majority of ICMP messages are status  mes-
sages  generated by some failure in UDP (and sometimes TCP),
and in 3.4.x and greater IPFilters, any  ICMP  error  status
message  (say  icmp-type 3 code 3 port unreachable, or icmp-
type 11 time exceeded) that matches an  active  state  table
entry  that  could  have  generated  that  message, the ICMP
packet is let in.  For example, in older IPFilters,  if  you
wanted traceroute to work, you needed to use:

    pass out on tun0 proto udp from any to any port 33434><33690 keep state
    pass in on tun0 proto icmp from any to any icmp-type timex

whereas  now  you can do the right thing and just keep state
on udp with:

    pass out on tun0 proto udp from any to any port 33434><33690 keep state

To provide some protection against  a  third-party  sneaking
ICMP  messages  through your firewall when an active connec-
tion is known to be in your state table, the  incoming  ICMP
packet  is checked not only for matching source and destina-
tion addresses (and ports, when applicable) but a tiny  part
of the payload of the packet that the ICMP message is claim-
ing it was generated by.

3.5.  FIN Scan Detection; "flags" Keyword, "keep frags" Key-
word

Lets go back to the 4 rule set from the previous section:

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









                            -18-


    block in  quick all
    block out quick all

This is almost, but not quite, satisfactory.  The problem is
that it's not just SYN packets that're allowed to go to port
23,  any  old packet can get through.  We can change this by
using the flags option:

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

Now only TCP packets, destined for 20.20.20.1, at  port  23,
with a lone SYN flag will be allowed in and entered into the
state table.  A lone SYN flag is only present  as  the  very
first packet in a TCP session (called the TCP handshake) and
that's really what we wanted all along.   There's  at  least
two  advantages  to  this:  No arbitrary packets can come in
and make a mess of your state table.   Also,  FIN  and  XMAS
scans  will  fail  since  they  set flags other than the SYN
flag.  Now all incoming packets must either be handshakes or
have state already.  If anything else comes in, it's  proba-
bly  a  port scan or a forged packet.  There's one exception
to that, which is when a packet comes in  that's  fragmented
from  its journey.  IPF has provisions for this as well, the
keep frags keyword.  With it, IPF will notice and keep track
of  packets that are fragmented, allowing the expected frag-
ments to to go through.  Lets rewrite the  3  rules  to  log
forgeries and allow fragments:

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

This  works  because  every  packet  that  should be allowed
through makes it into the state table  before  the  blocking
rules  are reached. The only scan this won't detect is a SYN
scan itself.  If you're truely worried about that, you might
even want to log all initial SYN packets.


-----------
 Some examples use flags S/SA instead of flags  S.
flags  S  actually  equates  to flags S/AUPRFS and
matches against only the SYN packet out of all six
possible  flags, while flags S/SA will allow pack-
ets that may or may not have the URG, PSH, FIN, or
RST  flags  set.  Some protocols demand the URG or
PSH flags, and S/SAFR would be a better choice for
these,  however  we feel that it is less secure to
blindly use S/SA when it isn't required.  But it's
your firewall.









                            -19-


3.6.  Responding To a Blocked Packet

     So  far, all of our blocked packets have been dumped on
the floor, logged or not, we've never sent anything back  to
the  originating host.  Sometimes this isn't the most desir-
able of responses because in doing so, we actually tell  the
attacker  that  a  packet filter is present.  It seems a far
better thing to misguide the attacker into  believing  that,
while  there's no packet filter running, there's likewise no
services to break into.   This  is  where  fancier  blocking
comes into play.

     When  a service isn't running on a Unix system, it nor-
mally lets the remote host know with  some  sort  of  return
packet.   In  TCP,  this is done with an RST (Reset) packet.
When blocking a TCP packet, IPF can actually return  an  RST
to the origin by using the return-rst keyword.

Where once we did:

    block in log on tun0 proto tcp from any to 20.20.20.0/24 port = 23
    pass  in     all

We might now do:

    block return-rst in log from any to 20.20.20.0/24 proto tcp port = 23
    block in log quick on tun0
    pass  in     all

We  need  two  block  statements since return-rst only works
with TCP, and we still want to block protocols such as  UDP,
ICMP,  and  others.   Now that this is done, the remote side
will get "connection refused" instead of  "connection  timed
out".

     It's  also possible to send an error message when some-
body sends a packet to a UDP port on your  system.   Whereas
once you might have used:

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

You  could  instead  use  the  return-icmp keyword to send a
reply:

    block return-icmp(port-unr) in log quick on tun0 proto udp from any to
20.20.20.0/24 port = 111

According to TCP/IP  Illustrated,  port-unreachable  is  the
correct  ICMP type to return when no service is listening on
the port in question.  You can use any ICMP type  you  like,
but  port-unreachable  is probably your best bet.  It's also
the default ICMP type for return-icmp.

     However, when using  return-icmp,  you'll  notice  that
it's  not very stealthy, and it returns the ICMP packet with









                            -20-


the IP address of the firewall, not the original destination
of  the  packet.   This was fixed in ipfilter 3.3, and a new
keyword; return-icmp-as-dest, has been added.   The new for-
mat is:

     block return-icmp-as-dest(port-unr) in log on tun0 proto udp from any to
20.20.20.0/24 port = 111

3.7.  Fancy Logging Techniques

     It  is  important  to note that the presence of the log
keyword only ensures that the packet will  be  available  to
the  ipfilter  logging device; /dev/ipl.   In order to actu-
ally see this log information, one must be running the ipmon
utility  (or  some  other utility that reads from /dev/ipl).
The typical usage of log is coupled with ipmon -s to log the
information to syslog.  As of ipfilter 3.3, one can now even
control the logging behavior of syslog by  using  log  level
keywords, as in rules such as this:

     block in log level auth.info quick on tun0 from 20.20.20.0/24 to any
     block in log level auth.alert quick on tun0 proto tcp from any to
20.20.20.0/24 port = 21

In  addition  to  this,  you  can tailor what information is
being logged.  For example, you may not be  interested  that
someone  attempted  to probe your telnet port 500 times, but
you are interested that they probed you once.  You  can  use
the  log  first  keyword  to only log the first example of a
packet.  Of course, the notion of "first-ness" only  applies
to  packets  in  a  specific  session,  and  for the typical
blocked packet, you will be hard pressed to encounter situa-
tions  where this does what you expect.  However, if used in
conjunction with pass and keep state, this can be a valuable
keyword for keeping tabs on traffic.

     Another  useful  thing  you  can do with the logs is to
keep track of interesting pieces of the packet  in  addition
to  the  header information normally being logged.  Ipfilter
will give you the first 128 bytes of the packet if  you  use
the log body keyword.  You should limit the use of body log-
ging, as it makes your logs very verbose,  but  for  certain
applications,  it  is  often handy to be able to go back and
take a look at the packet, or to send this data  to  another
application that can examine it further.

3.8.  Putting It All Together

     So  now  we  have  a  pretty tight firewall, but it can
still be tighter.  Some of the  original  ruleset  we  wiped
clean  is  actually  very useful.  I'd suggest bringing back
all the anti-spoofing stuff.  This leaves us with:

    block in           on tun0
    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









                            -21-


    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  out quick on tun0 proto tcp/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
    pass  in  quick on tun0 proto tcp from any to 20.20.20.1/32 port = 80 flags
S keep state

3.9.  Improving Performance With Rule Groups

     Let's extend our use of our firewall by creating a much
more  complicated,  and  we hope more applicable to the real
world, example configuration For this example,  we're  going
to  change  the interface names, and network numbers.  Let's
assume that we have three interfaces in  our  firewall  with
interfaces xl0, xl1, and xl2.

xl0 is connected to our external network 20.20.20.0/26
xl1 is connected to our "DMZ" network 20.20.20.64/26
xl2 is connected to our protected network 20.20.20.128/25

We'll  define the entire ruleset in one swoop, since we fig-
ure that you can read these rules by now:

    block in     quick on xl0 from 192.168.0.0/16 to any
    block in     quick on xl0 from 172.16.0.0/12 to any
    block in     quick on xl0 from 10.0.0.0/8 to any
    block in     quick on xl0 from 127.0.0.0/8 to any
    block in log quick on xl0 from 20.20.20.0/24 to any
    block in log quick on xl0 from any to 20.20.20.0/32
    block in log quick on xl0 from any to 20.20.20.63/32
    block in log quick on xl0 from any to 20.20.20.64/32
    block in log quick on xl0 from any to 20.20.20.127/32
    block in log quick on xl0 from any to 20.20.20.128/32
    block in log quick on xl0 from any to 20.20.20.255/32
    pass out on xl0 all

    pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 80 flags
S keep state
    pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 21 flags
S keep state
    pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 20 flags
S keep state
    pass out quick on xl1 proto tcp from any to 20.20.20.65/32 port = 53 flags
S keep state
    pass out quick on xl1 proto udp from any to 20.20.20.65/32 port = 53 keep
state
    pass out quick on xl1 proto tcp from any to 20.20.20.66/32 port = 53 flags
S keep state
    pass out quick on xl1 proto udp from any to 20.20.20.66/32 port = 53 keep
state
    block out on xl1 all
    pass in quick on xl1 proto tcp/udp from 20.20.20.64/26 to any keep state

    block out on xl2 all
    pass in quick on xl2 proto tcp/udp from 20.20.20.128/25 to any keep state

From this arbitarary example, we can already  see  that  our
ruleset is becoming unwieldy.   To make matters worse, as we
add  more  specific  rules  to  our  DMZ  network,  we   add









                            -22-


additional tests that must be parsed for every packet, which
affects the performance of the xl0 <-> xl2 connections.   If
you set up a firewall with a ruleset like this, and you have
lots of bandwidth and a moderate  amount  of  cpu,  everyone
that  has  a workstation on the xl2 network is going to come
looking for your head to place on a platter.   So,  to  keep
your  head  <->  torso  network intact, you can speed things
along by creating rule groups.   Rule groups  allow  you  to
write your ruleset in a tree fashion, instead of as a linear
list, so that if your packet has nothing to do with the  set
of  tests  (say, all those xl1 rules) those rules will never
be consulted.  It's somewhat like having multiple  firewalls
all on the same machine.

Here's a simple example to get us started:

    block out quick on xl1 all head 10
    pass out quick proto tcp from any to 20.20.20.64/26 port = 80 flags S keep
state group 10
    block out on xl2 all

In  this  simplistic example, we can see a small hint of the
power of the rule group.  If the packet is not destined  for
xl1,  the  head of rule group 10 will not match, and we will
go on with our tests.  If the packet does match for xl1, the
quick  keyword  will short-circuit all further processing at
the root level (rule group 0),  and  focus  the  testing  on
rules  which  belong  to group 10; namely, the SYN check for
80/tcp.  In this way, we can re-write  the  above  rules  so
that we can maximize performance of our firewall.

    block in quick on xl0 all head 1
      block in     quick on xl0 from 192.168.0.0/16 to any  group 1
      block in     quick on xl0 from 172.16.0.0/12 to any   group 1
      block in     quick on xl0 from 10.0.0.0/8 to any      group 1
      block in     quick on xl0 from 127.0.0.0/8 to any     group 1
      block in log quick on xl0 from 20.20.20.0/24 to any   group 1
      block in log quick on xl0 from any to 20.20.20.0/32   group 1
      block in log quick on xl0 from any to 20.20.20.63/32  group 1
      block in log quick on xl0 from any to 20.20.20.64/32  group 1
      block in log quick on xl0 from any to 20.20.20.127/32 group 1
      block in log quick on xl0 from any to 20.20.20.128/32 group 1
      block in log quick on xl0 from any to 20.20.20.255/32 group 1
      pass  in           on xl0 all group 1

    pass out on xl0 all

    block out quick on xl1 all head 10
      pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 80
flags S keep state group 10
      pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 21
flags S keep state group 10
      pass out quick on xl1 proto tcp from any to 20.20.20.64/26 port = 20
flags S keep state group 10
      pass out quick on xl1 proto tcp from any to 20.20.20.65/32 port = 53
flags S keep state group 10
      pass out quick on xl1 proto udp from any to 20.20.20.65/32 port = 53
   keep state group 10
      pass out quick on xl1 proto tcp from any to 20.20.20.66/32 port = 53
flags S keep state
      pass out quick on xl1 proto udp from any to 20.20.20.66/32 port = 53
   keep state group 10









                            -23-


    pass in quick on xl1 proto tcp/udp from 20.20.20.64/26 to any keep state

    block out on xl2 all

    pass in quick on xl2 proto tcp/udp from 20.20.20.128/25 to any keep state

Now  you  can  see the rule groups in action.  For a host on
the xl2 network, we can completely bypass all the checks  in
group  10  when  we're  not communicating with hosts on that
network.

     Depending on your situation, it may be prudent to group
your  rules  by protocol, or various machines, or netblocks,
or whatever makes it flow smoothly.

3.10.  "Fastroute"; The Keyword of Stealthiness

     Even though we're forwarding some packets, and blocking
other  packets, we're typically behaving like a well behaved
router should by decrementing the  TTL  on  the  packet  and
acknowledging  to  the entire world that yes, there is a hop
here.  But we can hide our presence from inquisitive  appli-
cations  like  unix  traceroute  which uses UDP packets with
various TTL values to map the hops between two sites.  If we
want  incoming  traceroutes  to  work, but we do not want to
announce the presence of our firewall as a hop, we can do so
with a rule like this:

    block in quick on xl0 fastroute proto udp from any to any port 33434 ><
33465

The  presence  of the fastroute keyword will signal ipfilter
to not pass the packet into the Unix IP  stack  for  routing
which results in a TTL decrement.  The packet will be placed
gently on the output interface by  ipfilter  itself  and  no
such decrement will happen.  Ipfilter will of course use the
system's routing table to figure out  what  the  appropriate
output  interface  really  is,  but it will take care of the
actual task of routing itself.

     There's a reason we used block quick  in  our  example,
too.   If  we  had  used  pass,  and if we had IP Forwarding
enabled in our kernel, we would end up having two paths  for
a  packet  to  come  out of, and we would probably panic our
kernel.

     It should be noted, however,  that  most  Unix  kernels
(and certainly the ones underlying the systems that ipfilter
usually runs on) have far more efficient routing  code  than
what  exists  in  ipfilter,  and  this keyword should not be
thought of as a way to improve the operating speed  of  your
firewall, and should only be used in places where stealth is
an issue.











                            -24-


4.  NAT and Proxies

     Outside  of  the  corporate  environment,  one  of  the
biggest  enticements  of firewall technology to the end user
is the ability to connect several computers through a common
external  interface,  often without the approval, knowledge,
or even consent of their service provider.  To those  famil-
iar  with Linux, this concept is called IP Masquerading, but
to the rest of the world it is known  by  the  more  obscure
name of Network Address Translation, or NAT for short.

4.1.  Mapping Many Addresses Into One Address

     The basic use of NAT accomplishes much the  same  thing
that  Linux's  IP Masquerading function does, and it does it
with one simple rule:

    map tun0 192.168.1.0/24 -> 20.20.20.1/32

Very simple.  Whenever a packet goes out the tun0  interface
with  a  source  address  matching  the CIDR network mask of
192.168.1.0/24 this packet will be rewritten within  the  IP
stack  such  that  its  source address is 20.20.20.1, and it
will be sent on to its original  destination.    The  system
also  keeps  a  list  of  what translated connections are in
progress so that it can perform the reverse  and  remap  the
response  (which  will  be  directed  to  20.20.20.1) to the
internal host that really generated the packet.

     There is a drawback to the rule we have  just  written,
though.   In  a  large  number of cases, we do not happen to
know what the IP address of our outside link  is  (if  we're
using tun0 or ppp0 and a typical ISP) so it makes setting up
our NAT tables a chore.   Luckily, NAT is  smart  enough  to
accept  an  address  of 0/32 as a signal that it needs to go
look at what the address of that interface really is and  we
can rewrite our rule as follows:

    map tun0 192.168.1.0/24 -> 0/32

Now we can load our ipnat rules with impunity and connect to
the outside world without having to edit  anything.  You  do
-----------
  To be pedantic, what IPFilter provides is really
called NPAT, for Network and Port Address Transla-
tion,  which means we can change any of the source
and destination IP Addresses and their source  and
destination  ports.   True  NAT only allows one to
change the addresses.
 This is a typical internal address  space,  since
it's non-routable on the Real Internet it is often
used for internal  networks.    You  should  still
block  these  packets  coming  in from the outside
world as discussed earlier.









                            -25-


have to run ipf -y to refresh the address if you get discon-
nected and redial or if your DHCP lease changes, though.

     Some of you may be wondering what happens to the source
port  when  the mapping happens.  With our current rule, the
packet's source port is unchanged from the  original  source
port.   There  can  be instances where we do not desire this
behavior; maybe we have another firewall further upstream we
have  to  pass  through, or perhaps many hosts are trying to
use the same source port, causing a collision where the rule
doesn't  match and the packet is passed untranslated.  ipnat
helps us here with the portmap keyword:

    map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:30000

Our rule now shoehorns all the translated connections (which
can be tcp, udp, or tcp/udp) into the port range of 20000 to
30000.

4.2.  Mapping Many Addresses Into a Pool of Addresses

     Another use common use of NAT is to take a small stati-
cally  allocated  block  of addresses and map many computers
into this smaller address space.   This is  easy  to  accom-
plish  using what you already know about the map and portmap
keywords by writing a rule like so:

    map tun0 192.168.0.0/16 -> 20.20.20.0/24 portmap tcp/udp 20000:60000

Also, there may be  instances  where  a  remote  application
requires that multiple connections all come from the same IP
address.  We can help with these situations by  telling  NAT
to  statically  map  sessions  from  a host into the pool of
addresses and work some magic to choose a port. This uses  a
the keyword map-block as follows:

    map-block tun0 192.168.1.0/24 -> 20.20.20.0/24

4.3.  One to One Mappings

     Occasionally  it is desirable to have a system with one
IP address behind the firewall to  appear  to  have  a  com-
pletely different IP address.  One example of how this would
work would be a lab of computers which are then attached  to
various networks that are to be put under some kind of test.
In this example, you would not want to have  to  reconfigure
the  entire  lab  when you could place a NAT system in front
and change the addresses in one simple place.    We  can  do
that  with  the  bimap  keyword,  for bidirectional mapping.
Bimap has some additional protections  on  it  to  ensure  a
known  state  for the connection, whereas the map keyword is
designed to allocate  an  address  and  a  source  port  and
rewrite the packet and go on with life.

--

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


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

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