Recently, I came across an interesting feature on Cisco IOS that mysteriously do something similar to an application inspection for FTP protocol and more that that, make modifications into replay messages from FTP server. You know, a router is a Layer 3 device that has no rights to do payload modifications, in some cases at most just several fields in IP header (e.g. TTL, src/dst IP addresses and port numbers in case of NAT). The behavior observed by me looks like oposite: a Cisco IOS router, when configured to do NAT, make specific changes on some FTP control messages. It’s like a router had borrowed something from ASA firewall inspection features.
Let’s do now some testings. For our scenario I built the following simple topology in GNS3.
The three components used are:
- the FTP client is a Windows 7 VM running in VMware Workstation
- the FTP Server is a Windows Server 2008R2 VM running in VMware Workstation
- the R1 is a Cisco IOS 7200 router with Cisco IOS version 12.4(24)T5
Note0: In my testings I used the FileZila 0.9.56 as an FTP server and Total Commander of version 8.51a with his embedded FTP client.
Note1: FTP server run in Passive Mode. My focus was only for FTP passive mode simply because this is the use case I have in my production scenario. I will not talk about FTP active mode.
On Cisco router applied the following simple configuration (interface & static inside NAT conf):
ip address 192.168.1.1 255.255.255.0
ip access-group 110 in
ip nat outside
ip address 192.168.2.1 255.255.255.0
ip nat inside
ip nat inside source static 192.168.2.20 192.168.3.20
access-list 110 deny ip any host 192.168.2.20 log
access-list 110 permit ip any any
After NAT, the FTP server is seen by the FTP client by 192.168.3.20 IP address.
As you can observe an additional ACL that deny any un-NAT-ed communications is applied inside on FastEthernet0/0 (from FTP client side) – just to be sure that all sessions pass through NAT.
Now, I will start two packet capture sessions in Wireshark for both router’s interfaces and initiate a new FTP passive mode connection to FTP server.
In Passive Mode the client request Passive mode operation by issuing the PASV command over the control connection on TCP port 21. The server suggest a data port and IP address, to which the client must connect. The port number are somewhat encoded in several message fields, see the formula in the illustration below.
The following screen show the capture of Passive mode acknowledge message (Passive OK, 227) packet with most important fields highlighted (src/dst ports, pasv response args).
Where: 1-passive mode request, 2-passive mode acknowledge, 3-acknowledge message arguments, 4-passive IP address (server IP), 5-passive port (listener for data connection), 6-source port for data connection (ephemeral), 7-control connection server source port, 8-control connection server destination port (a value different from 6).
If we look now at the same packet but this time after it passed the router/NAT we would see, besides the destination IP change in IP header (because of NAT), also the FTP message payload modifications: specifically, in message arguments, values from 192,168,2,20 changed to 192,168,3,20. It is obviously an effect of NAT FTP protocol inspection and corresponding changes in message made by router.
A more in depth information about how this all works you can find here: ciscopress.com – Routing TCP/IP, Volume II (CCIE Professional Development) – Network Address Translation (link here), btw, one the few sources available on the net.
What if the FTP server will be set to function on a non-standard port ?
The answer is that the inspection embedded in NAT would ignore such a server. It simply do just the standard NAT section but not also the payload inspection and modification. Ironically, that was the reason why, initially, I couldn’t understand why this works perfect in lab but not also in production. It appeared to be that the non-standard port applied on prod. FTP server was the culprit.
The next question then arise: What needs to be done for NAT FTP inspection work for non-standard FTP ports ?
More by accident than intentionally I found this cool Cisco article: cisco.com – Using Non-Standard FTP Port Numbers with NAT (link here), that explain what to do – not so much, just two additional configurations. In my case these would be:
access-list 10 permit 192.168.2.20
ip nat service list 10 ftp tcp port 5555
First, we create a standard ACL that would include the FTP server’s IP address (before NAT), and second, we would teach the IOS NAT to inspect on non-standard port number (in our case 5555) for that IP. If more than one FTP servers are used then add those to ACL too and if more than one tcp port numbers are used for control connections then specify those one by one separated by comma in second configuration command.
Bellow, you can see the ftp connection logs before (first section) and after (second section) the above configuration wad applied and FTP server configured to work with non-standard port number.
As can be observed, after applying configuration, the FTP server answer message arrive already modified with NATed (global inside) server IP address in payload.
How to deliberately disable NAT inspection?
It can be done only per NAT entry (no global configuration), by specifying no-payload keyword at the end of NAT entry definition command.
ip nat inside source static 192.168.2.20 192.168.3.20 no-payload
Why is so important for IP addr. in pasv answer to be fixed to FTP server’s NATed (global inside) value?
Well, actually the importance depends on how FTP client are configured/build. The truth is that an FTP client can work either in restrictive or in less restrictive mode (can’t remember from where I got the terms, they may be wrong) and depending on that, ignore or not the value provided in pasv answer message. An FTP client configured for restrictive mode will try a data connection only to IP address suggested in pasv answer, if the de connection could not be established the FTP session will fail. At the oposite side, an FTP client in less restrictive mode would simply ignore the IP address suggested in pasv answer and would try instead the IP address used initially for data connection (the IP address that you configure in FTP client. Obviously, the global inside address).
So, if you have an FTP client configured/build for restrictive mode then is important to have NAT inspection doing IP address exchange in pasv answer message. Again, absolutely by accident, I found that older versions of Total Commander use the restrictive mode for their FTP client (7.04a in my particular case). It was an opportunity for a little test with such a client. Bellow, you can see the FTP client connection logs for (a) with NAT inspection and (b) without it and the final FTP session status.
Clearly, for FTP session to succeed, a NAT FTP inspection that will do also translations in pasv answer message payload, needs to be in place.