Just thought I'd post a followup, in case someone else was having troubles
with packets getting through and not sure how to fix it.
Mara's suggestions were right on track. Once I changed the table to INPUT
from FORWARD, everything works fantastic.
The machine is a virtual email/web/ssh server with a public IP, we'll say
"184.108.40.206", hosting several domains. I wanted to disallow all
traffic to special ports (ftp, ssh, telnet, ssh-mail (465, 993, 995)), except
for traffic coming from our NAT firewall (meaning, all computers on the
LAN side of the NAT firewall, we'll say "220.127.116.11" are allowed
to access the public server on the special ports, but noone else is.
A simple diagram:
192.168.1.1 -> firewall NAT (18.104.22.168)
192.168.1.2 -> firewall NAT (22.214.171.124)
192.168.1.3 -> firewall NAT (126.96.36.199)
firewall NAT (188.8.131.52) -> public router (184.108.40.206)
public router (220.127.116.11) -> internet
public router (18.104.22.168) -> email/web/ssh server (22.214.171.124)
And since the firewall NAT is NATing all internal (192.168) traffic and causing
it to appear as though it is coming directly from the firewall NAT, we only allow
connections to the special ports from the firewall NAT box.
Here's the core of the iptables firewall rules on the email/web/ssh server (not
the firewall NAT, that is a separate machine):
# first, we establish a chain called "drop_kick", which logs all dropped packets
# and boots them. Remember, LOG is non-terminating! That's why we DROP
iptables -A drop_kick -j LOG --log-level info --log-prefix "Firewall: "
iptables -A drop_kick -j DROP
# Next, we allow traffic from the firewall NAT to all ports. This is a terminating
# rule, as are most.
iptables -A INPUT -p tcp -m tcp -s 126.96.36.199 -j ACCEPT
# Just flat out refuse invalid packets
iptables -A INPUT -m state --state INVALID -j drop_kick
# Then, kill any traffic going to the special ports. If we get to here, then the
# packet was not coming from the firewall NAT.
iptables -A INPUT -p tcp -m tcp -m multiport -j drop_kick --dports 21,22,23,465,993,995
I am still quite an amateur when it comes to iptables, and could probably do
this a much better way, but this does work. And since I don't run services on
other ports (aside from web stuff), I don't worry about filtering those ports.
If anyone has suggestions for improvement, please post it! I'd be happy to
learn better ways and the suggestions could also teach others!