Team LiB
Previous Section Next Section

Troubleshooting iptables

No matter how careful you are when you set up firewall rules and tables, it's likely that you'll run into a persistent problem that restarting iptables or rebooting doesn't fix. Here are some of the most frequent firewall troubles, along with hints to solve the problem quickly and efficiently.

Enabling Packet Forwarding

You may have clone everything right in setting up an iptables-based dual-homed network firewall, even down to copying someone else's working /etc/sysconfig/iptables file and rebooting. This common problem doesn't seem logical and many people are just left wondering what's wrong.

Assuming there are no other networking issues at work, check to make sure that kernel support for IPv4 packet forwardng is enabled. You can check the status with the command

   # sysctl -a | grep ip_forward
   net.ipv4.ip_forward = 0

which is the same as this:

   # cat /proc/sys/net/ipv4/ip_forward
   0

To enable packet forwarding, open /etc/sysctl.conf in a text editor and make this change:

   # Controls IP packet forwarding
   net.ipv4.ip_forward = 1

Save the file, exit the text editor, and force sysctl to re-read /etc/sysctl and boot with the proper changes:

   # sysctl -p
   net.ipv4.ip_forward = 1
   net.ipv4.conf.default.rp_filter = 1
   kernel.sysrq = 0
   kernel.core_uses_pid = 1

Try rebooting your firewall again. This allows packets to be forwarded in the kernel and traverse network interfaces. Even though iptables may be set up correctly, this can keep it all from working on a network firewall or multihome/router-based system.

This change will persist until you turn off packet forwarding (=0) through the same mechanism.

SSH Access Denied

If you set up iptables on a stand-alone workstation to allow SSH access but you cannot get in, something is obviously wrong, but what? Your problem may exist at one of several levels. You need to narrow the problem down to look at one part of the system at a time.

Fixing this is a process of elimination. First, turn off iptables:

# /etc/init.d/iptables stop
Flushing firewall rules:                              [ OK ]
Setting chains to policy ACCEPT: mangle nat filter    [ OK ]
Unloading iptables modules:                           [ OK ]

Try logging in now. If you can get in, you've probably got a bad rule or a conflict in one of the "filter" table's chains. Check RH- Firewall-1- INPUT rules carefully and fix anything that's wrong.

If this doesn't work and you're running TCP wrappers as well, do you have an ALL:ALL entry in /etc/hosts.deny? Even if you have an appropriate entry in /etc/hosts.allow, a typo in the allow entry will let the deny file's ALL:ALL override the allow setting. Comment out the ALL:ALL and try again to test for this type of problem.

Still not working? It's probably not the firewall. Did you set up the SysV init scripts for sshd to be persistent (in your default run level) across reboots? Check to see if it's running and configured to "be up" in your default run level:

# /etc/init.d/sshd status
sshd (pid 3619) is running...
[root@localhost root]#  chkconfig --list sshd
sshd        0:off   1:off    2:on    3:on   4:on   5:on   6:off

Make the necessary changes and reboot the SSH daemon. You should also issue the command netstat -ant|grep:22 to ensure that sshd binds to the proper port and IP. The default settings are stored in /etc/sshd/sshd_config and you can make changes there:

   ...
   #Port 22
   #Protocol 2,1
   #ListenAddress 0.0.0.0
   #ListenAddress ::
   ...

If all of these solutions still leave you hanging, watch your log files as you attempt to SSH in from another machine. The log messages should give you an idea of the problem:

   # tail -f /var/log/messages

Conflict with ipchains

If you start iptables and get an error like this

# /etc/init.d/iptables start
ipchains and iptables can not be used together.    [WARNING]

your iptables rules or firewall won't work properly. In this case, someone has either manually loaded the older and now outdated ipchains kernel module or configured the system to load it automatically. This older netfilter module, not fully supported under Fedora Core, can be checked with the following command:

   # lsmod | grep ^ip
   ipchains              49516   0  (unused)

You need to remove ipchains from the kernel with this command:

   # rmmod ipchains

Now, iptables should start without problems:

# /etc/init.d/iptables start
Applying iptables firewall rules:                         [ OK ]

To save dealing with this problem in the future, make sure that iptables is set to load automatically and ipchains is not:

# chkconfig --list | grep ^ip
iptables      0:off  1:off  2:on  3:on  4:on  5:on  6:off

No ipchains init script is configured. Good. Verify that ipchains is not being loaded in /etc/modules.conf or in your rc.local boot-time files:

   # grep ipch /etc/modules.conf /etc/rc.d/rc.local
   /etc/rc.d/rc.local:insmod ipchains

If you see output like this, ipchains is starting automatically. Edit the offending file, remove reference to ipchains, reboot, and run these tests again. You should see no reference to ipchains anywhere in the output and iptables should now start fine.

Denied Access Persists

You've added a rule to allow SSH connections into your workstation, but it won't connect. You've checked TCP wrappers files for typing errors, you've checked your "filter" table settings, and you've performed the sacred Dance of Firewall Strength, but nothing seems to work. All you get is this:

   ssh: connect to address 10.1.1.1 port 22: No route to host

Everything else is working fine. What gives?

Remember that iptables is an Access Control List, and on ACLs, order matters. On a Red Hat or Fedora Core system, you might think you're covered if you just issue this command:

   # iptables -A RH-Firewall-1-INPUT -p tcp --dport 22 -j ACCEPT

It's the right command, but it might not work because order matters. If you're appending a rule (with a -A) to an existing chain from the command line, be sure to list out the existing rules with the -line-numbers option:

# iptables -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target      prot opt source               destination
1    RH-Firewall-1-INPUT all  --  anywhere             anywhere
...
Chain RH-Firewall-1-INPUT (2 references)
num  target     prot opt source                destination
1    ACCEPT     all   --  anywhere             anywhere
2    ACCEPT     icmp  --  anywhere             anywhere        icmp any
3    ACCEPT     ipv6-crypt--   anywhere             anywhere
4    ACCEPT     ipv6-auth--    anywhere           anywhere
5    ACCEPT     all  --   anywhere             anywhere
     state RELATED, ESTABLISHED
6    ACCEPT     tcp  --   anywhere    anywhere     state NEW tcp dpt:http
7    REJECT     icmp --  !pc          anywhere     icmp any reject-with
     icmp-port-unreachable
8    REJECT     all  --  anywhere     anywhere     reject-with
     icmp-host-prohibited
9    ACCEPT     tcp  --  anywhere     anywhere     tcp dpt:ssh

Numerically insert (with the -I switch) your new "allow ssh" rule in the proper location (before the #7 or 8 REJECT), rather than append them. Be sure to use the chain name and the rule number location that you wish to insert to via the following syntax:

#iptables -I RH-Firewal1-1-INPUT 7 -p tcp --dport 22 -j ACCEPT

Now the corrected chain listing should look like this:

# iptables  -L --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    RH-Firewall-1-INPUT  all --  anywhere            anywhere
...
Chain RH-Firewall-1-INPUT (2 references)
num  target     prot opt source               destination
1    ACCEPT     all  -- anywhere               anywhere
2    ACCEPT     icmp -- anywhere              anywhere             icmp any
3    ACCEPT     ipv6-crypt-- anywhere              anywhere
4    ACCEPT     ipv6-auth-- anywhere             anywhere
5    ACCEPT     all -- anywhere               anywhere
     state RELATED,ESTABLISHED
6    ACCEPT     tcp  -- anywhere         anywhere          state NEW tcp dpt:http
7    ACCEPT     tcp  -- anywhere         anywhere          tcp dpt:ssh
8    REJECT     icmp -- !pc              anywhere          icmp any reject-with
     icmp-port-unreachable
9    REJECT     all --anywhere           anywhere          reject-with
     icmp-host-prohibited

That should do it.


Team LiB
Previous Section Next Section