荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: 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软件 网络书店