HOWTO Setup iptables: Difference between revisions

From Research
Jump to navigation Jump to search
No edit summary
 
(30 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Kernel Configuration==
==Kernel Configuration==
 
NOTE This configuration is for basic firewalling only; we don't do NAT/packet-forwarding... so, if you're reading this, and wish to use NAT/forwarding, you will be missing a few key configuration items :-O
     * NOTE As of kernel 2.6.22 you must enable the following
     Typical kernel 2.6.25 and higher kernel options for our firewalling:
   
   
  Networking  ---->
  Networking  ---->
Line 7: Line 7:
   Network packet filtering framework (Netfilter)--->
   Network packet filtering framework (Netfilter)--->
     Core Netfilter Configuration ---->
     Core Netfilter Configuration ---->
     ["enable"] Netfilter connection tracking support--->Layer 3 Independent Connection tracking
     <*> Netfilter connection tracking support
     ["enable"] Netfilter Xtables support (required for ip_tables)
    <*>   Amanda backup protocol support
     ["enable"] "NFLOG" target support
     -*- Netfilter Xtables support (required for ip_tables)
     ["enable"] "conntrack" connection tracking match support
     <*>  "limit" match support
     ["enable"] "state" match support  
     <*>  "multiport" Multiple port match support
     <*>  "state" match support
     IP: Netfilter Configuration --->
     IP: Netfilter Configuration --->
     ["enable"] IPv4 connection tracking support (required for NAT) required by "Layer 3 Independent Connection tracking" above (caused many headaches)
     <*> IPv4 connection tracking support (required for NAT)
     ["enable"] IP tables support (required for filtering/masq/NAT)
     <*> IP tables support (required for filtering/masq/NAT)
     ["enable"]   Packet Filtering
     <*>   Packet filtering
     ["enable"]     REJECT target support
     <*>     REJECT target support
    ["enable"]  Full NAT
    ["enable"]    MASQUERADE target support


==Iptables Installation==
==Iptables Installation==
  emerge iptables
  <font color=red>hostname</font> <font color=blue>~ #</font> '''emerge iptables'''
  rc-update add iptables default
  <font color=red>hostname</font> <font color=blue>~ #</font> '''rc-update add iptables default'''
Usually, when you try to start a new installation of iptables, you get an error, sometimes like this:
  <font color=red>hostname</font> <font color=blue>~ #</font> '''/etc/init.d/iptables start'''
<font color=red>*</font> Not starting iptables.  First create some rules then run:
<font color=red>*</font> /etc/init.d/iptables save
Or, you may see this kind of error:
FATAL: Module ip_tables not found.
iptables v1.3.8: can't initialize iptables table `filter': iptables who? (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.
Occasionally, there are complaints about "mangle"... it may be that there is some previous ruleset which included NAT/forwarding.  For our application, we do not need mangling-capability!<br>In any of the above startup cases, we will manually start iptables (that is, '''not''' using the init-script), and give it a very-simple command-line rule, just to get iptables going:
<font color=red>hostname</font> <font color=blue>~ #</font> '''/sbin/iptables -A INPUT -i lo -j ACCEPT'''
This usually (should!) result in very simple, default "all-pass" ruleset, which doesn't actually do anything except keep the init-scripts happy:
<font color=red>hostname</font> <font color=blue>~ #</font> '''iptables -L'''
Chain INPUT (policy ACCEPT)
target    prot opt source              destination
ACCEPT    all  --  anywhere            anywhere
Chain FORWARD (policy ACCEPT)
target    prot opt source              destination
Chain OUTPUT (policy ACCEPT)
target    prot opt source              destination
We then use the init-script to '''save''' our ruleset, which will at least then allow iptables to start properly the next time with the init-scripts:
<font color=red>hostname</font> <font color=blue>~ #</font> '''/etc/init.d/iptables save'''
<font color=lime>*</font> Saving iptables state ...
 
===Creating iptables Rulesets===
It's a great starting-point for ruleset development to see what ports are currently in-use, and consider that these may need to be opened through our firewall.  To see what ports are in-use, and by what programs/services:
<font color=red>hostname</font> <font color=blue>~ #</font> '''netstat -alnp'''
<br>
On a complex server, there can be many unfamiliar ports open, and some may vary with each invocation of the associated program :-(  Google around, and first see if you can identify all the services.  Secondly, see if you can nail down these services to always use a known/specific port.
<br>
In a worst-case scenario, you may decide it's too scary to actually begin blocking ports and breaking services to users - this can work OK with fail2ban!  You will gain some protection against dictionary-attacks, which is better than you had a moment ago (see Example 1).<br>
<hr>
[[example_simple_iptable_ruleset|Example 1 - very-basic /etc/iptables.bak to prevent breaking extensive/weird/complex services]]
 
[[example_webserver_iptable_ruleset|Example 2 - /etc/iptables.bak for a web-server with vsftpd upload, also SSH connectivity, and being monitored by nagios]]
 
[[example_webserver_nfs_keyserver_iptable_ruleset|Example 3 - /etc/iptables.bak for a web-server with both http and https, nfs-client, amanda-tape-backup-client, SSH connectivity, a Sassafrass keyserver, a flexlm license-server, and monitoring by nagios]]
 
[[example_ldap_samba_iptable_ruleset|Example 4 - /etc/iptables.bak for samba-server, LDAP, amanda-tape-backup-client, SSH connectivity, and monitoring by nagios]]
 
[[example_svnserve_nfsserve_iptable_ruleset|Example 5 - /etc/iptables.bak for SVN-server, NFS-server, amanda-tape-backup-client, SSH connectivity, and monitoring by nagios]]
<hr>


==Scripting the Rules==
==Scripting the Rules==
Once '''''iptables''''' is up-and-running, simply execute one of the scripts above, to implement your choice of working-policies,  Or, use these scripts above as a basis for your own similar-but-custom rulesets, which Google can help you with.  Our standard is to save the ruleset-script as '''''/etc/iptables.bak'''''.  So, once iptables is running (in very-basic-form), invoking the ruleset-script is very simple:
<font color=red>hostname</font> <font color=blue>~ #</font> '''sh /etc/iptables.bak'''


  #! /bin/sh
Save the configuration:
# /etc/iptables.bak
  <font color=red>hostname</font> <font color=blue>~ #</font> '''etc/init.d/iptables save'''
# Let's save typing & confusion with variables
IPTABLES=/sbin/iptables
# Flush active rules and custom tables
$IPTABLES --flush
$IPTABLES --delete-chain
# set the defaults so that by-default incoming packets are dropped, unless explicitly allowed;
# for a desktop workstation, we'll let lots of (unpredictable) outgoing packets go freely.
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT ACCEPT
# INBOUND POLICY
# ==============
# of course, accepting loopback is a good idea
$IPTABLES -A INPUT -i lo -j ACCEPT
#  (Applies to packets entering our network interface from the network,
#  and addressed to this host.)
$IPTABLES -A INPUT -m state --state INVALID -j DROP
$IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# ftp incoming
$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 20 -j ACCEPT
$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 21 -j ACCEPT
# ssh incoming, including non-standard port (if needed)
$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
#$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 222 -j ACCEPT
# web serving, let's allow it!
$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT
# nagios (5666); monitor time (123), allow snmp (161)
$IPTABLES -A INPUT -p tcp -m state --state NEW --dport 5666 -j ACCEPT
$IPTABLES -A INPUT -p udp -m state --state NEW --dport 123 -j ACCEPT
$IPTABLES -A INPUT -p udp -m state --state NEW --dport 161 -j ACCEPT
# OUTBOUND POLICY
# ===============
# of course, accepting loopback is a good idea
$IPTABLES -A OUTPUT -o lo -j ACCEPT
#  (Applies to packets sent to the network interface from local processes)
$IPTABLES -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT


Save the configuration:
...then ack up your known-working configuration in case you break something later you can quickly revert:
  etc/init.d/iptables save
  <font color=red>hostname</font> <font color=blue>~ #</font> '''cp /var/lib/iptables/rules-save /var/lib/iptables/rules.working'''


And then back up your working configuration in case you break something later you can quickly revert:
View and check the active ruleset:
  cp /var/lib/iptables/rules-save /var/lib/iptables/rules.working
  <font color=red>hostname</font> <font color=blue>~ #</font> '''iptables -L'''


Viewing/checking the active ruleset:
==Manually Working With Rules==
  iptables -L
You may wish to manually block some bad guy who is trying to access your SSH service (in this example).  You can add lines like these to '''/etc/iptables.bak''' ''(of course, substitute the bad-guy's IP-address)'':
# Manually added blocking-rules, often from watching log-output:                                                                                      
# =============================================================                                                                                     
#awk '($(NF-7) = /invalid user/){print $(NF-3)}' /var/log/messages | sort | uniq -c | sort                                                           
iptables -I INPUT -p tcp -s 83.103.96.33 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 41.206.41.90 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 87.139.25.251 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 200.171.229.109 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 217.91.80.206 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 61.74.75.56 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 80.169.105.159 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 62.96.29.34 --dport ssh -j REJECT --reject-with tcp-reset
  iptables -I INPUT -p tcp -s 190.146.246.36 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 195.202.52.155 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 80.153.59.28  --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 82.106.226.77  --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 194.51.12.238 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 61.74.75.43 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 113.105.82.13 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 211.115.234.143 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 92.79.128.167 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 58.247.222.163 --dport ssh -j REJECT --reject-with tcp-reset

Latest revision as of 17:11, 29 July 2010

Kernel Configuration

NOTE This configuration is for basic firewalling only; we don't do NAT/packet-forwarding... so, if you're reading this, and wish to use NAT/forwarding, you will be missing a few key configuration items :-O

   Typical kernel 2.6.25 and higher kernel options for our firewalling:

Networking  ---->
 Networking options  ---->
  Network packet filtering framework (Netfilter)--->
   Core Netfilter Configuration ---->
    <*> Netfilter connection tracking support
    <*>   Amanda backup protocol support
    -*- Netfilter Xtables support (required for ip_tables)
    <*>   "limit" match support
    <*>   "multiport" Multiple port match support
    <*>   "state" match support
   IP: Netfilter Configuration --->
    <*> IPv4 connection tracking support (required for NAT)
    <*> IP tables support (required for filtering/masq/NAT)
    <*>   Packet filtering
    <*>     REJECT target support

Iptables Installation

hostname ~ # emerge iptables
hostname ~ # rc-update add iptables default

Usually, when you try to start a new installation of iptables, you get an error, sometimes like this:

 hostname ~ # /etc/init.d/iptables start
* Not starting iptables.  First create some rules then run:
* /etc/init.d/iptables save

Or, you may see this kind of error:

FATAL: Module ip_tables not found.
iptables v1.3.8: can't initialize iptables table `filter': iptables who? (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.

Occasionally, there are complaints about "mangle"... it may be that there is some previous ruleset which included NAT/forwarding. For our application, we do not need mangling-capability!
In any of the above startup cases, we will manually start iptables (that is, not using the init-script), and give it a very-simple command-line rule, just to get iptables going:

hostname ~ # /sbin/iptables -A INPUT -i lo -j ACCEPT

This usually (should!) result in very simple, default "all-pass" ruleset, which doesn't actually do anything except keep the init-scripts happy:

hostname ~ # iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

We then use the init-script to save our ruleset, which will at least then allow iptables to start properly the next time with the init-scripts:

hostname ~ # /etc/init.d/iptables save
* Saving iptables state ...

Creating iptables Rulesets

It's a great starting-point for ruleset development to see what ports are currently in-use, and consider that these may need to be opened through our firewall. To see what ports are in-use, and by what programs/services:

hostname ~ # netstat -alnp


On a complex server, there can be many unfamiliar ports open, and some may vary with each invocation of the associated program :-( Google around, and first see if you can identify all the services. Secondly, see if you can nail down these services to always use a known/specific port.
In a worst-case scenario, you may decide it's too scary to actually begin blocking ports and breaking services to users - this can work OK with fail2ban! You will gain some protection against dictionary-attacks, which is better than you had a moment ago (see Example 1).


Example 1 - very-basic /etc/iptables.bak to prevent breaking extensive/weird/complex services

Example 2 - /etc/iptables.bak for a web-server with vsftpd upload, also SSH connectivity, and being monitored by nagios

Example 3 - /etc/iptables.bak for a web-server with both http and https, nfs-client, amanda-tape-backup-client, SSH connectivity, a Sassafrass keyserver, a flexlm license-server, and monitoring by nagios

Example 4 - /etc/iptables.bak for samba-server, LDAP, amanda-tape-backup-client, SSH connectivity, and monitoring by nagios

Example 5 - /etc/iptables.bak for SVN-server, NFS-server, amanda-tape-backup-client, SSH connectivity, and monitoring by nagios


Scripting the Rules

Once iptables is up-and-running, simply execute one of the scripts above, to implement your choice of working-policies, Or, use these scripts above as a basis for your own similar-but-custom rulesets, which Google can help you with. Our standard is to save the ruleset-script as /etc/iptables.bak. So, once iptables is running (in very-basic-form), invoking the ruleset-script is very simple:

hostname ~ # sh /etc/iptables.bak

Save the configuration:

hostname ~ # etc/init.d/iptables save

...then ack up your known-working configuration in case you break something later you can quickly revert:

hostname ~ # cp /var/lib/iptables/rules-save /var/lib/iptables/rules.working

View and check the active ruleset:

hostname ~ # iptables -L

Manually Working With Rules

You may wish to manually block some bad guy who is trying to access your SSH service (in this example). You can add lines like these to /etc/iptables.bak (of course, substitute the bad-guy's IP-address):

# Manually added blocking-rules, often from watching log-output:                                                                                       
# =============================================================                                                                                      
#awk '($(NF-7) = /invalid user/){print $(NF-3)}' /var/log/messages | sort | uniq -c | sort                                                             
iptables -I INPUT -p tcp -s 83.103.96.33 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 41.206.41.90 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 87.139.25.251 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 200.171.229.109 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 217.91.80.206 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 61.74.75.56 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 80.169.105.159 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 62.96.29.34 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 190.146.246.36 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 195.202.52.155 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 80.153.59.28  --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 82.106.226.77  --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 194.51.12.238 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 61.74.75.43 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 113.105.82.13 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 211.115.234.143 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 92.79.128.167 --dport ssh -j REJECT --reject-with tcp-reset
iptables -I INPUT -p tcp -s 58.247.222.163 --dport ssh -j REJECT --reject-with tcp-reset