|
January 1, 1996
Internet Firewall Essentials
It seems as if everybody is worried about connecting their organizations
to the Internet these days. There are widespread reports of hackers breaking
into everything from banks to warehouses and gaining unauthorized access
to critical systems. If you're leading an internal World Wide Web development
project for your company, you've probably had to face your own security
advocates who decry the end of pristine systems yet offer no assistance
in researching or developing a mutually satisfactory solution.
Well, here's your help. This chapter of Network Computing's Interactive
Network Design Manual will outline the critical elements for implementing
an Internet firewall in your organization, hopefully in a way that allows
you to choose the solutions that best suit your needs. The options range
from the cheap to the not-so-cheap, from the visible to the invisible,
and from difficult to easy.
As individual requirements will vary, we cannot readily endorse any
one product or approach over another, yet they all offer benefits that
you may want to use. In this new market, most products are only partially
finished -- yet are completely priced -- so your choices will likely
end up as budgetary decisions as much as functional ones.
What, Exactly, is a Firewall?
Almost by definition, a "firewall" provides a filter that
incoming or outgoing packets must pass through. If the firewall does
something beyond filtering, like checking against a restrictions list,
that's great, but it's not necessarily the "definition" of
a firewall's function.
Of course, most firewalls do perform some sort of "accept" or
"reject" functionality, but that's strictly a matter of implementation.
The simplest firewall could just be an Ethernet bridge that you keep
powered off, only to be made available when the connection is needed.
This would probably work for keeping intruders off of your network, but
I doubt you'd enjoy the management interface much. Most firewall products
offer much more in the way of actively filtering packets according to
certain criteria that you establish.
These filtering firewall products can take many forms. They may be
a replacement TCP/IP stack that you load on an existing system, or a
software module that exclusively communicates with an existing stack.
At the other end of the extreme, the product may be a completely independent
operating system written explicitly with Internet security as the objective.
There are also application-specific firewall products that only offer
protection for certain types of Internet connectivity, such as SMTP or
HTTP. There are also hardware-based products that typically fall into
the router realm, allowing you to set filters for incoming and outgoing
connections. Prices range from free (bundled with the stack or app) to
tens of thousands of dollars.
All of these products can rightly be called "firewalls" because
essentially they trap inbound or outbound packets, analyze them, and
then either send them on their way or toss them out. Any one of these
products may or may not suit your needs. Once you've got a handle on
the issues, however, you should be able to do your own product elimination,
simply by comparing functional specifications.
At the least, almost all firewall products offer IP address filtering. These
filters work by examining the header of the IP packet and making pass/fail
decisions based on the source and destination IP addresses. For clarification
purposes, let's look at the figure above, which shows a simple two-segment
network with a firewall separating them. One segment has a UNIX host,
and the other has a PC client.
When the PC client tries to Telnet to the UNIX host, the Telnet client
on the PC generates a TCP packet, and hands it to the local stack for
delivery. In turn, the stack places the TCP packet inside of an IP packet,
and then sends to the UNIX host via the route defined in the PC client's
TCP/IP stack. In our case, the PC client is sending the IP packet to
the firewall for delivery to the UNIX host.
Suppose that we have told the firewall that it is not to accept any
packets destined for the UNIX host, as depicted in below. Then the firewall
would reject the IP packet, perhaps bothering to tell the client or perhaps
not. Since no IP traffic for that destination would get forwarded, only
users on the same segment would be able to access the UNIX host.
Another
scenario might be that the firewall has been configured so that it simply
will not accept any packets from that PC in particular. Then other systems
could connect to the UNIX host, but that specific PC could not.
This type of filtering is the most basic of all. By setting accept
or reject filters per IP address, these types of products can provide
very basic protection mechanisms for a simple LAN. If the systems are
not allowed to communicate because of source or destination IP address
filters, then the packets are simply rejected.
These types of filters are commonly used in smaller shops that need
to control where users can or cannot go, but beyond that they're not
extremely reliable. IP addresses can be spoofed, so using these filters
by themselves are not enough to stop an intruder from getting into your
network. However, it is a fundamental building block of good firewall
design, and is a critical component of a complete defensive infrastructure.
If you do employ IP address filters, then make sure that you use IP
addresses when you create your accept and reject tables, and don't use
DNS host names, since DNS can be spoofed even more easily than IP addresses
can be.
TCP/UDP Port Filtering
Using simple IP address comparison to allow or reject packets is a
brute method of filtering. It doesn't allow for the possibility that
multiple services may be running on the destination host, some of which
we may want to allow users to access. For example, we may not want users
to Telnet into the system, but we may want them to be able to access
the SMTP/POP mail server that's running on it. To enable this level of
control, we have to be able to set filters according to the TCP or UDP
port numbers in conjunction with the IP address filters described earlier.
For example, the default Telnet configuration calls for the server to monitor
TCP port 23 for incoming connections. Therefore, if we know that we do
not want to allow any Telnet connections to our UNIX host from the PC,
we can simply tell the firewall to reject any IP packets going to the
UNIX host that have a TCP destination port number of 23. Since the PC's
Telnet client would normally generate just such a request, the service
would effectively be disabled for it, as depicted above.
It should be pointed out that this type of setup -- where we are explicitly
excluding a port -- is generally a bad idea. If you need to protect a
system, you're better off by rejecting everything, and only accepting
the TCP or UDP packets that you know you want to let through. It may
seem like more work, but it's less work in reality, and has the added
benefit of keeping your systems from being easily compromised. In other
words, of the two approaches -- that which is not forbidden is allowed,
and that which is not expressly allowed is forbidden -- the latter one
is safer.
If we wanted to reverse this example, perhaps using SMTP and POP,
then we would add these services to the acceptable list for the UNIX
host's destination address, and reject all other packets. Therefore,
any connection request bound for the UNIX host which had TCP destination
port addresses of 110 or 25 would be allowed to pass, but no other packets
would, since they wouldn't meet this "allow" condition. This
would include Telnet, thereby providing the "exclude" condition
described above, only with less work (told you so).
By combining the IP addresses and TCP/UDP port numbers, you can develop
some pretty reliable filters. For example, if your internal SMTP mail
server only talks to your Internet Service Provider's (ISP's) mail server,
then you could implement a firewall filter that only allowed incoming
SMTP connections that came from the ISP's mail server, and are destined
for your internal SMTP mail server. This will keep some of the hackers
from being able to exploit any SENDMAIL weaknesses that you haven't plugged.
This level of control is generally where many of the pseudo-firewall
products stop. By allowing you to set your filters so that no incoming
traffic from the Internet can access any ports except the ones you want,
it would seem to preserve your security to a satisfactory degree. However,
this is just not the case.
Clients have TCP/UDP Ports, Too
Since TCP/IP is a peer-to-peer protocol, each node has a unique address.
This philosophy carries up into the applications layer as well, meaning
that applications and services also have addresses (or port numbers).
Since it takes two to tango, both the client and the server must have
unique port numbers on their individual systems in order for a TCP or
UDP connection to be established. For example, the Telnet server listens
for incoming connections on port 23. However, the Telnet client also
has a port number. Without this, the client's IP stack would not know
which application the packet was for.
Historically, almost all TCP/IP client applications use a randomly
assigned port number above 1023 for their end of the connection. This
is a legacy from TCP/IP's roots in the UNIX world. On UNIX systems, only
the root account has access to ports below 1024, which are reserved for
server services (like Telnet, FTP, etc.). In order to allow client applications
to work, they must use port numbers above 1023.
For you to allow any sort of connection to work then, you must allow any
packet with destination port numbers higher than 1023 to come into your
network. If the response packets are not returned, the client will not
be able to establish a connection.
In terms of Internet firewalls, this can cause some problems in design.
If you are to block all incoming ports, then you have just kept all of
your clients from being able to use Internet resources. The inbound packets
that are the responses to their external connection requests will not
survive the firewall's inbound filters.
You may think that it's okay to open up all ports above 1023. Not
so. There are a lot of services that run on ports higher than 1023, such
as X clients, and RPC-based services like NFS and NIS/YP. Most of the
non-UNIX IP-specific products -- like NetWare/IP for example -- use port
numbers that are above 1023 as well. This means that if you let any old
packet that meets the above-1023 criteria into your network, then you're
exposing those systems to attack, and none of them are particularly well
known for their robust security mechanisms.
Build Bi-Directional Filters
One potential solution to this problem is to build bi-directional filters
into your firewall. You may want to define the filters so that you only
allow packets that are from well-known services into your network, and
reject any packets that are not from specific applications. For example,
if you know that your users will be accessing World Wide Web servers,
then you could only allow packets that have a source port number of 80
into the network, as illustrated below.
Unfortunately, there are a couple of problems with this solution as well. First of all,
you don't always know what port numbers the servers that you are trying
to access are running on. Modern day servers such as HTTP and Gopher
are completely configurable in this manner, allowing you to run them
on any port that you want to. If you implement this type of filter, then
your users will not be able to access those sites that do not use the "standard"
port numbers that you expect them to.
Another security problem comes from the fact that there is no way
for you to know for sure that the packets coming into your network from
port 80 are indeed response packets from a World Wide Web server. Some
hacker may have compiled their own network invasion tool that runs on
port 80 on their machine, thereby making their insidious data look perfectly
harmless, at least to your firewall anyway. If they can get into your
network just by setting their application's source port manually, then
they can do whatever they want with the vulnerable systems, and your
firewall will be useless.
Check the ACK Bit
If you can't trust the source IP addresses, and you can't even trust
the source port numbers, then it doesn't seem like you can do much in
the way of protecting your network from intruders. However, there is
one fool-proof mechanism that you can use reliably, although only with
TCP.
TCP is a "reliable" protocol that supports error-correction
and other robust capabilities. To achieve this reliability, every TCP
connection begins with a handshaking sequence that establishes specific
parameters of the connection. Also, every packet that gets sent must
be responded to with an acknowledgment before another packet will get
sent.
Rather than generate special-purpose ACK packets for every TCP packet,
a special bit in the TCP header is used for just this purpose. Therefore,
whenever a response packet is generated, the ACK bit gets set, and a
marker is noted to indicate what packet the ACK is for. The very first
packet in a negotiation is not acknowledging anything, and so it does
not have the ACK bit set. However, every subsequent TCP packet in an
exchange must have the ACK bit set for the connection to be maintained.
For example, if the PC opens a connection with a remote World Wide Web server,
it generates a connection request packet that does not have the ACK bit
set. When the server responds to this request, it sends a packet with
the ACK bit set, and with the marker set to the number of bytes received
from the client. The client then responds to this packet with its own
response packet, which also has the ACK bit set and with its own marker
also set to the number of bytes of data received from the server. The
figure above illustrates this series of events visually.
By monitoring the ACK bit, you can limit the types of incoming data
to only response packets. This means that a remote system cannot initiate
a TCP connection at all, but can only respond to packets that have been
sent to it.
Nor can an outsider manually set the ACK bit for their first packet,
thereby blowing past your security. The receiving node will see that
the packet is an acknowledgment for a packet that it sent (referenced
by the marker) and will discard it, as it would not be able to recall
any such packet ever being sent.
This one trick by itself can go a long way towards protecting your
network from invasion. If you can configure your firewall so that it
will only give entrance visas to TCP packets that have the ACK bit set,
then you are guaranteeing that no packets that have not been explicitly
requested will arrive on your internal network.
This mechanism is not a panacea however, and is not usable in several
situations. For example, if you have an internal World Wide Web server
or some other data that you wish to provide on a public basis, then you
would have to open port 80 (or whatever ports were to be used) so that
external requests for connections could come into your network. Also,
monitoring TCP packets for the ACK bit doesn't help at all with UDP packets,
as they don't have any ACK bit. Some TCP applications are designed so
that they initiate some connections, and these applications cannot work
across a firewall that does not allow incoming connections. One such
program is FTP.
The Problem With FTP
Unlike most of the Internet services that use a single pair of port
numbers for all communications, FTP uses two pairs of port numbers during
connections. The first pair is used for the FTP "command channel" that
provides a communications line for logging in and executing commands,
while the other pair is used for the FTP "data channel" that
is used for sending files or directory listings between the client and
server.
During a normal FTP session, the client will send a TCP connection
request to port 21 (the "command" channel) on the server, and
then execute commands such as LOGIN, DIR, and the like. Once the user
requests that data be sent, the FTP server uses its local port 20 (the "data" channel)
to initiate a connection to the client's "data" port. This
presents a spectacular problem. If the server is going to initiate a
connection to the client for the data transfer, then it will send a packet
that does not have the ACK bit set, meaning your firewall will reject
it, and thus the file transfer will never get started, much less finished.
Only an advanced firewall will recognize that the client does actually
tell the external server which port to use, and thus the firewall will
allow incoming connections for ports that it has seen the client tell
the server to use.
There is a workaround for this scenario however. Many FTP clients
and servers support the use of "passive mode" file transfers
(named after the PASV command), which allow the client to initiate the
file transfer connection. Rather than the server using port 20, when
it receives the PASV command it allocates a port above 1023, and informs
the client of its choice (via the command channel). The client then initiates
the TCP connection to the port number provided, and the server then begins
to transfer data. Not all clients or servers support the PASV command,
so this won't work in all situations, although it is becoming much more
common. Almost all Web browsers use PASV mode by default, and almost
every FTP client worth looking at supports it as well.
UDP Port Filtering
As I said earlier, monitoring the ACK bit in incoming TCP packets is
a very effective way to allow outbound TCP connections. However, UDP
doesn't offer this type of capability, since it does not have any ACK
functionality. UDP is designed for unreliable transmissions which do
not require or benefit from negotiated connections. These types of services
generally include broadcasts, routing protocols, and other "maintenance" packets
that advertise services. Unfortunately, there are lots of other services
that use UDP as well, including NFS, NTP, DNS, WINS, NetBIOS-over-TCP/IP,
and NetWare/IP. These types of services can be corrupted pretty easily,
or used as launching pads for additional attacks on your network.
One possible solution to this problem is to simply not allow any incoming
UDP connections. To enable this functionality, you need to be able to
configure your firewall so that it will forward UDP packets received
from the internal interface, but will not forward UDP packets received
from the external interface. While this will certainly prevent any incoming
UDP connections, it will not always be feasible.
For example, DNS name resolution requests use UDP, so if you are providing
your own DNS services, then you must allow at least some internal connection
requests to pass through your firewall. Also, there are client applications
like Archie and IRC which use UDP, and if you want to provide them to
your users you will need to let the appropriate response packets into
your network.
You'll need to provide for some sort of UDP connectivity, whether
it is for end-user applications or for system level services like DNS.
About the only thing that you can do is to limit these connections to
somewhat "trusted"
sites. For example, you may want to filter DNS so that only UDP packets
between your internal DNS server and your ISP's DNS server are allowed
to cross the wire. Likewise, you could filter Archie packets so that
only the UDP packets from a specific Archie server were allowed into
the network. Talk, being a relatively uncontrollable application, is
not easily configurable for filtering, and would likely have to be cut
off altogether.
There is a risk with allowing even well-known hosts to send packets
into your network, however. If a hacker can spoof the IP address of the
host that you have given clearance to, then they can take advantage of
your internal system, albeit to a limited degree. A new breed of packet-filtering
routers are becoming available that attempt to solve this problem by "remembering"
outbound UDP packets. If an incoming UDP packet matches the destination
address and port number of a recent outgoing UDP packet, then it is allowed
in. If no recent packet can be found in memory, the firewall will reject
the packet.
Again, the fundamental problem with this approach is that there is
no way of knowing for sure that the outside host generating the packet
is indeed the service that the internal client is expecting to communicate
with. If a hacker were to spoof the IP address of your ISP's DNS server,
then they could theoretically launch an attack from the UDP port associated
with DNS. However, this particular weakness would exist anyway if you
were filtering UDP packets so that only DNS queries and results from
your ISP were allowed into the network. Your situation is neither improved
nor degenerated by deploying these dynamic packet-filtering products.
Proxy and Bastion Servers
One solution to these problems has been to utilize proxy servers or
bastion hosts. These systems run from simple application redirectors
to complete fully-intelligent routers that act as application agents
on behalf of your network.
At the low end of the scale, products such as the CERN HTTPD server
can provide proxy connections to remote FTP, Gopher and HTTP servers
on behalf of your internal clients, thereby preventing them from connecting
to remote systems directly. This has the effect of making these specific
connections somewhat secure, as you can trust your proxy server to a
certain degree, and do not have to allow any incoming connections from
outside sources.
At the high-end, complete security-centric products that offer communication
replacement functions don't allow any direct connections at all, and
force everything to be examined and filtered for suitability. For example,
BorderWare's Firewall Server offers proxy functionality like the CERN
offering, but also provide public and private DNS servers, secure mail
servers, and a variety of other functions. Since these products have
multiple adapters, they essentially act as intelligent routers, rewriting
packets in memory on a per-connection basis, rather than simply forwarding
packets between the external and internal interfaces. These types of
products can be extremely expensive, but they are also your best bet
if this level of security is required.
Additional Concerns
There are other issues and concerns that even the fully-functional
bastion systems offer no value with. You still have to concern yourself
with some of the essential puzzlers of Internet security.
For example, IP addresses can be spoofed, so that a sinister host
appears to be a trusted host. This is often accomplished through the
use of IP's source-routing option, which essentially tells the routers
not use their normal routes for delivery of the packet, but to send it
via the router identified in the packet's header. This lets a hacker
use another system's IP address, and get the packets back, regardless
of what routes are in between him and the destination. Some of the higher-end
products allow you to disable or ignore the source routing bit, but not
all of them.
Disabling source routing can be a good thing to do. For Internet connectivity,
you generally have one path out of your network, and that's through the
ISP. If you disable source routing, you'll just return the packets back
through your normal routing channels. The ISP will have to deliver the
packets to the destination as they see fit. As your response packets
will not have source-routing headers (since you've turned it off), the
responses will follow the Internet's general routing tables.
Also, you will need to find out what the firewall product you are
considering does when it rejects a packet. Does it send an ICMP "host
unreachable"
message back to the originating system, or does it send an ICMP "host
administratively unreachable" message, or does it not do anything
at all? Each of these scenarios have different security implications,
and may make a difference in your choice of product.
The ICMP "host administratively unreachable" message will
tell a hacker that a firewall is specifically blocking a specific port,
which may be more information that you want to give out. The ICMP "host
unreachable" error can be interpreted literally by older systems,
who will then stop trying to send any packets at all to that host, which
may not be the desired effect, either. Sending nothing back at all will
cause the originating system to continually try to establish the connection
until the application or stack times out, which can be annoying to end
users who have made a simple mistake.
Sending nothing back is probably the safest method of the three, since
a hacker cannot tell whether or not a port is blocked or simply not in
use, but only that no responses come back at all.
Written by Eric
A. Hall.
Copyright © 1996 CMP Media, Inc. Used with permission. |