11

I'm trying to forward an FTP-server with IPTables. The FTP-Server is running on a Windows 2008 box (Cerberus).

Image

Details Win Box:

  • IP: 192.168.220.51
  • FTP-Port: 21
  • PASV-Ports: 11000-13000

The FTP-server works great in LAN.

The router is working fine for other clients (Serving NAT, DHCP, Firewall,...). I need to forward the FTP-service to the outside world, but I can't use ports 20-21 (already taken).

I tried this, but it didn't work:

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 2121 -j DNAT --to 192.168.220.51:21

Current IPTables config:

[root@router ~]# service iptables status
Table: nat
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0           
2    MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Table: filter
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     all  --  127.0.0.1            0.0.0.0/0           
2    DROP       all  --  0.0.0.0/0            0.0.0.0/0           
3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:2222 
4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:67 
5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:68 
6    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:1194 
7    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 
8    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:443 
9    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:3128 
10   ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:53 
11   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:53 
12   ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:1194 
13   ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
14   DROP       udp  --  0.0.0.0/0            0.0.0.0/0           
15   DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp flags:0x17/0x02 

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Any help would be great :-).

Bounty-Edit: I have not been able to figure this out, any help would be greatly appreciated.

EDIT2

I'm able to telnet into my FTP-server now, after running there commands:

modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 2121 -j DNAT --to 192.168.220.51:21

I'm starting to get there... I think I just need to get my PASV-Ports working now...

EDIT3: Extra Info

[root@router ~]# iptables -L -n -v
Chain INPUT (policy ACCEPT 3251 packets, 154K bytes)
 pkts bytes target     prot opt in     out     source               destination         
  540 48534 ACCEPT     all  --  *      *       127.0.0.1            0.0.0.0/0           
4270K 5625M ACCEPT     all  --  *      *       192.168.220.0/24     0.0.0.0/0           
    0     0 DROP       all  --  eth1   *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:2222 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:67 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:68 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:1194 
   65  8487 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:8080 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:443 
    8   404 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:3128 
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:53 
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpt:53 
    0     0 ACCEPT     udp  --  *      *       0.0.0.0/0            0.0.0.0/0           udp dpt:1194 
63870   81M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
  974  224K DROP       udp  --  *      *       0.0.0.0/0            0.0.0.0/0           
  638 34956 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp flags:0x17/0x02 

Chain FORWARD (policy ACCEPT 3578K packets, 3355M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 2275K packets, 703M bytes)
 pkts bytes target     prot opt in     out     source               destination  



[root@router ~]# iptables -L -n -v -t nat
Chain PREROUTING (policy ACCEPT 33954 packets, 2595K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0           tcp dpt:2121 to:192.168.220.51:21 

Chain POSTROUTING (policy ACCEPT 5925 packets, 699K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      eth1    0.0.0.0/0            0.0.0.0/0           
27170 1785K MASQUERADE  all  --  *      eth0    0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 5777 packets, 457K bytes)
 pkts bytes target     prot opt in     out     source               destination  

Solution

This is how I did it, might not be very pretty, but it works.

[root@router ~]# iptables -t nat -I PREROUTING -p tcp --dport 2121 -j DNAT --to 192.168.220.51:2121
[root@router ~]# iptables -I FORWARD -p tcp -d 192.168.220.51 --dport 2121 -j ACCEPT
[root@router ~]# iptables -t nat -I PREROUTING -p tcp --dport 11000:13000 -j DNAT --to 192.168.220.51:11000-13000
[root@router ~]# iptables -I FORWARD -p tcp -d 192.168.220.51 --dport 11000:13000 -j ACCEPT

Some extra notes: The FTP-server is listening on bot 21 an 2121 and the PASV-range is set from 11000 to 13000

Bart De Vos
  • 17,761
  • 6
  • 62
  • 81
  • Are the ftp conntrack & nat kernel modules loaded? What is the output of `lsmod | grep -i ftp` ? – Steven Monday Mar 27 '11 at 17:11
  • Empty, I did not load any extra kernel modules. Do I need some? – Bart De Vos Mar 27 '11 at 17:15
  • 1
    @TiZon: Yes. Iptables needs the conntrack modules to track the port numbers and addresses that FTP uses in the PASV and PORT commands. Plus, when you're doing NAT, the NAT modules are needed to rewrite port numbers and addresses so that the FTP protocol can work correctly. – Steven Monday Mar 27 '11 at 18:17
  • 2
    +1 for good and complete explanation. – Gopoi Mar 28 '11 at 01:39
  • 3
    @TiZon: as Steven Monai already mentioned, in order for FTP to work properly behind a NAT gateway, you'll need `ip_conntrack_ftp` and `ip_nat_ftp` kernel modules loaded. FTP is an *interesting* protocol to have to deal with behind a firewall/NAT gateway. You may find it easier to simply use sftp (SSH FTP) which only uses port 22 and is encrypted (vastly more secure). FileZilla is a great free FTP client that supports SFTP. – Sean C. Apr 01 '11 at 12:25
  • @Sean C.: SFTP isn't an option (to slow due to encryption overhead). I'll try some more with `ip_nat_ftp`. – Bart De Vos Apr 01 '11 at 12:44
  • Could we get the output of `iptables -L -n -v` and `iptables -L -n -v -t nat` rather than just `service iptables status`? It would be useful to know eg interfaces on which rules apply. Thanks. – MadHatter Apr 03 '11 at 19:25

3 Answers3

9

I believe you need FTP connection tracking module loaded.

http://www.sns.ias.edu/~jns/wp/2006/01/12/iptables-connection-tracking-ftp/

Vick Vega
  • 2,398
  • 16
  • 22
7

To get passive support working, you are going to need to forward the passive ports to the internal ftp server with the same port numbers.

Easy solution: forward all of them all the time

InternetIP:11000-13000 --> 192.168.220.51:11000-13000

Harder solution:

You will need some special-purpose connection tracking agent that reads the FTP protocol and makes the right NAT mappings just in time. It looks like ip_conntrack_ftp might do this.

e_tothe_ipi
  • 478
  • 2
  • 3
  • I did it like this. I permanently forwarded all the ports. It may not be the best solution, but it works. First post edited with howto. – Bart De Vos Apr 04 '11 at 08:02
0
iptables -t nat -I PREROUTING -p tcp --dport 2121 -j DNAT --to 192.168.220.51:2121
iptables -I FORWARD -p tcp -d 192.168.220.51 --dport 2121 -j ACCEPT
modprobe nf_conntrack_ftp 
modprobe nf_nat_ftp

should be enough

  • Shouldn't port number `2121` be replaced with `21`? How do the ftp modules recognize a connection as ftp control? Will it be applied to every connection using port 21 either before or after NAT? – kasperd May 21 '14 at 15:29
  • Some explanation would be nice, so we know you're not just cargo culting the answer – Tom O'Connor May 21 '14 at 15:58
  • You choose which source port to which destination port to forward. It may be any suitable for you. It will be applied to every connection to port you specify, in our case 2121, in nat "PREROUTING" table. How netfilter ftp module works you can read here http://en.wikipedia.org/wiki/Netfilter#Connection_tracking_helpers – Yalok Iy Jun 25 '14 at 15:34