Red Hat Linux 9 firewall - update 2


 

 

 

 

 

Introduction to this webpage

This web page is a second update to the previous ones, about using Red Hat Linux 9 as a firewall. It has several sections, but they are all related to getting ftp through the firewall.

If you haven`t read the previous pages, this page will not make much sense.

 

Introduction to ftp

Ftp is a rather old and insecure protocol.

Iana has specified that port 21 is used for the ftp control dialogue between the ftp client and the server - this is a Telnet look-alike session, with a set of known commands, and specific responses.

The ftp server uses port 21 for the control session, but the client workstation doesn`t.

Iana has also specified that port 20 is used for data transfer between the ftp client and the server - but it usually isn`t used by either the server or the client workstation.

Getting ftp through the firewall has turned out to be quite tricky.

There are three problems that have caused this - dynamic port allocation, the ftp protocol itself, and network address translation.

 

Dynamic port allocation

Modern workstation operating systems have the characteristic that they assign port numbers dynamically, with each new ip connection being given a new port number.

Presumably this has been done as a security mechanism, however in many circumstances the port number sequence is quite predictable. Windows NT, Windows XP, and Red Hat Linux 9 all work in a similar way.

When the operating first boots up, the first ip connection has a port number starting value - in Windows NT and Red Hat Linux 9 it is around 1025.

In Windows XP it is a bit more complicated, during the boot-up period, some ip connections use port numbers 1025 upwards, while some others use port numbers 3000 upwards. Once XP has booted up, new ip connections use port numbers from 3000 upwards.

Each subsequent new related connection adds 1 to the previous port number.

Each subsequent new unrelated connection adds 1 or 2 or 3 to the previous port number.

This mechanism is the same for all ip connections, it doesn`t matter which protocol is sitting above ip.

So for example, if you open a web browser, type in a URL, then press return, the browser requests a new ip connection, and let`s say the operating system selects 3123 as the client port number ( the destination port is of course the standard http port of 80 ).

If now there is a link to an ftp server on this site to allow file downloads, this is a related connection, so the operating system would now use port 3124 for the ftp connection. At the end of the ftp transaction, the operating system would go back to port 3123 talking to port 80 to continue the http dialogue.

Then enter a new URL, this is now a new connection, so the operating system uses port 3125 or 3126 or 3127.

The upshot of all this is that it is not possible to program IP tables to pass only a narrow range of outgoing port numbers, because the outgoing port number in use for any connection depends on how many other connections there have already been, and there could have been several thousand.

[ My understanding of connection tracking in IP tables is that it only knows about existing connections, it doesn`t keep a dynamic record of previous connections from every ip address. ]

So there is the first problem that our firewall is going to meet - dynamic port allocation.

 

Now back to ftp

As mentioned above, an ftp session has two distinct parts -

  • 1 - Setting up the ftp session between the client and the server. The server uses port 21 for this, but as explained above, the client doesn`t use port 21, it uses some port from 1025 or 3000 upwards

  • 2 - The data transfer - this should be on port 20, but also as explained above, the client doesn`t use port 20, it adds 1 on to the port number used in the setting up process. So the client uses ports from 1026 or 3001 upwards.

There are two basic mechanisms by which ftp can work -

  • active ftp

  • passive ftp

 

Active ftp

In active ftp the client is responsible for specifying the port that the client is listening on, and hence the port the server should use as the destination port for data traffic.

The client sends this information by means of the PORT command, which command specifies the ip address of the client and the port number.

The PORT command is part of the telnet look-alike session on port 21, and the whole command looks like

      PORT 192,168,100,35,13,123 

The sequence of numbers following the PORT command specifies the client socket - the first four numbers are the ip address of the client in the normal dotted decimal notation. The fifth and sixth numbers specify the port number, also expressed in dotted decimal notation.

To convert the port number in dotted decimal notation to the normal decimal number understandable by humans - multiply the fifth number by 256, and add it to the sixth number.

So the ....,13,123 shown above converts to

       (13x256) + 123 = 3583 

ie, port number 3583

This port number has come from the operating system, as described above - ie, in this case the telnet look-alike session used port 3582 in this example, and the data transfer will therefore use port 3583.

Before we get bogged down in port numbers, for active ftp, there is another problem - the PORT command has attached to it the ip address of the client workstation.

Nothing unusual in that - every packet has the ip address of the sending computer.

Normally both the sending ip address and the destination ip address are contained within the headers of the packet.

With the PORT command, the sending ip address is contained within the body of the data packet, as well as in the headers.

If we are using network address translation, then ip tables changes the ip address of the sending computer in the packet headers, but it doesn`t change the sending ip address in the body of the packet.

So the ftp server receives the packet containing the PORT command with the actual ip address of the sending computer instead of the address that the rest of the world should see, and the server sends the data to this address. This address doesn`t exist outside the firewall, so the ftp session fails at this point.

There doesn`t seem to be a way round this with ip tables, so active ftp will not work with a firewall where iptables is doing network address translation.

 

Passive ftp

Passive ftp starts the same way as active ftp, with a telnet look-alike session on port 21.

However when it comes to changing to the data transfer part, the client workstation issues a PASV command instead of the PORT command, and the PASV command does not have the ip address of the sending computer attached to it.

So the only part of the data packet that contains the ip address of the sending computer is the headers, and the ip address of the sending computer contained within the headers will be changed by network address translation, so the ftp server is given the correct internet address of the client.

 

Back to dynamic port allocation

We may have established that we can use passive ftp through our firewall that does NAT, but now we have yet another problem.

As described in detail above, we have the client workstation using any port number from 1025 upwards, for both the telnet look-alike control part of the ftp session, and for the data transfer part of the session.

The server is a little kinder during the telnet look-alike part, it does use port 21 - it has to, otherwise the client couldn`t find it.

However once the server gets that PASV command, it stops using port 21, and uses any port number it seems to fancy.

I have seen an ftp server which used a port number around 1600, and others that used port numbers as high as 58,000.

Here is a simplified extract of the output from a packet sniffer which is listening to an ftp session between a client ( 192.168.100.53 ), and an ftp server ( 10.0.0.8 ). You can see the telnet look-alike session using the server port 21, then the data transfer session using server port 37,116. Finally it goes back to the telnet look-alike session to end the whole process.

   192.168.100.53.3022 > 10.0.0.80.21: S 2906492676:2906492676
   10.0.0.80.21 > 192.168.100.53.3022: S 1369514704:1369514704(0) 
   192.168.100.53.3022 > 10.0.0.80.21: . ack 1 win 64240 (DF)
   10.0.0.80.21 > 192.168.100.53.3022: P 1:40(39) ack 1 win 2482
   .
   .
   .
   192.168.100.53.3023 > 10.0.0.80.37116: S 2907544169:2907544169(0)
   10.0.0.80.37116 > 192.168.100.53.3023: S 1371080414:1371080414(0)
   192.168.100.53.3023 > 10.0.0.80.37116: . ack 1 win 64240 (DF)
   10.0.0.80.37116 > 192.168.100.53.3023: . 1:1461(1460) ack 1 win
   .
   .
   .
   192.168.100.53.3022 > 10.0.0.80.21: . ack 289 win 63952 (DF)
   10.0.0.80.21 > 192.168.100.53.3022: P 289:319(30) ack 48 win 
   192.168.100.53.3022 > 10.0.0.80.21: . ack 319 win 63922 (DF)
   10.0.0.80.21 > 192.168.100.53.3022: P 319:333(14) ack 54 win 

So during the data transfer process, we have a client using any port number from 1025 upwards, talking to a server that uses any port number.

So now our port blocking has gone out the window - we have to have a rule that allows unlimited source and destination port numbers above 1025.

Once that rule is in place, we have lost any protection given by port blocking for ports over 1025, and we are dependent on the protection given by the stateful packet filtering, and by the network address translation.

 

Finally ...

Here are the rules we need to add to our script, in order to get ftp through the firewall.

First of all, here are the rules required to get the telnet look-alike session through the firewall. These rules are no worse than any of the other existing rules that allow specific ports through the firewall - they are specific to port 21.

    iptables -t filter -A incoming-1 -p tcp --sport 21 /

                                                 -j incoming-2

    iptables -t filter -A outgoing-2 -p tcp --dport 21 /

                                                 -j ACCEPT   

Now here are the rules that really do the damage to our port blocking attempts. As it is only XP based pc`s on the secure subnet that need to use ftp, these rules exclude client port numbers below 3000.

    iptables -t filter -A incoming-1 -p tcp --dport 3000: /

                                         --sport 1025: -j incoming-2

    iptables -t filter -A outgoing-2 -p tcp --sport 3000: /

                                         --dport 1025: -j ACCEPT   

These rules can be added to the shell script in the appropriate places.

NB - I have wrapped these to get them into the browser window. Remove the wrapping when adding to the shell script.

 


© 2004 Ron Turner


Return to the Firewall index page