![]() | ![]() |
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.
For example, in normal-mode FTP the client opens a control connection to the server. When data needs to be transferred:
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.
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.)
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.
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).