Enabling Outbound Connections


Introduction

When network people talk about outbound connectivity, they mean a condition that private nodes can communicate (i.e. send and receive packets) with public nodes when they initiate the communication. This means that if a private node sends initial TCP SYN or UDP data packet(s) to a public node, it can send subsequent packets and also receive reply packets from the public node.

This website explains how we enable outbound connectivity using Linux iptables. To enable outbound connections, we need to set NAT to assign public IP:port to packets from private nodes and translate private IP:port into the public IP:port. Also reply packets from public nodes must be translated back to the original private IP:port. All of these can be done by using what is called "source NAT" or "masquerading" and we just need to run one iptables command. However, things may be not that simple because your network configuration may be not quite ready for this. Here, I am explaining various things that are necessary for outbound connectivity:

1. Private Node Setup

For NAT to be able to translate packet addresses, those packets must pass through the NAT. Obvious, right? Therefore, you have to make every machine inside a private network talk with outside machines through their NAT. This can be done by changing the routing table at private nodes. Easiest way is to set the default router as the NAT. The most popular way on Redhat is to have an entry in "/etc/sysconfig/network" file such as "GATEWAY=ip.addr.of.NAT". Another way is to run "/sbin/route" command in a network startup script.

2. Head Node Setup

2.1 Bringing up interfaces

A headnode must have at least two (Ethernet) interfaces up and running: one at the public side with a public IP address and the other at the private side with private IP address. If I run "/sbin/ifconfig -a" on my headnode, I get the following lines. You should get something similar to mine:

	eth0      Link encap:Ethernet  HWaddr 00:A0:CC:50:E5:3C  
	          inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
	          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
	          RX packets:4561356 errors:0 dropped:0 overruns:0 frame:0
	          TX packets:4721689 errors:2 dropped:0 overruns:0 carrier:2
	          collisions:416051 txqueuelen:100 
	          Interrupt:11 Base address:0xfc00 

	eth1      Link encap:Ethernet  HWaddr 00:60:B0:5D:3C:0E  
	          inet addr:128.105.144.36  Bcast:128.105.255.255  Mask:255.255.0.0
	          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
	          RX packets:7337489 errors:0 dropped:0 overruns:0 frame:0
	          TX packets:1737311 errors:0 dropped:0 overruns:0 carrier:0
	          collisions:0 txqueuelen:100 
	          Interrupt:11 Base address:0xf8e0 

	lo        Link encap:Local Loopback  
	          inet addr:127.0.0.1  Mask:255.0.0.0
	          UP LOOPBACK RUNNING  MTU:16436  Metric:1
	          RX packets:6972 errors:0 dropped:0 overruns:0 frame:0
	          TX packets:6972 errors:0 dropped:0 overruns:0 carrier:0
	          collisions:0 txqueuelen:0

The output above tells that my computer has two interfaces: one ("eth0") with private IP address "192.168.0.1" assigned and up and running, and the other ("eth1") with public IP address "128.105.144.36" and also up and running. The last 6 lines which starts with "lo Link ..." give information of local interface and you will get similar lines.

To bring interfaces up and running, you can use "/sbin/ifconfig" command. Running this command in a network startup script ("/etc/sysconfig/network-scripts/ifcfg-ifname", where "ifname" is the name of interface such as eth0 or eth1 in the above example) is a good idea.

2.2 Enabling iptables

Checking whether iptables is enabled or not can be done by running "/sbin/iptables -t nat -L". (Note: you should have the root privilige to run iptables commands.) If you get something (but not errors) from running the command, your system has iptables enabled. You may skip to the next section. FYI, the following lines are valid output, which basically say that no rule has been added to the kernel table

	Chain PREROUTING (policy ACCEPT)
	target     prot opt source               destination         

	Chain POSTROUTING (policy ACCEPT)
	target     prot opt source               destination         

	Chain OUTPUT (policy ACCEPT)
	target     prot opt source               destination

However, if your machine has ipchains enabled instead of iptables (Redhat 7.1 is normally shipped with this option), you will get error messages something similar:

	/lib/modules/2.4.2-2smp/kernel/net/ipv4/netfilter/ip_tables.o: 
	init_module: Device or resource busy
	Hint: insmod errors can be caused by 
	incorrect module parameters, including invalid IO or IRQ parameters
	/lib/modules/2.4.2-2smp/kernel/net/ipv4/netfilter/ip_tables.o: insmod 
	/lib/modules/2.4.2-2smp/kernel/net/ipv4/netfilter/ip_tables.o failed
	/lib/modules/2.4.2-2smp/kernel/net/ipv4/netfilter/ip_tables.o: insmod 
	ip_tables failed
	iptables v1.2.1a: can't initialize iptables table `nat': iptables who? (do 
	you need to insmod?) Perhaps iptables or your kernel needs to be upgraded

In this case you have to disable ipchains and enable iptables. To be sure that the reason iptables not working is ipchains being enabled, run "/sbin/lsmod" and check if the module "ipchains.o" is installed. If you can't find the line with "ipchains.o" from running the command, you need to contact your system admin. Otherwise ipchains can be disabled by running "/sbin/chkconfig --level=2345 ipchains off" and rebooting the head node.

2.3 Making headnode as a router

To make machines inside private network be able to talk to public and/or vice versa, you have to make your headnode act as a router, i.e. it should be able to route or forward packets from private network to public and vice versa.

In most Berkeley based systems, including Linux 2.4, you can check whether a machine is acting as a router by looking at the content of "/proc/sys/net/ipv4/ip_forward" This file is supposed to have a single character which is "0" or "1", and if it has "0", you need to enable "ip forwarding" by adding the line at "/etc/rc.d/rc.local":

	/bin/echo "1" > /proc/sys/net/ipv4/ip_forward

and then running:

	/etc/rc.d/rc.local

2.4 Routing table setup at the headnode

In addition to making your headnode route packets, you need to configure it to route packets to the correct machines by setting its routing table. If you can talk to both public and private nodes from your headnode, the routing table of the headnode must be good enough for correct packet forwarding. However, it is a good idea to check the routing table using "route" or "netstat -r" command. If the routing is not correct, you must change the routing table. The best way, not always but at least in this context, to setup the routing table is to statically change routing rules and make the change permanent by editing "/etc/sysconfig/static-routes" file. Below is an example of the file.

	eth0 net 129.89.200.0 netmask 255.255.254.0 gw *
	eth1 net 129.89.57.0 netmask 255.255.255.0 gw *
	eth1 net default netmask 0.0.0.0 gw 129.89.57.1

The example file is for the system with two ethernet cards, eth0 and eth1. The interpretation of each line is as follow:

1st Line
packets whose first 31 bits of destination match to the first 31 bits of 129.89.200.0 will be directly delivered (without using any further router) to the destine machine through eth0
2nd line
similar to the first line. But the first 32 bits of destination will be compared against the first 32 bits of 129.89.200.0
3rd line
this line is for the default router setup and says that packets which do not match any of preceding rules in the file will be sent to 129.89.57.1 through eth1. One very important thing is that there are various ways to set default router in Unix systems and one of them may precedes the rule you entered in this file. The most popular way on Redhat is to have an entry in "/etc/sysconfig/network" file such as "GATEWAY=129.89.57.1". Another way is to run "/sbin/route" command. Therefore, you have to do the test that follows after editing the static route file.

After editing "/etc/sysconfig/static-routes" appropriately, you have to run the following command to make the change take effect:

	/etc/rc.d/init.d/network restart

You also need to run "/sbin/route -a" command to check the routing table has been setup correctly.

2.5 SNAT setup

The last step of headnode configuration is enabling outbound connections. Now you need to use iptables commands. You can enable outbound connections either by source NAT or masquerading. Here, I just explain the former way.

Add the following line to any startup script, "/etc/rc.d/init.d/network" for example, and run the script:

	/sbin/iptables -t nat -A POSTROUTING -o eth-pub -j SNAT --to pub-ip

In the command, "eth-pub" is the interface name (such as "eth0" or "eth1" that your headnode has at the public side. "pub-ip" is the (public) IP address assigned to "eth-pub". For those of you who are curious what the rule says, it basically says that "translate source addresses into pub-ip after routing decision is made and for packet that are going to be sent via eth-pub".

3. Testing

If you can ping from private machine to any public machine, you are all set in terms of private network setup. One warning is that some machines are set as not responding to ping request. So the fact that you can't ping to a public machine does not necessarily mean that your network has been setup in a wrong way.