FTP and PF

Most modern application protocols run over a single network connection. If you make a web request, your browser opens a connection to the server on port 80, requests information, and receives the answer, all on the same connection. SSH opens a single connection on port 22 and exchanges all information over that port, even if you tunnel a hundred other protocols inside it. Experience and experiments with older protocols taught the wisdom of this approach. FTP is an older protocol, and it provides a wealth of experience on how not to do things.

The original version of FTP (today called active FTP) required the client to connect to the server on port 21. The server would then open a connection back to the client, from port 20 to some random high-numbered port on the client for sending information. The connection from server to client is called the data connection, or the back channel. The FTP client and server agree on the ports to be used and how the second connection will be used. On a network protocol level, however, no connection exists between the client’s connection to port 21 and the server’s connection from port 20, so there’s no way for a firewall to use stateful inspection to sort out if such a connection is allowed. Worse, if the client is behind a NAT device, there’s no way to determine to which private IP address the firewall should route an incoming FTP data request.

Passive FTP is an updated version of the FTP protocol where the client initiates both TCP connections. All modern clients and servers support passive FTP. The differences between active and passive FTP spark endless rounds of user education and increased help-desk load, especially if you’re trying to use FTP through a web browser. (And if anyone is going to break my help desk staff, it’s going to be me!) Active FTP simplified firewall rules, because the firewall didn’t need to allow the back channel. Unfortunately, the creators of passive FTP called the modified protocol FTP. Clients don’t care about active or passive, they just want “this FTP thing” to work, regardless of the actual protocol underlying it.

To complicate things, some FTP servers and clients implement something between active and passive FTP. The FTP protocol has been around for decades (it predates TCP/IP), and people have tweaked and “improved” it for years. Getting a random combination of FTP server and client through a random NAT device and a packet filter can cause nightmares, or at least require opening a wide range of TCP ports.

OpenBSD and PF get around this problem by including an FTP application proxy, ftp-proxy(8). When a client makes an FTP request, PF intercepts the request and reroutes it to the application proxy. The proxy tracks the FTP protocol transactions, uses anchors to insert the appropriate rules into the firewall, and removes the rules when the transfer finishes. Strictly speaking, ftp-proxy isn’t a traditional proxy. Data doesn’t actually go through ftp-proxy; the “proxy” adjusts the firewall rules so that traffic can pass. The proxy requires two parts: a running ftp-proxy instance and the redirect rules.

Configuring ftp-proxy(8)

Like any other OpenBSD daemon, ftp-proxy is enabled in /etc/rc.conf.local. There’s no configuration file—only command-line arguments. By default, ftp-proxy automatically listens on port 8021 on the loopback interface. It’s very rare for me to add any command-line arguments for ftp-proxy for routine use.

ftpproxy_flags=""

If I’m debugging a problem, however, I might run ftp-proxy in the foreground, in debugging mode. Doing this shows me all FTP transactions as they occur.

# ftp-proxy -dD7

This displays everything that passes through the FTP proxy, including the ports used for the data channel back to the client. Press CTRL-C to stop ftp-proxy.

The most common problem I have with ftp-proxy is that nothing appears in the debugging terminal. That means that the firewall isn’t diverting any traffic to the proxy. Check your pf.conf file to verify that you have the necessary rules to support the FTP proxy.

PF Configuration and the FTP Proxy

PF must know to send FTP requests to ftp-proxy. There’s a good example configuration in the default pf.conf file:

anchor "ftp-proxy/*"
pass in quick inet proto tcp to port ftp divert-to 127.0.0.1 port 8021
pass out inet proto tcp from (self) to any port ftp

Here’s where we use anchors. The ftp-proxy/* anchor can contain sub-rulesets. The ftp-proxy daemon modifies these anchors on the fly to configure the necessary traffic or data connections. The second rule declares that PF will divert any traffic addressed to the FTP port (21 as per /etc/services) to port 8021 on the localhost. The third rule says that the firewall host can send TCP port 21 traffic to any other host. This rule contains a new term, (self), which is PF shorthand for “all IP addresses on the localhost.”

How can you be sure this works? First, find an FTP server that supports active FTP. Open your FTP client and log in to the server, going through the firewall. Once you log in, use the pasv command at the FTP prompt. This command turns passive mode on and off. If the server doesn’t recognize pasv, it supports only passive FTP. Find another FTP server for this test. Once the FTP server reports that “passive mode is off,” list the contents of a directory. Directory listings, like data files, come over the data channel.

During the data transfer of an active FTP connection, you should see rules in the ftp-proxy/* anchor.

# pfctl -a "ftp-proxy/*" -sr
anchor "6837.2" all {
  pass in log (all) quick on rdomain 0 inet proto tcp from 129.128.5.191 to 139.171.202.34 port = 62323 flags S/SA keep state (max 1) rtable 0 rdr-to 192.0.2.2 port 64280
  pass out log (all) quick on rdomain 0 inet proto tcp from 129.128.5.191 to 192.0.2.2 port = 64280 flags S/SA keep state (max 1) nat-to 129.128.5.191
}

The rules created by ftp-proxy are very specific. They permit only one connection, from a particular server to a particular client, with address translation rules to make each side think it’s actually talking to the proper client or server.

Note

To learn how to restrict your clients to using only anonymous FTP, or how to use ftp-proxy to permit inbound FTP access to a server inside your firewall, read the ftp-proxy(8) man page.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.70.21