Главная страница


ru.unix.bsd

 
 - RU.UNIX.BSD ------------------------------------------------------------------
 From : Dmitry Podolsckiy                    2:50/441       19 May 2000  19:42:33
 To : Alex Prohorenko
 Subject : ip filter
 -------------------------------------------------------------------------------- 
 
 
                         Alex Prohorenko wrote to All:
 
  AP> Как в IP Filter выставь передресацию с порта машинки видимой внешне на
  AP> внутреннюю?
  Вот, откопал кое-что. Может кому будет интеpесно. ;)
 
 ==================
 IP Filter is a neat little firewall package.  It does just about
 everything other free firewalls (ipfwadm, ipchains, ipfw) do, but
 it's also portable and does neat stuff the others don't.  This
 document is intended to make some cohesive sense of the sparse
 documentation presently available for ipfilter.  Some prior
 familiarity with packet filtering will be useful (too much familiarity
 may make this document a waste of your time).  There's probably
 numerous books on the subject that would be beneficial to read.  I
 used TCP/IP illustrated, myself.  On we go.
 Part 1 - Config File Dynamics, Order and Precedence
 IPF (IP Filter) has a config file (as opposed to say, running some
 command again and again for each new rule).  The config file drips
 with Unix:  There's one rule per line, the "#" mark denotes a comment,
 and you can have a rule and a comment on the same line.  Extranious
 whitespace is allowed, I use it to keep my rules readable.
 The rules are read from top to bottom, each one appended after
 another.  This quite simply means that if the entirety of your config
 file is:
 block in all
 pass  in all
 The computer sees it as:
 block in all
 pass  in all
 Which is to say that when a packet comes in, the first thing IPF applies is:
 block in all
 Should IPF deem it necessary to move on to the next rule, it would then
 apply the second rule:
 pass  in all
 At this point, you might want to ask yourself "would IPF move on to the
 second rule?"  If you're familiar with ipfwadm or ipfw, you probably
 won't ask yourself this.  Shortly after, you will become bewildered
 at the weird way packets are always getting denied or passed when
 they shouldn't.  Many packet filters stop comparing packets to
 rulesets the moment the first match is made- IPF is not one of them.
 Unlike the other packet filters, ipf keeps a flag on whether or not
 it's going to pass the packet.  Unless you interrupt it, it'll go
 through the entire ruleset, making its decision on whether or not to
 pass or drop the packet based on the last matching rule.  The scene:
 IP Filter's on duty.  It's been been scheduled a slice of CPU time.
 It has a checkpoint clipboard that reads:
 block in all
 pass  in all
 A packet comes in the gateway and it's time to go to work.  It
 takes a look at the packet, it takes a look at the first rule:
 block in all
 "So far I think I will block this packet" says IPF.  It takes a
 look at the second rule:
 "So far I think I will pass this packet" says IPF.  It takes
 a look at a third rule.  There is no third rule (a null pointer
 is dereferenced, signal 12, kernel panic- AIiiyyee!), so it
 goes with what its last motivation was, to pass the packet
 onward.
 It's a good time to point out that even if the ruleset had been
 block in all
 block in all
 block in all
 block in all
 pass  in all
 that the packet still would have gone through.  There is no cumulative
 effect.  The last matching rule always takes precedence.
 I'm sure there's a good use for this method of layout, but I must confess
 that I don't yet grasp it.  It has some horrible aspects in the area of
 portability and speed.  Imagine converting your old filters to this format,
 Imagine if you had 100 rules and most of the applicable ones were
 the first 10. There would be a terrible overhead for every packet
 coming in to go through 100 rules every time.  Fortunately, there's
 a simple keyword you can add to any rule that makes it take action
 at that match.  The keyword is "quick."
 Here's a modified copy of the original ruleset using the quick keyword:
 block in quick all
 pass  in       all
 In this case, IPF looks at the first rule:
 block in quick all
 The packet matchs and the search is over.  The packet is expunged without
 a peep.  There are no notices, no logs, no memorial service.  Cake will
 not be served.  So what about the next rule?
 pass  in       all
 This rule is never encountered.  It could just as easily not be in the
 config file at all.  The sweeping match of "all" and the terminal keyword
 "quick" from the previous rule make certain that no rules are followed
 afterward.
 Having half a config file laid to waste is rarely a desirable state.
 On the other hand, IPF is here to block packets and as configured,
 it's doing a heck of a good job.  Nonetheless, IPF is also here to
 let *some* packets through, so a change to the ruleset to make this
 possible is called for.
 IPF will match packets on numerous criteria.  The one that we most commonly
 think of is the IP address.  There are some blocks of address from which we
 should never get traffic.  One such block are the unroutable networks such
 as 192.168.0.0/16 (/16 being a netmask.  Perhaps you are more familiar with
 the wordier version of 255.255.0.0).  If you wanted to block 192.168.0.0/16,
 this is one way to do it:
 block in quick from 192.168.0.0/16 to any
 pass  in       all
 Now we have a less stringent ruleset that actually does something for us.
 Lets imagine a packet comes in from 1.2.3.4.  The first rule is applied:
 block in quick from 192.168.0.0/16 to any
 The packet is from 1.2.3.4, not 192.168.*.*, so there is no match.  The
 second rule is applied:
 pass  in       all
 The packet from 1.2.3.4 is definitely a part of all, so the packet is
 sent to wherever it happened to be going.
 On the other hand, suppose we have a packet that comes in from 192.168.1.2.
 The first rule is applied:
 block in quick from 192.168.0.0/16 to any
 There's a match, the packet is dropped, and that's the end.  Again, it
 doesn't move to the second rule because the first rule matches and contains
 the "quick" keyword.
 Every packet you recieve comes from a network interface.
 From a modem speaking PPP to ethernet cards talking 10 base-T,
 there's an interface involved.  Say your machine has 3 interfaces,
 lo0 (loopback), xl0 (3com ethernet), and tun0 (FreeBSD's generic tunnel
 interface that ppp uses), but you don't want packets coming in on the
 tun0 interface?
 block in quick on tun0
 pass  in       all
 In this case, the "on" keyword means that that data is coming in
 on the named interface.  If a packet comes in on tun0, the first
 rule will block it.  If a packet comes in on lo0 or xl0, the first
 rule will not match, the second rule will, the packet will be passed.
 It's an odd state of affairs when one decides it best to have the
 tun0 interface up, but not allow any data to be recieved from it.
 The more criterea the firewall matches against, the tighter (or
 looser) the firewall can become.  Maybe you want data from tun0,
 but not from 192.168.0.0/16?  This is the start of a powerful
 firewall.
 block in quick on tun0 from 192.168.0.0/16 to any
 pass  in       all
 A packet from 192.168.1.1 on the xl0 interface will get passed.
 A packet from 1.2.3.4 on the tun0 interface will get passed.
 Infact, every packet from everywhere will be allowed in, except
 for packets from 192.160.0.0/16 on tun0.
 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
 The first three address blocks are the unroutable IP space.  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 external
 entrance is a good idea.
 It seems very frequent that companies have internal networks before
 they want a link to the outside world.  I'd even go so far as to
 say that's the main reason people consider firewalls in the first
 place, though they're just as important for a single machine as
 for an office network.  The machine that bridges the outside world
 to the inside world and vice versa is the router.  What separates
 the router from any other machine is simple: It has two interfaces.
 We'll call them tun0 for the external link and xl0 for the internal
 link.
 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 illegitimate 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 200.200.200.0/24, you know that the only traffic for that internal
 network is going to come off the local ethernet.  Should a packet from
 200.200.200.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 destination.  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
 block in quick on tun0 from 200.200.200.0/24 to any
 pass  in       all
 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 200.200.200.0/24.  To do this, we add the "log"
 keyword:
 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 200.200.200.0/24 to any
 pass  in       all
 [a month passes while I become fascinated with thingamajigs, gadgets
  and other non-ipf related gadgets]
 There's a couple other things you may need to do, too.  If you're
 running FreeBSD, you'll need to have IPFILTER_LOG compiled into
 your kernel.  Second, ipf requires ipmon to log, no matter what OS
 you're using.  I prefer to run ipmon with as "ipmon -s" so it
 syslogs logged packets instead of having them dump to stdout.
 So far, our firewall is pretty good at blocking packets coming to
 it from suspect places, but there's still more to be done.  For one
 thing, we're accepting packets destined anywhere.  One thing we ought
 to do is make sure packes to 200.200.200.0/32 and 200.200.200.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
 network from being used as a smurf relay:
 block in log quick on tun0 from any to 200.200.200.0/32
 block in log quick on tun0 from any to 200.200.200.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 200.200.200.0/24 to any
 block in log quick on tun0 from any to 200.200.200.0/32
 block in log quick on tun0 from any to 200.200.200.255/32
 pass  in       all
 Denial of Service attacks are almost as rampant as buffer overflows.
 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.
 Of course, this isn't really an ideal situation.  Why not drop all ICMP?
 Well, because it's useful.  So maybe you want to keep some types of ICMP
 traffic.  If you want ping and traceroute to work, you need to let in
 icmp types 8 and 11.  Strictly speaking, this might not be a good idea,
 but if you need to weigh security verses convenience, ipf lets you do it.
 pass in quick on tun0 proto icmp from any to 200.200.200.0/24 icmp-type 8
 pass in quick on tun0 proto icmp from any to 200.200.200.0/24 icmp-type 11
 Remeber 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 200.200.200.0/24 icmp-type 8
 pass  in     quick on tun0 proto icmp from any to 200.200.200.0/24 icmp-type 11
 block in log quick on tun0 proto icmp from any to any
 Now to put it all together:
 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 200.200.200.0/24 to any
 block in log quick on tun0 from any to 200.200.200.0/32
 block in log quick on tun0 from any to 200.200.200.255/32
 pass  in     quick on tun0 proto icmp from any to 200.200.200.0/24 icmp-type 8
 pass  in     quick on tun0 proto icmp from any to 200.200.200.0/24 icmp-type 11
 block in log quick on tun0 proto icmp from any to any
 pass  in       all
 Please note the location of the icmp rules.  They're intentionally placed
 behind the first 7 blocking rules because we don't want to accidentally
 pass some icmp traffic that would have been dropped by the anti-spoofing
 and anti-smurfing rules.  It's very important to keep a close eye on what
 you "pass" before all the relevent "block" rules are run.
 Now that we've started blocking packets based on protocol, we can start
 blocking packets based on protocol ports.  Services such as rsh, rlogin,
 and telnet are all very convenient to have.  They're also hidiously
 insecure against network sniffing and spoofing.  One great compromise is
 to only allow the services to run internally, then block them externally.
 Both rlogin, rsh, and telnet use specific TCP ports (513, 514, and 23
 respectively).  Creating rules to block them is easy:
 block in     quick on tun0 proto tcp from any to 200.200.200.0/24 port = 513
 block in     quick on tun0 proto tcp from any to 200.200.200.0/24 port = 514
 block in     quick on tun0 proto tcp from any to 200.200.200.0/24 port = 23
 Make sure all 3 are before the "pass in all" and those ports are good to
 not go:
 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 200.200.200.0/24 to any
 block in log quick on tun0 from any to 200.200.200.0/32
 block in log quick on tun0 from any to 200.200.200.255/32
 pass  in     quick on tun0 proto icmp from any to 200.200.200.0/24 icmp-type 8
 pass  in     quick on tun0 proto icmp from any to 200.200.200.0/24 icmp-type 11
 block in log quick on tun0 proto icmp from any to any
 block in     quick on tun0 proto tcp from any to 200.200.200.0/24 port = 513
 block in     quick on tun0 proto tcp from any to 200.200.200.0/24 port = 514
 block in     quick on tun0 proto tcp from any to 200.200.200.0/24 port = 23
 pass  in       all
 You might also want to block udp/111 (portmap), tcp/515 (lpd), tcp/udp
 (2049), tcp/6000 (X) and so on and so forth.  You can get a complete
 listing of the ports being listed to by using "netstat -a" or lsof, if
 you have it installed.  Blocking udp is the same as tcp.  The rule for
 portmap would be:
 block in     quick on tun0 proto udp from any to 200.200.200.0/24 port = 111
 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 service?
 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 quick
 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 tcp/80 and that's it.
 We can do that.  We can do that with a eecond rule, and you already
 know how:
 pass  in quick on ed0 proto tcp from any to 200.200.200.1/32 port = 80
 block in quick on ed0
 This machine will pass in port 80 traffic for 200.200.200.1, and deny
 everything else.  Perhaps this is all one needs?
 Well, I usually find myself needing more.  I want to be able to telnet
 out over the ed0 interface.  I want convenience and security in one.
 Lots of people seem to, that's why ciscos have an "established" clause
 that lets established tcp sessions go through.  Ipfw has established.
 Ipfwadm has setup/established.  They all have this feature, but the
 name is very misleading.
 When I first saw it, I thought it meant my 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.  That's why they only support established TCP connections,
 that's the only protocol that has flags which the router can
 extrapolate the established state of the connection.  Anybody who can
 create a packet with bogus flags can get by such a firewall.
 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 udp and icmp, not just tcp.  The
 only problem is this: the way it does it is non-intuitive.  Ipf calls
 it "keeping state".  The keyword for the ruleset is "keep state" (There
 is also "keep frags", which is advisable as well).
 Keeping state's setup is weird.  Normally, we know that when we want a
 packet to come in, we used "pass in" and when we want one coming in to
 be blocked we use "block in.".  State is different in that, if you want
 a packet to come in, you say "pass out".  By passing the packet out,
 a reciprical rule is created that allows a reply to come back in the
 other direction.  Lets show this as an actual rule:
 pass out quick proto tcp from 200.200.200.1/32 to any keep state
 Thought it doesn't say so, you must imagine there being an auxillery
 rule that exists in the same place in line that reads:
 pass in quick proto tco from ThatIpISentTo to 200.200.20.1/32
 There is no way to express the previous line, don't even try putting
 it in there, it won't work.  The "keep state" option makes it implicit.
 Here's what our ruleset looks like now:
 pass out quick in ed0 proto tcp from 200.200.200.1/32 to any keep state
 pass  in quick on ed0 proto tcp from any to 200.200.200.1/32 port = 80
 block in quick on ed0
 The workings of the keep state ruleset is much like the workings of the
 saying "do not speak until spoken to."  It's just not permitted (except
 on port 80:-).  Actually, lets keep state on udp and icmp packets as
 well:
 pass out quick in ed0 proto tcp/udp from 200.200.200.1/32 to any keep state
 pass out quick in ed0 proto icmp    from 200.200.200.1/32 to any keep state
 pass  in quick on ed0 proto tcp from any to 200.200.200.1/32 port = 80
 block in quick on ed0
 Ipf has a tcp/udp shorthand.  It's actually two rules, but you can
 write it as one.  Now we're keeping state on tcp, udp, icmp.  That
 means we can make outgoing connections with ease.  Nothing is denied
 to us, but the outside world can only send packets to our port 80 with
 any sort of freedom.
 Lets take a look at what happens, rule by rule, if I ping to www.3com.com:
 First, a DNS packet is generated, because I don't know the IP address of
 www.whitehouse.gov.  DNS uses UDP, so the first rule matches, the packet
 is passed, and ipf lets my nameserver's IP reply back to me (since I
 spoke to it before it spoke to me).  It told me www.3com.com is at
 192.156.136.22.  Now I send an icmp packet to 192.156.136.22.  The second
 rule matches this since it's an icmp packet.  The packet goes out, an
 exception is made for a reply to come back, the reply comes back, the
 exception is removed.  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.
 For added scrutiny, we might consider changing
 pass  in quick on ed0 proto tcp from any to 200.200.200.1/32 port = 80
 to:
 pass in quick on ed0 proto tcp from any to 200.200.200.1/32 port = 80 flags S
 keep frags
 This will only let packets through to port 80 if they have a Syn flag.  This
 is handy in detecting Fin scans (where the Fin flag is set).
 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     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 200.200.200.0/24 to any
 block in log quick on tun0 from any to 200.200.200.0/32
 block in log quick on tun0 from any to 200.200.200.255/32
 pass out quick in ed0 proto tcp/udp from 200.200.200.1/32 to any keep state
 pass out quick in ed0 proto icmp    from 200.200.200.1/32 to any keep state
 pass in  quick on ed0 proto tcp from any to 200.200.200.1/32 port = 80 flags S
 keep frags
 block in quick on ed0
 Now we're looking pretty good.
 ===============
 
   Cheers,
    \Dmitry.
 
 --- GoldED+/EMX 1.1.1.2
  * Origin: 7-096-64-186-97,9600,MO,V34,H16,U,TVd (2:50/441)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 ip filter   Alex Prohorenko   19 May 2000 08:51:15 
 ip filter   Dmitry Podolsckiy   19 May 2000 19:42:33 
 Re: ip filter   Dmitry Grigorovich   22 May 2000 04:21:56 
Архивное /ru.unix.bsd/10203392599db.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional