LinuxSelfhelp.com

6.7. IPPORTFW, IPMASQADM, IPAUTOFW, REDIR, UDPRED, and other Port Forwarding tools

IPPORTFW, IPAUTOFW, REDIR, UDPRED, and other programs are generic TCP and/or UDP port forwarding tools for Linux IP Masquerade (for < 2.4 kernels). These tools are typically used with or as a replacement for specific IP MASQ modules to get a specific network traffic through the MASQ server.

With port forwarders, you can redirect data connections from the Internet to an internal, privately addressed machine behind your IP MASQ server. This forwarding ability includes network protocols such as TELNET, WWW, SMTP, FTP (with a special patch - see below), ICQ, and many others.

NOTE: If you are just looking to do simple port forwarding without IP Masquerading support, you will STILL NEED to enable IP Masquerading in the kernel AND either run a IPTABLES, IPCHAINS, or IPFWADM ruleset to be able to use Linux's port forwarding tools.

So why all the different choices? MARK (MFW), IPMASQADM (PORTFW or AUTOFW), IPPORTFW, IPAUTOFW, REDIR, and UDPRED (all URLs are in Section 3.2.3) were the various tools available to IP MASQ users to allow this type of functionality. Later, as the Linux IP Masquerade feature matured, many of these tools were eventually replaced by the PORTFW and MARK systems which are more intelligent solutions.

In recent 2.2.x kernels, the IPMASQADM tool combined the IPAUTOFW and IPPORTFW 2.0.x kernel tools into one binary. Both the IPMASQADM tool and IPTABLES also supports a new mechanism called "MARK" or MFW. The MARK system works where a specific IPTABLES or IPCHAINS ruleset would match a given packet sequence. Once matched, the tool would "mark" these packets. Later, the IPMASQADM tool or a specific IPTABLE "table" could be instructed to change these packets as needed and forward them off to their desired destination. Currently, this HOWTO doesn't cover the MARK solution but it will in the near future.

Anyway, because of the availablity of the newer tools, it is *HIGHLY DISCOURAGED* to use the old tools such as IPAUTOFW (even AUTOFW in IPMASQADM) and REDIR because they don't properly notify the Linux kernel of their presence and can ultimately CRASH your Linux server with extreme use.

NOTE #2: With enabling PORTFW functionality in ANY 2.2.x or 2.0.x Linux kernel, internal machines typically CANNOT use the same "external" PORTFWed IP address to access an internal" machine. This feature was only intended to be used with "external" computers on the Internet. If limitation this is an issue for you, you can implement the REDIR tool in addition to the specific PORTFW tool to let internal machines get redirected to the internal servers too. One good thing to note is that IPTABLES for the 2.4.x kernels now solves this issue once and for all. If you would like a technical explination on why this internal/external forwarding doesn't work, please page down towards the bottom of the 2.2.x PORTFW section for a note from Juan Jose Ciarlante.

NOTE #3: The forwarding of FTP server traffic to an internal MASQed FTP server, known as PORTFW FTP, is now full ysupported in the 2.4.x kernels as well as in the 2.2.x kernels via a BETA version FTP kernel module (does NOT come with the stock Linus kernels). It should also be noted that you can also PORTFW FTP traffic using an external FTP proxy program (not covered in this HOWTO). It should be noted that the Beta 2.2.x FTP kernel module code is still experimental and some people get better results simply using ACTIVE FTP sessions compared to PASSIVE connections. Interestingly enough, other people have seen the exact opposite behavior. Please let us know what your results are like. More about this is covered below in both the 2.2.x and 2.0.x sections as the solutions require the use of different patches.

WARNING! Before jumping right into installing ANY of these tools, it needs to be mentioned that network security can be an issue with ANY PORT FORWARD tool. The reason for this is because these tools basically create a hole in strong packet firewalls for the required TCP/UDP ports. Though this doesn't pose any threat to your Linux machine, it might be an issue to the PORTFW'ed internal machine(s). No worries though, this is what Steven Clarke (the author of IPPORTFW) had to say about that:

   "Port Forwarding is only called within masquerading functions so it 
   fits inside the same IPFWADM/IPCHAINS rules. Masquerading is an extension to 
   IP forwarding. Therefore, ipportfw only sees a packet if it fits 
   both the input and masquerading ipfwadm rule sets."

What that means in English is that if you have a strong packet firewall running, PORTFW doesn't directly bypass any of that security. You will still be able to allow or deny specific IPs and/or domains to this new PORTFW'ed resource if you so wish.

With this said, it's important to have a strong firewall ruleset. Please see Section 6.4.1, Section 6.4.2, and Section 6.4.3 for more details on getting strong rulesets.

2.4.x kernels users should be ready to go for PORTFW functionality. 2.2.x and 2.0.x kernel kernel users will need to re-compile the Linux kernel to support PORTFW. It should be noted that some Linux distribution kernels might have this already done for you.

6.7.1. 2.4.x PORTFWD'ing: Using IPTABLE's PREROUTING option for 2.4.x kernels

Unlike ALL previous Linux kernels, the 2.4.x series now allows for full PORTFW, PORTFW FTP, and PORTFW REDIR functionality within the "iptables" tool itself.

NOTE: Once you enable a port forwarder on say port 80 (forward WWW traffic through the MASQ server to an internal WWW server), that port will no longer be used by the Linux IP Masquerade server itself. To be more specific, if you have a WWW server already running on the MASQ server, enabling PORTFW will now give all Internet users acces to the WWW pages from the -INTERNAL- WWW server and not the pages on your IP MASQ server.

To enable port forwarding on a 2.4.x kernel, edit the /etc/rc.d/rc.firewall-2.4 ruleset. Add the follow lines but be sure to replace the word "$EXTIP" with your specific Internet IP address.

NOTE: If you use get a DYNAMIC TCP/IP address from your ISP (PPP, ADSL, Cablemodems, etc.), you will NEED to make your /etc/rc.d/rc.firewall ruleset more intelligent. To do this, please see Section 6.4.2 from above or TrinityOS - Section 10 for more details on strong rulesets and Dynamic IP addresses. I'll give you a hint though: /etc/ppp/ip-up for PPP users.

/etc/rc.d/rc.firewall
#echo "Enabling PORTFW Redirection on the external LAN.."
#
#   This will forward ALL port 80 traffic from the external IP address
#   to port 80 on the 192.168.0.10 machine
#
#   Be SURE that when you add these new rules to your rc.firewall, you
#   add them before a direct or implict DROP or REJECT.
#
$PORTFWIP=192.168.0.10

$IPTABLES -A FORWARD -i $EXTIF -o $INTIF -p tcp --dport 80 -m state \
--state NEW,ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A PREROUTING -t nat -p tcp -d $EXTIP --dport 80 \ 
-j DNAT --to $PORTFWIP:80 

That's it! Just re-run your /etc/rc.d/rc.firewall-2.4 ruleset and test it out!

PORTFW FTP: If you have the "ip_conntrack_ftp" and "ip_nat_ftp" kernel modules loaded into kernel space (as already done in the rc.firewall-2.4 script), the simple PREROUTING command like the one shown above changed for for port "21" should do the trick. Much easier than the old 2.2.x / 2.0.x ways!

Please note, if you PORTFW to an internal FTP server that is running on, say port 8021 and NOT running on port 21, you MUST tell the "ip_conntrack_ftp" module about the new port. To do this, edit your rc.firewall file and change the loading of the FTP module to look something like this:
/sbin/insmod ip_conntrack_ftp ports=21,8021

In the past, if users PORTFWed port 80 on their EXTERNAL IP to some internal machine, only machines on the Internet would work properly. If you tried to do this from an internal machine, it would fail. Fortunately, there is a workaround for 2.2.x and 2.0.x kernels using the REDIR tool. Fortunately, this is NOT required anymore for the 2.4.x kernels. To fix this, add a line like the following ABOVE the "Catch all" FORWARDing rule in the rc.firewall file. This example will REDIRECT internal WWW traffic to the 192.168.0.2 internal machine (please change this IP address to reflect your configuration):
$IPTABLES -t nat -A PREROUTING -d $EXTIP -p tcp --dport 80 \
-m state --state NEW,ESTABLISHED,RELATED -j DNAT --to 192.168.0.2

6.7.2. 2.2.x PORTFWD'ing: Using IPMASQADM with 2.2.x kernels

First, make sure you have the newest 2.2.x kernel uncompressed into /usr/src/kernel/linux. If you haven't already done this, please see Section 3.2.2 section for full details. Next, download the "ipmasqadm.c" program from Section 8.5 into the /usr/src/kernel directory.

Next, you'll need to compile the 2.2.x kernel as shown in Section 3.2.2 section. Be sure to say "YES" to the IPPORTFW option when you configure the kernel. Once the kernel compile is complete and you have rebooted, return to this section.

Now, compile and install the IPMASQADM tool:

        cd /usr/src
        tar xzvf ipmasqadm-x.tgz
        cd ipmasqadm-x
        make
        make install 

Now, for this example, we are going to allow ALL WWW Internet traffic (port 80) hitting your Internet TCP/IP address to be forwarded to the internal Masqueraded machine at IP address 192.168.0.10.

PORTFW FTP: As mentioned above, there are two solutions for forwarding FTP server traffic to an internal MASQed PC. The first solution *IS* a BETA level IP_MASQ_FTP module for 2.2.x kernels to PORT Forward FTP connections to an internal MASQed FTP server. The other method is using a FTP proxy program (the URL is in Section 8.5. It should also be noted that the FTP kernel module also supports the adding of additional PORTFW FTP ports on the fly without the requirement of unloading and reloading the IP_MASQ_FTP module and thus breaking any existing FTP transfers. You can find more about this new code at the IPMASQ WWW site at http://ipmasq.cjb.net;. There are also examples and some additional information about PORTFWed FTP connection below in the 2.0.x. kernel section.

NOTE: Once you enable a port forwarder on port 80, that port can no longer be used by the Linux IP Masquerade server. To be more specific, if you have a WWW server already running on the MASQ server, a port forward will now give all Internet users the WWW pages from the -INTERNAL- WWW server and not the pages on your IP MASQ server.

Anyway, to enable port forwarding, edit the /etc/rc.d/rc.firewall ruleset. Add the follow lines but be sure to replace the word "$extip" with your Internet IP address.

NOTE: If you use get a DYNAMIC TCP/IP address from your ISP (PPP, ADSL, Cablemodems, etc.), you will NEED to make your /etc/rc.d/rc.firewall ruleset more intelligent. To do this, please see Section 6.4.2 from above or TrinityOS - Section 10 for more details on strong rulesets and Dynamic IP addresses. I'll give you a hint though: /etc/ppp/ip-up for PPP users.

/etc/rc.d/rc.firewall
#echo "Enabling IPPORTFW Redirection on the external LAN.."
#
#   This will forward ALL port 80 traffic from the external IP address
#   to port 80 on the 192.168.0.10 machine
#
/usr/sbin/ipmasqadm portfw -f
/usr/sbin/ipmasqadm portfw -a -P tcp -L $extip 80 -R 192.168.0.10 80

That's it! Just re-run your /etc/rc.d/rc.firewall ruleset and test it out!

If you get the error message "ipchains: setsockopt failed: Protocol not available", you AREN'T running your new IPPORTFW enabled kernel. Make sure that you moved the new kernel over, re-run LILO, and then reboot again. If you are sure you are running your new kernel, run the command "ls /proc/net/ip_masq" and make sure the "portfw" file exists. If it doesn't, you must have made an error when configuring your kernel. Try again.

For those who want to understand why PORTFW cannot redirect traffic for both external and internal interfaces (the REDIR situation), here is an email from Juanjo that better explains it:

From Juanjo Ciarlante
--

>If I use:
>
> ipmasqadm portfw -a -P tcp  -L 1.2.3.4 80 -R 192.168.2.3 80
>
>Everything works great from the outside but internal requests for the same
>1.2.3.4 address fail. Are there chains that will allow a machine on localnet 
>192.168.2.0 to accesss www.periapt.com without using a proxy? 

Actually not.

I usually setup a ipmasqadm rule for outside, *AND* a port
redirector for inside. This works because ipmasqadm hooks before
redir will get the eventual outside connection, _but_ leaves things
ok if not (stated by APPROPIATE rules).

The actual "conceptual" problem comes from the TRUE client (peer) IP
goal (thanks to masq) being in the same net as target server.

The failing scenario for "local masq" is :
   client: 192.168.2.100
   masq:   192.168.2.1
   serv:   192.168.2.10

1)client->server packet
 a) client:  192.168.2.100:1025  -> 192.168.2.1:80   [SYN]
 b) (masq):  192.168.2.100:1025  -> 192.168.2.10:80  [SYN]
            (and keep  192.168.2.1:61000 192.168.2.100:1025 related)
 c) serv:    gets masqed packet (1b)

2)server->client packet
 a) serv:    192.168.2.10:80     -> 192.168.2.100:1025  [SYN,ACK]
 b) client:  192.168.2.100:1025  -> 192.168.2.10:80     [RST]

Now take a moment to compare (1a) with (2a).
You see, the server replied DIRECTLY to client bypassing masq (not
letting masq to UNDO the packet hacking) because it is in SAME net, so
the client resets the connection.

hope I helped.

Warm regards
Juanjo

6.7.3. 2.0.x PORTFWD'ing: Using IPPORTFW on 2.0.x kernels

First, make sure you have the newest 2.0.x kernel uncompressed into /usr/src/kernel. If you haven't already done this, please see Section 3.2.3 for full details. Next, download the "ipportfw.c" program and the "subs-patch-x.gz" kernel patch from Section 3.2.3 into the /usr/src/ directory.

NOTE: Please replace the "x" in the "subs-patch-x.gz" file name with the most current version available on the site.

Next, if you plan on port forwarding FTP traffic to an internal server, you will have to apply an additional NEW IP_MASQ_FTP module patch found in Section 3.2.3. More details regarding this are later in this section. Please note that this is NOT the same patch as for the 2.2.x kernels so some functionality such as the dynamic FTP PORT functionality is not present.

Now, copy the IPPORTFW patch (subs-patch-x.gz) into the Linux directory
        cp /usr/src/subs-patch-1.37.gz /usr/src/linux

Next, apply the kernel patch to create the IPPORTFW kernel option:
        cd /usr/src/linux
        zcat subs-patch-1.3x.gz | patch -p1

Ok, time to compile the kernel as shown in Section 3.2.3. Be sure to say YES to the IPPORTFW option now available when you configure the kernel. Once the compile is complete and you have rebooted, return to this section.

Now with a newly compiled kernel, please compile and install the actual "IPPORTFW" program
        cd /usr/src
        gcc ipportfw.c -o ipportfw
        mv ipportfw /usr/local/sbin

Now, for this example, we are going to allow ALL WWW Internet traffic (port 80) hitting your Internet TCP/IP address to then be forwarded to the internal Masqueraded machine at IP address 192.168.0.10.

NOTE: Once you enable a port forwarder on port 80, that port can no longer be used by the Linux IP Masquerade server. To be more specific, if you have a WWW server already running on the MASQ server and then you port forward port 80 to an internal MASQed computer, ALL internet users will see the WWW pages pages from the -INTERNAL- WWW server and not the pages on your IP MASQ server. This only performs a port forward to some other port, say 8080, to your internal MASQ machine. Though this will work, all Internet users will have to append :8080 to the URL to then contact the internal MASQed WWW server.

Anyway, to enable port forwarding, edit the /etc/rc.d/rc.firewall ruleset. Add the follow lines but be sure to replace the word "$extip" with your Internet IP address.

NOTE: If you use get a DYNAMIC TCP/IP address from your ISP (PPP, ADSL, Cablemodems, etc.), you will NEED to make your /etc/rc.d/rc.firewall ruleset more intelligent. To do this, please see Section 6.4.2from above or TrinityOS - Section 10 for more details on strong rulesets and Dynamic IP addresses. I'll give you a hint though: /etc/ppp/ip-up for PPP users.

/etc/rc.d/rc.firewall
#echo "Enabling IPPORTFW Redirection on the external LAN.."
#
#   This will forward ALL port 80 traffic from the external IP address
#   to port 80 on the 192.168.0.10 machine
#
/usr/local/sbin/ipportfw -C
/usr/local/sbin/ipportfw -A -t$extip/80 -R 192.168.0.10/80

That's it! Just re-run your /etc/rc.d/rc.firewall ruleset and test it out!

If you get the error message "ipfwadm: setsockopt failed: Protocol not available", you AREN'T running your new kernel. Make sure that you moved the new kernel over, re-run LILO, and then reboot again.

Port Forwarding FTP servers:

If you plan on port forwarding FTP to an internal machine, things get more complicated. The reason for this is because the standard IP_MASQ_FTP kernel module wasn't written for this though some users report that it works without any problems. Personally, without the patch, I've heard that extended file transfers in excess of 30 minutes will fail without the patch while other users swear that it works flawlessly. Anyway, I recommend that you try the following PORTFW instruction with the STOCK ip_masq_ftp module and see if it works for you. If it doesn't, try using the modified ip_masq_ftp module.

For those who need the module, Fred Viles wrote a modified IP_MASQ_FTP module to make things work. If you are curious what EXACTLY are the issues, download the following archive since Fred documents it quite well. Also understand that this patch is somewhat experimental and should be treated as such. It should be noted that this patch is ONLY available for the 2.0.x kernels though there is a different patch available for 2.2.x kernels.

So, to get the 2.0.x patch working, you need to:

  • FIRST, apply the IPPORTFW kernel patch as shown earlier in this section.

  • Download the "msqsrv-patch-36" from Fred Viles's FTP server in Section 3.2.3and put it into /usr/src/linux.

  • Patch the kernel with this new code by running "cat msqsrv-patch-36 | patch -p1"

  • Next, replace the original "ip_masq_ftp.c" kernel module with the new one

    mv /usr/src/linux/net/ipv4/ip_masq_ftp.c /usr/src/linux/net/ipv4/ip_masq_ftp.c.orig

    mv /usr/src/linux/ip_masq_ftp.c /usr/src/linux/net/ipv4/ip_masq_ftp.c

  • Lastly, build and install the kernel with this new code in place.

Once this is complete, edit the /etc/rc.d/rc.firewall ruleset and add the following lines, but be sure to replace the word "$extip" with your Internet IP address.

This example, like the one above, will allow ALL FTP Internet traffic (port 21) hitting your Internet TCP/IP address to then be forwarded to the internal Masqueraded machine at IP address 192.168.0.10.

NOTE: Once you enable a port forwarder on port 21, that port can no longer be used by the Linux IP Masquerade server. To be more specific, if you have an FTP server already running on the MASQ server, a port forward will now give all Internet users the FTP files from the -INTERNAL- FTP server and not the files on your IP MASQ server.

/etc/rc.d/rc.firewall
#echo "Enabling IPPORTFW Redirection on the external LAN.."
#
/usr/local/sbin/ipportfw -C
/usr/local/sbin/ipportfw -A -t$extip/21 -R 192.168.0.10/21

#NOTE: If you are using multiple local port numbers to PORTFW
#      to multuple internal FTP servers (say, 21, 2121, 2112,
#      etc, you need to configure the ip_masq_ftp nodule to
#      listen to these ports.  To do this, edit the 
#      /etc/rc.d/rc.firewall script as shown in this HOWTO
#      to look like:
#
# /sbin/modprobe ip_masq_ftp ports=21,2121,2112
#
# Re-run the /etc/rc.d/rc.firewall script for these changes to
# take effect.


#Please note that PORTFWing port 20 is probably NOT required 
#  for ACTIVE connections as the internal FTP server will 
#  initiate this port 20 connection and it will be properly 
#  handled by the classic MASQ mechanisms.

That's it! Just re-run your /etc/rc.d/rc.firewall ruleset and test it out!