13.4. What Makes a Good Firewalled Service?
The ideal service to run through a firewall is one that makes a
single TCP connection in one direction for each session. It should
make that connection from a randomly allocated port on the client to
an assigned port on the server, the server port should be used only
by this particular service, and the commands it sends over that
connection should all be secure. The following sections look at these
ideal situations and some that aren't so ideal.
13.4.1. TCP Versus Other Protocols
Because TCP is a connection-oriented
protocol, it's easy to proxy; you go through the overhead of
setting up the proxy only once, and then you continue to use that
connection. UDP has no concept of connections; every packet is a
separate transaction requiring a separate decision from the proxy
server. TCP is therefore easier to proxy (although there are UDP
proxies). Similarly, ICMP is difficult to proxy because each packet
is a separate transaction. Once again, ICMP is harder to proxy than
TCP but not impossible; some ICMP proxies do exist.
The situation is much the same for packet
filters. It's relatively easy to allow TCP through a firewall
and control what direction connections are made in; you can use
filtering on the ACK bit to ensure that you allow internal clients
only to initiate connections, while still letting in responses. With
UDP or ICMP, there's no way to easily set things up this way.
Using stateful packet filters, you can watch for packets that appear
to be responses, but you can never be sure that a packet is genuinely
a response to an earlier one, and you may be waiting for responses to
packets that don't require one.
13.4.2. One Connection per Session
It's easy for a firewall to
intercept the initial connection from a client to a server.
It's harder for it to intercept a return connection. With a
proxy, either both ends of the conversation have to be aware of the
existence of the proxy server, or the server needs to be able to
interpret and modify the protocol to make certain the return
connection is made correctly and uniquely. With plain packet
filtering, the inbound connection has to be permitted all the time,
which often will allow attackers access to ports used by other
protocols. Stateful packet filtering, like proxying, has to be able
to interpret the protocol to figure out where the return connection
is going to be and open a hole for it.
For example, in normal-mode FTP the client opens a control connection
to the server. When data needs to be transferred:
- The client chooses a random port above 1023 and prepares it to accept
a connection.
- The client sends a PORT command to the server containing the IP
address of the machine and the port the client is listening on.
- The server then opens a new connection to that port.
In order for a proxy server to work, the proxy server must:
- Intercept the PORT command the client sends to the server.
- Set up a new port to listen on.
Connect back to the client on the port the client specified.
Send a replacement PORT command (using the port number on the proxy)
to the FTP server.
- Accept the connection from the FTP server, and transfer data back and
forth between it and the client.
It's not enough for the proxy server to simply read the PORT
command on the way past because that port may already be in use. A
packet filter must either allow all inbound connections to ports
above 1023, or intercept the PORT command and create a temporary rule
for that port. Similar problems are going to arise in any protocol
requiring a return connection.
Anything more complex than an outbound
connection and a return is even worse. The talk
service is an example; see the discussion in Chapter 19, "Real-Time Conferencing Services", for an example of a service with a tangled
web of connections that's almost impossible to pass through a
firewall. (It doesn't help any that talk
is partly UDP-based, but even if it were all TCP, it would still be a
firewall designer's nightmare.)
13.4.3. One Session per Connection
It's almost as bad to have multiple sessions on the same
connection as it is to have multiple connections for the same
session. If a connection is used for only one purpose, the firewall
can usually make security checks and logs at the beginning of the
connection and then pay very little attention to the rest of the
transaction. If a connection is used for multiple purposes, the
firewall will need to continue to examine it to see if it's
still being used for something that's acceptable.
13.4.4. Assigned Ports
For a firewall, the ideal thing is for
each protocol to have its own port number. Obviously, this makes
things easier for packet filters, which can then reliably identify
the protocol by the port it's using, but it also simplifies
life for proxies. The proxy has to get the connection somehow, and
that's easier to manage if the protocol uses a fixed port
number that can easily be redirected to the proxy. If the protocol
uses a port number selected at configuration time, that port number
will have to be configured into the proxy or packet filter as well.
If the protocol uses a negotiated or dynamically assigned port, as
RPC-based protocols do, the firewall has to be able to intercept and
interpret the port negotiation or lookup. (See
Chapter 14, "Intermediary Protocols", for more information about RPC.)
Furthermore, for security it's desirable for the protocol to
have its very own assigned port. It's always tempting to layer
things onto an existing protocol that the firewall already permits;
that way, you don't have to worry about changing the
configuration of the firewall. However, when you layer protocols that
way, you change the security of the firewall, whether or not you
change its configuration. There is no way to let a new protocol
through without having the risks of that new protocol; hiding it in
another protocol will not make it safer, just harder to inspect.
13.4.5. Protocol Security
Some services are
technically easy to allow through a firewall but difficult to secure
with a firewall. If a protocol is inherently unsafe, passing it
through a firewall, even with a proxy, will not make it any safer,
unless you also modify it. For example, X11 is mildly tricky to
proxy, for reasons discussed at length in
Chapter 18, "Remote Access to Hosts", but the real reason it's difficult to
secure through firewalls has nothing to do with technical issues
(proxy X servers are not uncommon as ways to extend X capabilities).
The real reason is that X provides a number of highly insecure
abilities to a client, and an X proxy system for a firewall needs to
provide extra security.
The
two primary ways to secure inherently unsafe protocols are
authentication and protocol modification.
Authentication allows you to be certain that you
trust the source of the communication, even if you don't trust
the protocol; this is part of the approach to X proxying taken by
SSH. Protocol modification
requires you to catch unsafe operations and at least offer the user
the ability to prevent them. This is reasonably possible with X (and
TIS FWTK provides a proxy called x-gw that does
this), but it requires more application knowledge than would be
necessary for a safer protocol.
If it's difficult to distinguish between safe and unsafe
operations in a protocol, or impossible to use the service at all if
unsafe operations are prevented, and you cannot restrict connections
to trusted sources, a firewall may not be a viable solution. In that
case, there may be no good solution, and you may be reduced to using
a victim host, as discussed in Chapter 10, "Bastion Hosts". Some
people consider HTTP to be such a protocol (because it may end up
transferring programs that are executed transparently by the client).
| | |
13.3. Analyzing Other Protocols | | 13.5. Choosing Security-Critical Programs |