Now would be a good time to save your script and execute it. Run the script by executing "bash -x <name>". The "-x" switch will show every command that is executed in the script - that way, you can see what is actually happening. If all goes well there shouldn't be any errors.
You can now check what kind of rules and policies are loaded into iptables, by issuing "iptables -L".
It should give a list similar to this:
router:~# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN state NEW
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
DROP all -- 10.0.0.101 anywhere
DROP all -- loopback/8 anywhere
DROP all -f anywhere anywhere
DROP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,PSH,ACK,URG/FIN,SYN,RST,ACK
DROP tcp -- anywhere anywhere tcp flags:FIN,SYN/FIN,SYN
DROP tcp -- anywhere anywhere tcp flags:SYN,RST/SYN,RST
ACCEPT icmp -- 10.0.1.0/24 anywhere
ACCEPT all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT all -- 10.0.1.0/24 anywhere state NEW
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere state NE
Now it's about time to change our policy back to DROP (remember those commented lines on the last page?), but before we do that we have to open a couple of pinholes. As a matter of example I'll open up the SSH port (22) on the firewall from both the external as the internal side of the machine.
iptables -A INPUT -d $INTIP -p tcp --destination-port 22 -m state --state NEW -j ACCEPT
iptables -A INPUT -d $EXTIP -p tcp --destination-port 22 -m state --state NEW -j ACCEPT
Ports for other services are opened in an identical way. If we now set the policy to DROP and reload the script, our SSH connection won't be refused. So, cross your fingers and run the script once again.
There are plenty of lists that describe which service uses which port(s). Most common ones are FTP(21), SSH(22), http(80), microsoft-ds[file sharing](137, 138, 139 & 445) and https(443).
Passing on the goods
The final thing a router should do is forward external ports to internal servers. There are three steps involved in this process. First we need to open the port in the "forward" chain to allow for incoming connections. Then, we need to write an entry in the NAT table to handle the address translation and as a last step we open up the OUTPUT chain of the firewall to allow the firewall to access the service too.
Because this can be quite a long list, I wrote a small bash function to keep the instructions clean:
The usage is dead easy. Just call the function with the correct parameters (all are required). This is where the 'Internal servers IP' section from the first part of the article comes in handy, because you can use that variable in the forwarding rules. Also note that it is quite easy to do port remapping. Port remapping comes in handy when your ISP blocks certain ports in a pitiful effort to prevent its users from hosting servers on the network. Just adjust the external and internal ports to hold the correct values, and you are set! The rule to remap the SSH port on an internal server with an IP of 10.0.1.200, as defined at the top of the script, from 2222 to 22 would look like this