Monday, March 29, 2010

solaris 8 patch installation status codes

Solaris 8 Patch Installation Status Codes
      
      0. No error
      1. Usage error
      2. Attempt to apply a patch that's already been applied
      3. Effective UID is not root
      4. Attempt to save original files failed
      5. pkgadd failed
      6. Patch is obsoleted
      7. Invalid package directory
      8. Attempting to patch a package that is not installed
      9. Cannot access /usr/sbin/pkgadd (client problem)
     10. Package validation errors
     11. Error adding patch to root template
     12. Patch script terminated due to signal
     13. Symbolic link included in patch
     14. NOT USED
     15. The prepatch script had a return code other than 0.
     16. The postpatch script had a return code other than 0.
     17. Mismatch of the -d option between a previous patch install and the current one.
     18. Not enough space in the file systems that are targets of the patch.
     19. $SOFTINFO/INST_RELEASE file not found
     20. A direct instance patch was required but not found
     21. The required patches have not been installed on the manager
     22. A progressive instance patch was required but not found
     23. A restricted patch is already applied to the package
     24. An incompatible patch is applied
     25. A required patch is not applied
     26. The user specified backout data can't be found
     27. The relative directory supplied can't be found
     28. A pkginfo file is corrupt or missing
     29. Bad patch ID format
     30. Dryrun failure(s)
     31. Path given for -C option is invalid
     32. Must be running Solaris 2.6 or greater
     33. Bad formatted patch file or patch file not found
     34. Incorrect patch spool directory
     35. Later revision already installed

     36. Cannot create safe temporary directory
     37. Illegal backout directory specified
     38. A prepatch, prePatch or a postpatch script could not be executed
     39. A compressed patch was unable to be decompressed
     40. Error downloading a patch
     41. Error verifying signed patch
     42. Error unable to retrieve patch information from SQL DB
     43. Error unable to update the SQL DB
     44. Lock file not available
     45. Unable to copy patch data to partial spool directory.
and afterwards...
# less /var/sadm/install_data/Solaris_rev_Recommended_log
# /usr/bin/showrev -p

Friday, March 26, 2010

snort client setup

So. You want to set up a snort client for your distributed snort network on a scad of Ubuntu boxes?  It is pretty easy, once you've done it three or four times.

1. Pre-tasks.


Uncomment the line beginning with: deb cdrom

This will configure the dpkg package system to NOT look for packages on the cdrom.

Then we want to update our sources and upgrade our binaries to the latest:
# apt-get update
# apt-get upgrade
If ssh is not already installed, install it:

# apt-get install ssh
We're going to roll our own snort; install all required packages:
# apt-get -s install mysql-client libnet1 libnet1-dev libpcre3 libpcre3-dev libmysqlclient15-dev \
autoconf automake1.9 libpcap libpcap-dev libpcap0.8 libpcap0.8-dev libpcre-dev libmysqlclient15-dev gcc \
make libtool libssl-dev gcc-4.1 g++ libpcap-dev build-essential
Does everything look fine?
# apt-get install mysql-client libnet1 libnet1-dev libpcre3 libpcre3-dev libmysqlclient15-dev \
autoconf automake1.9 libpcap libpcap-dev libpcap0.8 libpcap0.8-dev libpcre-dev libmysqlclient15-dev gcc \
make libtool libssl-dev gcc-4.1 g++ libpcap-dev build-essential

2. Compile & install Snort, then add the snort user & group.


This step involves installing snort, adding the snort user & group, then installing the detection rules.
We're installing the latest snort as found on the snort site.
# cd /usr/local/src
# wget http://snort.org/dl/snort-2.8.3.2.tar.gz

# tar xvzf snort-2.8.3.2.tar.gz
# cd snort-2.8.3.2 (take the time to read the doc/INSTALL file)
# ./configure --with-mysql --enable-dynamicplugin
# make
# make install
# ln -s /usr/local/src/snort-2.8.3.2 ./snort
Next, run the following commands:
# mkdir /etc/snort
# mkdir /var/log/snort
# groupadd snort
# useradd -g snort -d /etc/snort snort
# chown snort:snort /var/log/snort ; chown snort:snort /etc/snort
If you have a pre-compiled version of snort, you may wish to do the following:
# ldd /usr/local/bin/snort

And you'll see what libraries are lacking on your system. The following is from client; looks like all we need is libmysql15off:
root@client: bin# ldd snort
        linux-gate.so.1 =>  (0xb7f50000)
        libmysqlclient.so.15 => not found
        libpthread.so.0 => /lib/libpthread.so.0 (0xb7f32000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0xb7f04000)
        libz.so.1 => /usr/lib/libz.so.1 (0xb7eef000)
        libpcre.so.3 => /usr/lib/libpcre.so.3 (0xb7ec8000)
        libpcap.so.0.8 => /usr/lib/libpcap.so.0.8 (0xb7e9d000)
        libm.so.6 => /lib/libm.so.6 (0xb7e78000)
        libnsl.so.1 => /lib/libnsl.so.1 (0xb7e61000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7e5d000)
        libc.so.6 => /lib/libc.so.6 (0xb7d29000)
        /lib/ld-linux.so.2 (0xb7f51000)

3. Get initial set of rules.


Note: central repository for rules is on server.
# cd /etc/snort
# scp -r root@server:/etc/snort/rules ./rules

4. Configure and start the Snort program.


# cp /usr/local/src/snort/etc/*.conf* .
# cp /usr/local/src/snort/etc/*.map .

Now it is time to configure and start snort.

First, we need to edit the main configuration file:
# pico -w /etc/snort/snort.conf
To get change these lines to match environment:
var RULE_PATH /etc/snort/rules
var HOME_NET 192.168.1.0/24

var EXTERNAL_NET !$HOME_NET
Add the following:
portvar SSH_PORTS 22
The snort pre-processor throws a lot of false positives; disable some options by unhashing:
config disable_decode_alerts
config disable_tcpopt_experimental_alerts
config disable_tcpopt_obsolete_alerts
config disable_tcpopt_ttcp_alerts
config disable_tcpopt_alerts
config disable_ipopt_alerts

Let's see if snort works by editing local rules:
# pico -w /etc/snort/rules/local.rules
Make a simple rule for testing:
alert icmp any any -> $HOME_NET any (msg:"ICMP test"; \
dsize:8; itype:8; sid:10000001;)
Or to a whole lot of alerts, make this local rule:

alert tcp any any -> any any (msg:"test"; sid:1000002;)
Now we can start snort:
# /usr/local/bin/snort -Dq -u snort -g snort -c /etc/snort/snort.conf
snort should initialize successfully. Look at /var/log/syslog for  a line that looks like this:

snort[12991]: Snort initialization completed successfully (pid=12991)
If not already enabled, bring up "sniffing" interface:
# ifconfig eth1 up
Use the snort startup commands above along with the -i option to call an interface you would like to sniff from. (i.e. -i eth1).   Remember to kill the existing snort process first before you start a new one.

5. Set up remote logging.


Check if snort user via the remote client can connect to the snort database on central snort server.
# mysql -h server -u snort -p -D snort
If the connection is rejected, check the DB table permissions.

Uncomment and edit this line:
output database: log, mysql, user=snort password=password dbname=snort host=localhost sensor_name=ww.xx.yy.zz

For server logging:
output database: log, mysql, user=snort password=supersecretpassword dbname=snort host=server sensor_name=client
Note: For mysql clients with rev less than 5.0 , please see old mysql client setup.

10. Keep rules up to date with Oinkmaster.


# cd /usr/local/src
# wget http://internap.dl.sourceforge.net/sourceforge/oinkmaster/oinkmaster-2.0.tar.gz

# tar xvzf oinkmaster-2.0.tar.gz
# ln -s /usr/local/src/oinkmaster-2.0 ./oinkmaster
# cd oinkmaster-2.0
# cp oinkmaster.pl /usr/local/bin
# mkdir /usr/local/etc
# cp oinkmaster.conf /usr/local/etc
# ln -s /usr/local/etc/oinkmaster.conf /etc/oinkmaster.conf
# mkdir /etc/snort/rules.hold ; mkdir /etc/snort/backup
# mkdir /var/run/oinkmaster ; chmod 775 /var/run/oinkmaster
Since this is a slave server, we're going to edit oinkmaster.conf to grab rules from a directory to be rsynced from the central repository and then process those rules. Our repository is server.
# pico -w /usr/local/etc/oinkmaster.conf
Note this section of the configuration file and edit:

url = dir:///etc/snort/rules.hold
tmpdir = /tmp
We're going to have to do some more initial legwork by creating an oinkmaster user, gen pubkeys. Yeah.
# groupadd oinkmaster
# useradd -d /opt/oinkmaster -g oinkmaster -G snort -s /bin/bash oinkmaster
# mkdir /opt/oinkmaster ; chown oinkmaster:oinkmaster /opt/oinkmaster
# chown oinkmaster:snort /etc/snort/rules.hold
# su - oinkmaster
~ ssh-keygen -t rsa -b 2048

note:  Double-check if oinkmaster is permitted to ssh into the system:

# less /etc/ssh/sshd_config
AllowUsers root oinkmaster
If not, add the user and re-start ssh daemon.

As oinkmaster user on client:
~ ssh -l root server "sudo bash -c \"cat /opt/oinkmaster/.ssh/id_rsa.pub\"" > \
/opt/oinkmaster/.ssh/authorized_keys2
Do a test ssh connection from repository to see if pubkey authentication is working properly. From repository as oinkmaster user:

oinkmaster@server:~$ ssh oinkmaster@client
Then...
The authenticity of host 'client' can't be established.
RSA key fingerprint is bb:e4:31:de:9a:04:0a:1d:56:2b:62:c5:dd:4d:72:18.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'client' (RSA) to the list of known hosts.

oinkmaster@client:~$
Push the initial set of rules from repository to client. On repository:
# su - oinkmaster
~ pico -w /opt/oinkmaster/scripts/pushsnortrules-test.sh

Add the following line:
rsync -c --delete -r -H -p -z -o -g -t -e 'ssh -i /opt/oinkmaster/.ssh/id_rsa' \
/etc/snort/rules client:/etc/snort/rules.hold
What the above specifies is that rsync will use the oinkmaster key to connect to the client and will delete all and replace the rules in the rules.hold directory. The client's oinkmaster.conf has defined the rules.hold directory to be used for new rules to be loaded into snort.

Run pushsnortrules-test.sh on the repository as oinkmaster:

~ ./opt/oinkmaster/scripts/pushsnortrules-test.sh
After the rules have been rsynced with success, add the same line to pushsnortrules.sh . Test oinkmaster.pl on client:
# mkdir /tmp/oinktest
# /usr/local/bin/oinkmaster.pl -o /tmp/oinktest
Take a look in /tmp/oinktest to see if the rules are in place:
# ls -lah /tmp/oinktest/
Once it has been determined that the rules updated correctly, run oinkmaster.pl with the production output location as defined in the configuration file.

Note: The -o switch tells oinkmaster to override the output directory in the configuration file; the -b switch will make oinkmaster back up the current rules in the location before doing the actual update; play with this is so desired; the /etc/snort/backup directory is created for this purpose.

11. Set up configuration files and init scripts.


On repository, there are init scripts and configuration files. scp them over to client sensor and place thusly:

/etc/snort/snort.scripts/oinkoink.sh -> /root/scripts/oinkoink.sh
/etc/snort/snort.scripts/snort.debian.conf -> /etc/snort/snort.debian.conf
/etc/snort/snort.scripts/snort.default -> /etc/default/snort
/etc/snort/snort.scripts/snort.initd -> /etc/init.d/snort

The above should be configured to match specific sensor environment. The /etc/default/snort file works will with the init.d script and will override settings in /etc/snort/snort.conf ; snort.debian.conf is good for determining specifying the interface and settings debian specific. Please be reminded to check the path for the snort binary in the init.d script.

After chmod +x /etc/init.d/snort

Make init script an init script, do:
# update-rc.d snort defaults 95
Or use sysvconfig...

12. Set up cron jobs for oinkmaster running & auto email.


Set up favorite email daemon to send mail, then, in /etc/crontab add the following (if mail isn't set up, set it up):
# snort
49 5    * * *   root    /root/scripts/oinkoink.sh
50 5    * * *   root    /usr/local/bin/oinkmaster.pl -C /etc/oinkmaster.conf -o \
/etc/snort/rules | mail -s "oinkmaster client" youyesyou@somewherenothere.com
10 6    * * *   root    /etc/init.d/snort restart >> /dev/null 2>&1

Just to be safe, check if commandline mailing works:
echo testing | mail -s testorama youyesyou@somewherenothere.com

13. Start snort daemon


You're ready to start IDSing. Or something. On the client, execute:
# /etc/init.d/snort start

To watch snort start, stare at the appropriate syslog:
# tail -n 30 -f /var/log/syslog
Go to the repository webconsole and examine away once you've installed base... you have done that, right?

cidr cheat sheet


Netmask Netmask (binary) CIDR Notes
_____________________________________________________________________________
255.255.255.255 11111111.11111111.11111111.11111111 /32 Host (single addr)
255.255.255.254 11111111.11111111.11111111.11111110 /31 Unuseable
255.255.255.252 11111111.11111111.11111111.11111100 /30 2 useable
255.255.255.248 11111111.11111111.11111111.11111000 /29 6 useable
255.255.255.240 11111111.11111111.11111111.11110000 /28 14 useable
255.255.255.224 11111111.11111111.11111111.11100000 /27 30 useable
255.255.255.192 11111111.11111111.11111111.11000000 /26 62 useable
255.255.255.128 11111111.11111111.11111111.10000000 /25 126 useable
255.255.255.0 11111111.11111111.11111111.00000000 /24 "Class C" 254 useable

255.255.254.0 11111111.11111111.11111110.00000000 /23 2 Class C's
255.255.252.0 11111111.11111111.11111100.00000000 /22 4 Class C's
255.255.248.0 11111111.11111111.11111000.00000000 /21 8 Class C's
255.255.240.0 11111111.11111111.11110000.00000000 /20 16 Class C's
255.255.224.0 11111111.11111111.11100000.00000000 /19 32 Class C's
255.255.192.0 11111111.11111111.11000000.00000000 /18 64 Class C's
255.255.128.0 11111111.11111111.10000000.00000000 /17 128 Class C's
255.255.0.0 11111111.11111111.00000000.00000000 /16 "Class B"

255.254.0.0 11111111.11111110.00000000.00000000 /15 2 Class B's
255.252.0.0 11111111.11111100.00000000.00000000 /14 4 Class B's
255.248.0.0 11111111.11111000.00000000.00000000 /13 8 Class B's
255.240.0.0 11111111.11110000.00000000.00000000 /12 16 Class B's
255.224.0.0 11111111.11100000.00000000.00000000 /11 32 Class B's
255.192.0.0 11111111.11000000.00000000.00000000 /10 64 Class B's
255.128.0.0 11111111.10000000.00000000.00000000 /9 128 Class B's
255.0.0.0 11111111.00000000.00000000.00000000 /8 "Class A"

254.0.0.0 11111110.00000000.00000000.00000000 /7
252.0.0.0 11111100.00000000.00000000.00000000 /6
248.0.0.0 11111000.00000000.00000000.00000000 /5
240.0.0.0 11110000.00000000.00000000.00000000 /4
224.0.0.0 11100000.00000000.00000000.00000000 /3
192.0.0.0 11000000.00000000.00000000.00000000 /2
128.0.0.0 10000000.00000000.00000000.00000000 /1
0.0.0.0 00000000.00000000.00000000.00000000 /0 IP space

Net Host Total
Net Addr Addr Addr Number
Class Range NetMask Bits Bits of hosts
----------------------------------------------------------
A 0-127 255.0.0.0 8 24 16777216 (i.e. 114.0.0.0)
B 128-191 255.255.0.0 16 16 65536 (i.e. 150.0.0.0)
C 192-254 255.255.255.0 24 8 256 (i.e. 199.0.0.0)
D 224-239 (multicast)
E 240-255 (reserved)
F 208-215 255.255.255.240 28 4 16
G 216/8 ARIN - North America
G 217/8 RIPE NCC - Europe
G 218-219/8 APNIC
H 220-221 255.255.255.248 29 3 8 (reserved)
K 222-223 255.255.255.254 31 1 2 (reserved)

ref: RFC1375 & http://www.iana.org/assignments/ipv4-address-space
http://www.iana.org/numbers.htm

----------------------------------------------------------

The current list of special use prefixes:
0.0.0.0/8
127.0.0.0/8
192.0.2.0/24
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
169.254.0.0/16
all D/E space

ref: RFC1918 http://www.rfc-editor.org/rfc/rfc1918.txt
or ftp://ftp.isi.edu/in-notes/rfc1918.txt
rfc search: http://www.rfc-editor.org/rfcsearch.html
http://www.ietf.org/ietf/1id-abstracts.txt
http://www.ietf.org/shadow.html

iptables

HOWTO Iptables for newbies
From Gentoo Linux Wiki

Iptables is a userspace command line program that can plug into netfilter (a set of hooks inside the Linux kernel that allows kernel modules to register callback functions with the network stack. ) Iptables is used to set up, maintain, and inspect the tables of IP packet filter rules in the Linux kernel.

Contents
Introduction
I found the iptables documentation available to be severely newbie unfriendly. Most assumed a more than working knowledge of ipchains and pretty much picked up from there. Usually my approach to a new endeavor is that I want the option of getting up and going quickly, with minimal explanation. Afterwards I go back to read over more advanced options. This howto is designed with that in mind. It will show you how to setup basic functionality get you connected quickly and then it will incrementally show how to add policies and rules that can help a safe connection.

QuickStart Guide
Create basic iptable functionality.

Kernel Support
Check to see if you have kernel support for netfilter / iptables

zgrep -i netfilter /proc/config.gz
CONFIG_NETFILTER=y
or

grep -i netfilter /usr/src/linux/.config
CONFIG_NETFILTER=y

If not then you'll need to compile iptables support into the kernel.

You can either do this manually with the kernel sources:


cp /usr/src/linux/.config /etc/linux-config.bak
emerge sync && USE=symlink emerge -nk gentoo-sources
cd /usr/src/linux
cp /etc/linux-config.bak /usr/src/linux/.config
make menuconfig

Warning: These commands can be considered as being "bad practice" and should not be used relentlessly. You might consider doing a make oldconfig before the make menuconfig, but it's still not recommended to copy configurations from one kernel version to another.

Alternatively, you will probably find it easier to use genkernel. Either way, once you get to the menu configuration you will need to enable to following:





Linux Kernel Configuration: Netfilter



As for kernel 2.6.16 up you have to enable Xtables support first, iptables next


Networking  ---->
Networking options ---->
Network Packet Filtering (replaces Ipchains)--->
Core Netfilter Configuration ---->
["enable"] Netfilter Xtables support (required for ip_tables)
["enable"] Netfilter Xtables_Match_State, most firewall scripts use state...including the sample here.
IP: Netfilter Configuration --->

["enable"] IP tables support (required for filtering/masq/NAT)
["enable"] Packet Filtering
IPv6: Netfilter Configuration (EXPERIMENTAL) --->
IP6 tables support (required for filtering/masq/NAT)


Select the IPv6 option only if you need it.





Linux Kernel Configuration: Netfilter


  • NOTE As of kernel 2.6.20 (as of 2.6.19) you must enable the following

Networking  ---->
Networking options ---->
Network packet filtering framework (Netfilter)--->
Core Netfilter Configuration ---->
["enable"] Netfilter connection tracking support--->Layer 3 Independent Connection tracking
["enable"] Netfilter Xtables support (required for ip_tables)
["enable"] "state" match support
IP: Netfilter Configuration --->

["enable"] IPv4 connection tracking support (required for NAT) required by "Layer 3 Ind Conn tracking"
["enable"] IP tables support (required for filtering/masq/NAT)
["enable"] Packet Filtering
["enable"] REJECT target support


Edit Above (Kernel 2.6.20): "Reject Target Support" needs to be also enabled or the rules below will not load.





Linux Kernel Configuration: Netfilter


  • NOTE As of kernel 2.6.22 you must enable the following

Networking  ---->
Networking options ---->
Network packet filtering framework (Netfilter)--->
Core Netfilter Configuration ---->
["enable"] Netfilter connection tracking support--->Layer 3 Independent Connection tracking
["enable"] Netfilter Xtables support (required for ip_tables)
["enable"] "NFLOG" target support
["enable"] "conntrack" connection tracking match support
["enable"] "state" match support
IP: Netfilter Configuration --->

["enable"] IPv4 connection tracking support (required for NAT) required by "Layer 3 Ind Conn tracking"
["enable"] IP tables support (required for filtering/masq/NAT)
["enable"] Packet Filtering
["enable"] REJECT target support
["enable"] Full NAT
["enable"] MASQUERADE target support



If you intend to load iptables as a module,







Linux Kernel Configuration: Loadable Module Support


also make sure you have automatic kernel module loading enabled


Loadable module support --->
[*] Enable loadable module support
[ ] ...
[*] Automatic kernel module loading


Build the kernel:
make && make modules_install

If you're just a newbie (hence this guide) then just go ahead and enable all of the options as modules - if you don't upgrade the kernel you won't even have to reboot to use iptables. Enable the various target/match support options also.

Because you'll likely want the iptables module to load every time you boot:


echo "ip_tables" >> /etc/modules.autoload.d/kernel-2.6
echo "iptable_filter" >> /etc/modules.autoload.d/kernel-2.6
echo "nf_conntrack" >> /etc/modules.autoload.d/kernel-2.6
echo "nf_conntrack_ipv4" >> /etc/modules.autoload.d/kernel-2.6
echo "xt_state" >> /etc/modules.autoload.d/kernel-2.6
echo "xt_tcpudp" >> /etc/modules.autoload.d/kernel-2.6
echo "ipt_REJECT" >> /etc/modules.autoload.d/kernel-2.6
update-modules

The first two lines enable basic iptables support; the remaining lines load modules required for specific matching and state tracking rules.

Basic iptables Configuration
You'll need to get the userland utilities. Don't forget to modprobe ip_tables and modprobe iptable_filter if you have built them as a module.

emerge iptables
The average home user might want something that accepts certain incoming connections but blocks everything else.

1. Save your current firewall rules iptables-save > /etc/iptables.bak
2. Open /etc/iptables.bak in your favorite text editor
3. Add the following rule(s) in appropriate order (according to your existing rules).







File: /etc/iptables.bak

# Generated by iptables-save v1.2.11 on Tue May 10 08:06:58 2005
*filter
:INPUT ACCEPT [5:952]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1192099:595387635]

# accept all from localhost
-A INPUT -s 127.0.0.1 -j ACCEPT

# accept all previously established connections
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# ssh
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

# ftp / webserver related
-A INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT

# Windows / Samba
-A INPUT -p tcp -m state --state NEW -m tcp --dport 137:139 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 426 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 445 -j ACCEPT

# up to 5 Bit-torrent connections
-A INPUT -p tcp -m state --state NEW -m tcp --dport 6881:6886 -j ACCEPT

# reject everything else
-A INPUT -j REJECT --reject-with icmp-port-unreachable

COMMIT
# Completed on Tue May 10 08:06:58 2005



4. Restore all rules to be part of your current configuration

iptables-restore  /etc/iptables.bak
5. Save the configurations:

/etc/init.d/iptables save
And then back up your working configuration in case you break something later you can quickly revert:

cp /var/lib/iptables/rules-save /var/lib/iptables/rules.working
Now check up your iptables start-up script before adding iptables to your default runlevel:

/etc/init.d/iptables start; /etc/init.d/iptables stop; /etc/init.d/iptables start
The reason we start, then stop, then start again is because we haven't yet started the iptables script...so we must set the “initialized” status before stopping. Stopping essentially erases all settings and puts you back to zero.

If everything works well and you don't seem to have lost access to the server, then you can add iptables to the default runlevel:

rc-update add iptables default

GUI Alternatives
Or if you are so inclined, you can also configure iptables using the firestarter GUI (for GNOME users).
emerge firestarter

Note: net-firewall/firestarter in portage is masked, marked for removal on the 29th June 2007
or kmyfirewall (for KDE users)

emerge kmyfirewall
Another alternative is to use guarddog (QT).

emerge guarddog

Firewall Hardening


In the following, we're going to further secure our now functional firewall. By the time we are through we should have a set of tested rules and policies that will prevent not only attacks to our own computer, but also attacks from our computer to the internet. Protecting others from the possibility of being attacked by one of our compromised computers is an essential and often overlooked aspect of security and common internet courtesy. I would even say for the SOHO network this is the most important aspect. Normally virus infection is only a minor nuissance to a small network and rarely results in data loss....for us 100% *nix users it practically doesn't even exist. However, since small soho networks are often less secure than larger ones they are a favorite target for crackers looking for a “launchpad” for DoS attacks or other underhanded skullduggary.

The following is offered in a piecemeal fashion in a sequence that enables the easiest step by step testing. Each step may require that something be inserted before, after, or in the middle of our existing script. This was done so that (hopefully) your network will only go down for a brief period during setup. I've done it this way because I have assumed many of you (like me) have a standalone linux firewall/server. Since my preferred method is ssh, the network going down can be a PITA involving crawling under tables and such. If you're daring, you can just copy the script at the end and run it. It should be fully functional, but I have only tested it on my system so ymmv.

Setting up environment variables
We will define our networks interfaces and various tools used in the script:





File: newfirewall.sh



#!/bin/sh
#
# ********** VARIABLE DEFINITIONS **********
#
# External interface
EXTIF="eth0"

# Internal interface
INTIF="eth1"
# Loop device/localhost
LPDIF="lo"
LPDIP="127.0.0.1"
LPDMSK="255.0.0.0"
LPDNET="$LPDIP/$LPDMSK"
# Text tools variables
IPT="/sbin/iptables"

IFC="/sbin/ifconfig"
G="/bin/grep"
SED="/bin/sed"
AWK="/usr/bin/awk"
ECHO="/bin/echo"
# Setting up external interface environment variables
# Set LC_ALL to "en" to avoid problems when awk-ing the IPs etc.
export LC_ALL="en"

EXTIP="`$IFC $EXTIF|$AWK /$EXTIF/'{next}//{split($0,a,":");split(a[2],a," ");print a[1];exit}'`"
EXTBC="255.255.255.255"
EXTMSK="`$IFC $EXTIF|$G Mask:|$SED 's/.*Mask:\([^ ]*\)/\1/'`"
EXTMSK="`$IFC $EXTIF|$AWK /$EXTIF/'{next}//{split($0,a,":");split(a[4],a," ");print a[1];exit}'`"

EXTNET="$EXTIP/$EXTMSK"
$ECHO "EXTIP=$EXTIP EXTBC=$EXTBC EXTMSK=$EXTMSK EXTNET=$EXTNET"
# Due to absence of EXTBC I manually set it to 255.255.255.255
# this (hopefully) will serve the same purpose
# Setting up environment variables for internal interface
INTIP="`$IFC $INTIF|$AWK /$INTIF/'{next}//{split($0,a,":");split(a[2],a," ");print a[1];exit}'`"
INTBC="`$IFC $INTIF|$AWK /$INTIF/'{next}//{split($0,a,":");split(a[3],a," ");print a[1];exit}'`"

INTMSK="`$IFC $INTIF|$AWK /$INTIF/'{next}//{split($0,a,":");split(a[4],a," ");print a[1];exit}'`"
INTNET="$INTIP/$INTMSK"
$ECHO "INTIP=$INTIP INTBC=$INTBC INTMSK=$INTMSK INTNET=$INTNET"



iptables ACCEPTS
Ok now we're going to set up the ACCEPTs which will allow us to communicate with our server. In reality this is very ill advised. A solid firewall policy should DENY then ACCEPT. But if you do that you lose all connections while you're testing so you're not sure if your ACCEPT rules work at all. So, though we are entering this first, it will be the second to last rule set in the final script.





File: accepts-firewall.sh



$IPT -t nat -A PREROUTING -j ACCEPT
# $IPT -t nat -A POSTROUTING -o $EXTIF -s $INTNET -j SNAT --to $EXTIP
# Comment out next line (that has "MASQUERADE") to not NAT internal network
$IPT -t nat -A POSTROUTING -o $EXTIF -s $INTNET1 -j MASQUERADE
$IPT -t nat -A POSTROUTING -o $EXTIF -s $INTNET2 -j MASQUERADE
$IPT -t nat -A POSTROUTING -j ACCEPT
$IPT -t nat -A OUTPUT -j ACCEPT
$IPT -A INPUT -p tcp --dport auth --syn -m state --state NEW -j ACCEPT
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT




iptables DROP & REJECT


Next we are going to define a couple of custom chains which will log DROP and REJECT events. This way we don't have to enter a separate line for each command entered. The logs will be sent to where your syslog default log messages are sent (usually /var/log/messages). Later I'm going to write a grep/sed script that will parse and organize these for easy viewing and set it as a daily cron job.
This should be inserted immediately after the above definitions. When you are done, run the script again. It should have no affect on functionality of the network since we're just setting definitions. But it will ensure that we have no errors thusfar.






File: logging-firewall.sh




# ********** LOGGING CHAINS **********
#
# We are now going to create a few custom chains that will result in
# logging of dropped packets. This will enable us to avoid having to
# enter a log command prior to every drop we wish to log. The
# first will be first log drops the other will log rejects.
# Do not complain if chain already exists (so restart is clean)
$IPT -N DROPl 2> /dev/null
$IPT -A DROPl -m limit --limit 3/minute --limit-burst 10 -j LOG --log-prefix 'FIREWALL DROP BLOCKED:'
$IPT -A DROPl -j DROP
$IPT -N REJECTl 2> /dev/null
$IPT -A REJECTl -m limit --limit 3/minute --limit-burst 10 -j LOG --log-prefix 'FIREWALL REJECT BLOCKED:'
$IPT -A REJECTl -j REJECT
$IPT -N DROP2 2> /dev/null
$IPT -A DROP2 -m limit --limit 3/second --limit-burst 10 -j LOG --log-prefix 'FIREWALL DROP UNKNOWN:'
$IPT -A DROP2 -j DROP
$IPT -N REJECT2 2> /dev/null
$IPT -A REJECT2 -m limit --limit 3/second --limit-burst 10 -j LOG --log-prefix 'FIREWALL REJECT UNKNOWN:'
$IPT -A REJECT2 -j REJECT
# For testing, a logging ACCEPT chain
$IPT -N ACCEPTl 2> /dev/null
$IPT -A ACCEPTl -m limit --limit 10/second --limit-burst 50 -j LOG --log-prefix 'FIREWALL ACCEPT:'
$IPT -A ACCEPTl -j ACCEPT




iptables flushing
Ok, now that we see our devices are being detected properly, we are going to insert a flush commands. So that when our rules are assigned it will be done cleanly. These lines should be inserted after our utilities definitions, the last one being:





File: sed-script.sed




SED='/bin/sed'
# Flush all existing chains and erase personal chains
CHAINS=`cat /proc/net/ip_tables_names 2>/dev/null`
for i in $CHAINS
do
$IPT -t $i -F
done
for i in $CHAINS
do
$IPT -t $i -X
done



Local interfaces
Now we're ready to start laying down some rules. First we are going to accept all packets from our loopback device if the ip address matches that of any of our local interfaces:

$IPT -A INPUT   -i $LPDIF -s   $LPDIP   -j ACCEPT
$IPT -A INPUT -i $LPDIF -s $EXTIP -j ACCEPT
$IPT -A INPUT -i $LPDIF -s $INTIP1 -j ACCEPT
$IPT -A INPUT -i $LPDIF -s $INTIP2 -j ACCEPT

Blocking broadcasting
Now we will block broadcasts both incoming and outgoing. This can prevent DoS attacks against us, as well as preventing our clients from being used to DoS someone else. This is part of what's called "Egress Protection". It's a do unto your neighbour sort of philosophy. If all SysAdmins followed this policy, than many of the more severe and costly DoS attacks would either not have occurred or been extremely limited.

# Blocking Broadcasts
$IPT -A INPUT -i $EXTIF -d $EXTBC -j DROPl
$IPT -A INPUT -i $INTIF1 -d $INTBC1 -j DROPl
$IPT -A INPUT -i $INTIF2 -d $INTBC2 -j DROPl
$IPT -A OUTPUT -o $EXTIF -d $EXTBC -j DROPl
$IPT -A OUTPUT -o $INTIF1 -d $INTBC1 -j DROPl
$IPT -A OUTPUT -o $INTIF2 -d $INTBC2 -j DROPl
$IPT -A FORWARD -o $EXTIF -d $EXTBC -j DROPl
$IPT -A FORWARD -o $INTIF1 -d $INTBC1 -j DROPl
$IPT -A FORWARD -o $INTIF2 -d $INTBC2 -j DROPl
Now test the script once more to ensure we have no syntax errors. Also notice that we are using our newly defined DROPl chain. This means that the dropped packets will be logged.

Block WAN to LAN
Next we are going to block WAN access to our LAN if not specifically intended for our ISP assign IP:

# Block WAN access to internal network
# This also stops nefarious crackers from using our network as a
# launching point to attack other people
# iptables translation:
# "if input going into our external interface isn't being sent to our isp assigned
# ip address, drop it like a hot potato"
$IPT -A INPUT -i $EXTIF -d ! $EXTIP -j DROPl

Tightening the internal LAN
We're going to apply the same logic to our internal LAN. In other words, any packets not originating from our predefined internal network will be rejected:

# Now we will block internal addresses originating from anything but our
# two predefined interfaces.....just remember that if you jack your
# your laptop or another pc into one of these NIC's directly, you'll need
# to ensure that they either have the same ip or that you add a line explicitly
# that IP as well
# Interface one/internal net one
$IPT -A INPUT -i $INTIF1 -s ! $INTNET1 -j DROPl
$IPT -A OUTPUT -o $INTIF1 -d ! $INTNET1 -j DROPl
$IPT -A FORWARD -i $INTIF1 -s ! $INTNET1 -j DROPl
$IPT -A FORWARD -o $INTIF1 -d ! $INTNET1 -j DROPl
# Interface two/internal net two
$IPT -A INPUT -i $INTIF2 -s ! $INTNET2 -j DROPl
$IPT -A OUTPUT -o $INTIF2 -d ! $INTNET2 -j DROPl
$IPT -A FORWARD -i $INTIF2 -s ! $INTNET2 -j DROPl
$IPT -A FORWARD -o $INTIF2 -d ! $INTNET2 -j DROPl

Next we do some more Egress checking of outgoing packets and stop all icmp requests except for pinging:

# An additional Egress check
$IPT -A OUTPUT -o $EXTIF -s ! $EXTNET -j DROPl
# Block outbound ICMP (except for PING)
$IPT -A OUTPUT -o $EXTIF -p icmp --icmp-type ! 8 -j DROPl
$IPT -A FORWARD -o $EXTIF -p icmp --icmp-type ! 8 -j DROPl
Ok, where moving along now and we should test the script for errors.

Ports

Assuming an all clear we're going to start plugging some of the more bothersome port holes:

# COMmon ports:
# 0 is tcpmux; SGI had vulnerability, 1 is common attack
# 13 is daytime
# 98 is Linuxconf
# 111 is sunrpc (portmap)
# 137:139, 445 is Microsoft
# SNMP: 161,2
# Squid flotilla: 3128, 8000, 8008, 8080
# 1214 is Morpheus or KaZaA
# 2049 is NFS
# 3049 is very virulent Linux Trojan, mistakable for NFS
# Common attacks: 1999, 4329, 6346
# Common Trojans 12345 65535
COMBLOCK="0:1 13 98 111 137:139 161:162 445 1214 1999 2049 3049 4329 6346 3128 8000 8008 8080 12345 65535"
# TCP ports:
# 98 is Linuxconf
# 512-515 is rexec, rlogin, rsh, printer(lpd)
# [very serious vulnerabilities; attacks continue daily]
# 1080 is Socks proxy server
# 6000 is X (NOTE X over SSH is secure and runs on TCP 22)
# Block 6112 (Sun's/HP's CDE)
TCPBLOCK="$COMBLOCK 98 512:515 1080 6000:6009 6112"

# UDP ports:
# 161:162 is SNMP
# 520=RIP, 9000 is Sangoma
# 517:518 are talk and ntalk (more annoying than anything)
UDPBLOCK="$COMBLOCK 161:162 520 123 517:518 1427 9000 9 6346 3128 8000 8008 8080 12345 65535"
After defining the environment variables all we have to do is a simple for loop to assign rules to them all:

echo -n "FW: Blocking attacks to TCP port"
for i in $TCPBLOCK;
do
echo -n "$i "
$IPT -A INPUT -p tcp --dport $i -j DROPl
$IPT -A OUTPUT -p tcp --dport $i -j DROPl
$IPT -A FORWARD -p tcp --dport $i -j DROPl
done
echo ""

echo -n "FW: Blocking attacks to UDP port "
for i in $UDPBLOCK;
do
echo -n "$i "
$IPT -A INPUT -p udp --dport $i -j DROPl
$IPT -A OUTPUT -p udp --dport $i -j DROPl
$IPT -A FORWARD -p udp --dport $i -j DROPl
done
echo ""
Ok, now with iptables each time we run the script it simply appends these to already existing chains...so things are probably getting a bit messy. For that reason we're going to jump to the beginning of our script....right after the enviroment variables for sed and grep, but before those of EXTIP and EXTBC and add a loop that deletes and flushes. This ensure we're working from a clean state. We didn't want to do that before because we couldn't have tested our script without either shutting down our connection or dropping our firewall completely. This script first sets all policies to DROP, than flushes and deletes our chains. In order to ensure that we can still ssh back into our server after a script restart we are going to append an INPUT chain for ssh. This should always be placed at the end of the script for now. This done in order to prevent a window from opening up while we reset rules which is a common error made:

# Deny than accept: this keeps holes from opening up
# while we close ports and such
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP

# Flush all existing chains and erase personal chains
CHAINS=`cat /proc/net/ip_tables_names 2>/dev/null`
for i in $CHAINS;
do
$IPT -t $i -F
done
for i in $CHAINS;
do
$IPT -t $i -X
done
$IPT -A INPUT -i $INTIF1 -p tcp --dport 22 --syn -m state --state NEW -j ACCEPT

Sysctl's
Right afterwards we are going to activate the sysctl's for tcp_syncookies, icmp_echo_ignore_broadcasts, rp_filter, and accept_source_route. Heretofore many of the rules we've been "testing" haven't been able to actually work. In essence we were simply doing syntax error tests. Now our rules will be "for real":

echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

# Source Address Verification
for f in /proc/sys/net/ipv4/conf/*/rp_filter;
do
echo 1 > $f
done
# Disable IP source routing and ICMP redirects
for f in /proc/sys/net/ipv4/conf/*/accept_source_route;
do
echo 0 > $f
done
for f in /proc/sys/net/ipv4/conf/*/accept_redirects;
do
echo 0 > $f
done
echo 1 > /proc/sys/net/ipv4/ip_forward

Now we're going to add ftp connection tracking so that we won't get PASV errors when emerging packages:

# Opening up ftp connection tracking
MODULES="ip_nat_ftp ip_conntrack_ftp"
for i in $MODULES;
do
echo "Inserting module $i"
modprobe $i
done

Basic Service NAT
Now back to end of our script, we are going to open up services for systems behind our firewall. I have included services such as IRC, MSN, ICQ, and NFS, FTP, domain, and time. And some others. The important thing to note is that these will ONLY be availabe BEHIND the firewall. So this will not enable someone to ftp into your LAN:

IRC='ircd'
MSN=1863
ICQ=5190
NFS='sunrpc'
# We have to sync!!
PORTAGE='rsync'
OpenPGP_HTTP_Keyserver=11371
# All services ports are read from /etc/services
TCPSERV="domain ssh http https ftp ftp-data mail pop3 pop3s imap3 imaps imap2 time $PORTAGE $IRC $MSN $ICQ $OpenPGP_HTTP_Keyserver"
UDPSERV="domain time"
echo -n "FW: Allowing inside systems to use service:"
for i in $TCPSERV;
do
echo -n "$i "
$IPT -A OUTPUT -o $EXTIF -p tcp -s $EXTIP --dport $i --syn -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF1 -p tcp -s $INTNET1 --dport $i --syn -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF2 -p tcp -s $INTNET2 --dport $i --syn -m state --state NEW -j ACCEPT
done
echo ""

echo -n "FW: Allowing inside systems to use service:"
for i in $UDPSERV;
do
echo -n "$i "
$IPT -A OUTPUT -o $EXTIF -p udp -s $EXTIP --dport $i -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF1 -p udp -s $INTNET1 --dport $i -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF2 -p udp -s $INTNET2
done
echo ""

Now we're done all that's left is allowing us to ping the outside world by opening up pinging out of the firewall:

# Allow to ping out
$IPT -A OUTPUT -o $EXTIF -p icmp -s $EXTIP --icmp-type 8 -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF1 -p icmp -s $INTNET1 --icmp-type 8 -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF2 -p icmp -s $INTNET2 --icmp-type 8 -m state --state NEW -j ACCEPT

# Allow firewall to ping internal systems
$IPT -A OUTPUT -o $INTIF1 -p icmp -s $INTNET1 --icmp-type 8 -m state --state NEW -j ACCEPT
$IPT -A OUTPUT -o $INTIF2 -p icmp -s $INTNET2 --icmp-type 8 -m state --state NEW -j ACCEPT
Now we are going to default to DROP and Log anything that's left in case we overlooked something. The ACCEPT entry's we made at the very beginning would come right before this in the final script:

# Log & block whatever is left
$IPT -A INPUT -j DROPl
$IPT -A OUTPUT -j REJECTl
$IPT -A FORWARD -j DROPl
And you're done. I had a friend nmap and nessus my connection with this rule set and as far as both of them were concerned the only thing it was even slightly sure about was that the ip existed...other than that nothing. I can IRC, MSN, ICQ, ane emerge sync to my hearts content.

PART III will cover setting up some essential SOHO services like NFS and CUPS in a security conscious manner.


Scripts
A couple scripts.

The full script
Now here's the full script from the above information in all its glory (I also put the ssh forwarding in a more appropriate place):





File: iptables.sh



# First set LC_ALL to en to avoid l10n problems when awk-ing IPs etc.
export LC_ALL="en"
# External interface
EXTIF=ppp0
# Internal interface
INTIF1=eth1
INTIF2=eth2
# Loop device/localhost
LPDIF=lo
LPDIP=127.0.0.1
LPDMSK=255.0.0.0
LPDNET="$LPDIP/$LPDMSK"
# Text tools variables
IPT='/sbin/iptables'
IFC='/sbin/ifconfig'
G='/bin/grep'
SED='/bin/sed'
# Last but not least, the users
JAMES=192.168.1.77
TERESA=192.168.2.77
# Deny then accept: this keeps holes from opening up
# while we close ports and such
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
# Flush all existing chains and erase personal chains
CHAINS=`cat /proc/net/ip_tables_names 2>/dev/null`
for i in $CHAINS;
do
$IPT -t $i -F
done
for i in $CHAINS;
do
$IPT -t $i -X
done
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# Source Address Verification
for f in /proc/sys/net/ipv4/conf/*/rp_filter;
do
echo 1 > $f
done
# Disable IP source routing and ICMP redirects
for f in /proc/sys/net/ipv4/conf/*/accept_source_route;
do
echo 0 > $f
done
for f in /proc/sys/net/ipv4/conf/*/accept_redirects;
do
echo 0 > $f
done
echo 1 > /proc/sys/net/ipv4/ip_forward
# Setting up external interface environment variables
EXTIP="`$IFC $EXTIF|$G addr:|$SED 's/.*addr:\([^ ]*\) .*/\1/'`"

#EXTBC="`$IFC $EXTIF|$G Bcast:|$SED 's/.*Bcast:\([^ ]*\) .*/\1/'`"
EXTBC="255.255.255.255"
EXTMSK="`$IFC $EXTIF|$G Mask:|$SED 's/.*Mask:\([^ ]*\)/\1/'`"
EXTNET="$EXTIP/$EXTMSK"
#echo "EXTIP=$EXTIP EXTBC=$EXTBC EXTMSK=$EXTMSK EXTNET=$EXTNET"
echo "EXTIP=$EXTIP EXTBC=$EXTBC EXTMSK=$EXTMSK EXTNET=$EXTNET"

# Due to absence of EXTBC I manually set it to 255.255.255.255
# this (hopefully) will serve the same purpose
# Setting up environment variables for internal interface one
INTIP1="`$IFC $INTIF1|$G addr:|$SED 's/.*addr:\([^ ]*\) .*/\1/'`"
INTBC1="`$IFC $INTIF1|$G Bcast:|$SED 's/.*Bcast:\([^ ]*\) .*/\1/'`"
INTMSK1="`$IFC $INTIF1|$G Mask:|$SED 's/.*Mask:\([^ ]*\)/\1/'`"
INTNET1="$INTIP1/$INTMSK1"
echo "INTIP1=$INTIP1 INTBC1=$INTBC1 INTMSK1=$INTMSK1 INTNET1=$INTNET1"
#Setting up environment variables for internal interface two
INTIP2="`$IFC $INTIF2|$G addr:|$SED 's/.*addr:\([^ ]*\) .*/\1/'`"

INTBC2="`$IFC $INTIF2|$G Bcast:|$SED 's/.*Bcast:\([^ ]*\) .*/\1/'`"
INTMSK2="`$IFC $INTIF2|$G Mask:|$SED 's/.*Mask:\([^ ]*\)/\1/'`"
INTNET2="$INTIP2/$INTMSK2"
echo "INTIP2=$INTIP2 INTBC2=$INTBC2 INTMSK2=$INTMSK2 INTNET2=$INTNET2"
# We are now going to create a few custom chains that will result in
# logging of dropped packets. This will enable us to avoid having to
# enter a log command prior to every drop we wish to log. The
# first will be first log drops the other will log rejects.
# Do not complain if chain already exists (so restart is clean)
$IPT -N DROPl 2> /dev/null
$IPT -A DROPl -j LOG --log-prefix 'DROPl:'
$IPT -A DROPl -j DROP
$IPT -N REJECTl 2> /dev/null
$IPT -A REJECTl -j LOG --log-prefix 'REJECTl:'
$IPT -A REJECTl -j REJECT
# Now we are going to accpet all traffic from our loopback device
# if the IP matches any of our interfaces.
$IPT -A INPUT -i $LPDIF -s $LPDIP -j ACCEPT
$IPT -A INPUT -i $LPDIF -s $EXTIP -j ACCEPT
$IPT -A INPUT -i $LPDIF -s $INTIP1 -j ACCEPT
$IPT -A INPUT -i $LPDIF -s $INTIP2 -j ACCEPT
# Blocking Broadcasts
$IPT -A INPUT -i $EXTIF -d $EXTBC -j DROPl
$IPT -A INPUT -i $INTIF1 -d $INTBC1 -j DROPl
$IPT -A INPUT -i $INTIF2 -d $INTBC2 -j DROPl
$IPT -A OUTPUT -o $EXTIF -d $EXTBC -j DROPl
$IPT -A OUTPUT -o $INTIF1 -d $INTBC1 -j DROPl
$IPT -A OUTPUT -o $INTIF2 -d $INTBC2 -j DROPl
$IPT -A FORWARD -o $EXTIF -d $EXTBC -j DROPl
$IPT -A FORWARD -o $INTIF1 -d $INTBC1 -j DROPl
$IPT -A FORWARD -o $INTIF2 -d $INTBC2 -j DROPl
# Block WAN access to internal network
# This also stops nefarious crackers from using our network as a
# launching point to attack other people
# iptables translation:
# "if input going into our external interface does not originate from our isp assigned
# ip address, drop it like a hot potato
$IPT -A INPUT -i $EXTIF -d ! $EXTIP -j DROPl
# Now we will block internal addresses originating from anything but our
# two predefined interfaces.....just remember that if you jack your
# your laptop or another pc into one of these NIC's directly, you'll need
# to ensure that they either have the same ip or that you add a line explicitly
# for that IP as well
# Interface one/internal net one
$IPT -A INPUT -i $INTIF1 -s ! $INTNET1 -j DROPl
$IPT -A OUTPUT -o $INTIF1 -d ! $INTNET1 -j DROPl
$IPT -A FORWARD -i $INTIF1 -s ! $INTNET1 -j DROPl
$IPT -A FORWARD -o $INTIF1 -d ! $INTNET1 -j DROPl
# Interface two/internal net two
$IPT -A INPUT -i $INTIF2 -s ! $INTNET2 -j DROPl
$IPT -A OUTPUT -o $INTIF2 -d ! $INTNET2 -j DROPl
$IPT -A FORWARD -i $INTIF2 -s ! $INTNET2 -j DROPl
$IPT -A FORWARD -o $INTIF2 -d ! $INTNET2 -j DROPl
# An additional Egress check
$IPT -A OUTPUT -o $EXTIF -s ! $EXTNET -j DROPl
# Block outbound ICMP (except for PING)
$IPT -A OUTPUT -o $EXTIF -p icmp --icmp-type ! 8 -j DROPl
$IPT -A FORWARD -o $EXTIF -p icmp --icmp-type ! 8 -j DROPl
# COMmon ports:
# 0 is tcpmux; SGI had vulnerability, 1 is common attack
# 13 is daytime
# 98 is Linuxconf
# 111 is sunrpc (portmap)
# 137:139, 445 is Microsoft
# SNMP: 161,2
# Squid flotilla: 3128, 8000, 8008, 8080
# 1214 is Morpheus or KaZaA
# 2049 is NFS
# 3049 is very virulent Linux Trojan, mistakable for NFS
# Common attacks: 1999, 4329, 6346
# Common Trojans 12345 65535
COMBLOCK="0:1 13 98 111 137:139 161:162 445 1214 1999 2049 3049 4329 6346 3128 8000 8008 8080 12345 65535"

# TCP ports:
# 98 is Linuxconf
# 512-515 is rexec, rlogin, rsh, printer(lpd)
# [very serious vulnerabilities; attacks continue daily]
# 1080 is Socks proxy server
# 6000 is X (NOTE X over SSH is secure and runs on TCP 22)
# Block 6112 (Sun's/HP's CDE)
TCPBLOCK="$COMBLOCK 98 512:515 1080 6000:6009 6112"
# UDP ports:
# 161:162 is SNMP
# 520=RIP, 9000 is Sangoma
# 517:518 are talk and ntalk (more annoying than anything)
UDPBLOCK="$COMBLOCK 161:162 520 123 517:518 1427 9000"
echo -n "FW: Blocking attacks to TCP port "
for i in $TCPBLOCK;
do
echo -n "$i "
$IPT -A INPUT -p tcp --dport $i -j DROPl
$IPT -A OUTPUT -p tcp --dport $i -j DROPl
$IPT -A FORWARD -p tcp --dport $i -j DROPl
done
echo ""
echo -n "FW: Blocking attacks to UDP port "

for i in $UDPBLOCK;
do
echo -n "$i "
$IPT -A INPUT -p udp --dport $i -j DROPl
$IPT -A OUTPUT -p udp --dport $i -j DROPl
$IPT -A FORWARD -p udp --dport $i -j DROPl
done
echo ""
# Opening up ftp connection tracking
MODULES="ip_nat_ftp ip_conntrack_ftp"
for i in $MODULES;
do
echo "Inserting module $i"
modprobe $i
done
# Defining some common chat clients. Remove these from your accepted list for better security.
# ICQ and AOL are 5190
# MSN is 1863
# Y! is 5050
# Jabber is 5222
# Y! and Jabber ports not added by author and therefore left out of the script
IRC='ircd'
MSN=1863
ICQ=5190
NFS='sunrpc'
# We have to sync!!
PORTAGE='rsync'
OpenPGP_HTTP_Keyserver=11371
# All services ports are read from /etc/services
TCPSERV="domain ssh http https ftp ftp-data mail pop3 pop3s imap3 imaps imap2 \
time $PORTAGE $IRC $MSN $ICQ $OpenPGP_HTTP_Keyserver"
UDPSERV="domain time"

echo -n "FW: Allowing inside systems to use service:"
for i in $TCPSERV;
do
echo -n "$i "
$IPT -A OUTPUT -o $EXTIF -p tcp -s $EXTIP --dport $i --syn -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF1 -p tcp -s $INTNET1 --dport $i --syn -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF2 -p tcp -s $INTNET2 --dport $i --syn -m state --state NEW -j ACCEPT
done
echo ""
echo -n "FW: Allowing inside systems to use service:"
for i in $UDPSERV;
do
echo -n "$i "
$IPT -A OUTPUT -o $EXTIF -p udp -s $EXTIP --dport $i -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF1 -p udp -s $INTNET1 --dport $i -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF2 -p udp -s $INTNET2 --dport $i -m state --state NEW -j ACCEPT
done
echo ""

# Allow to ping out
$IPT -A OUTPUT -o $EXTIF -p icmp -s $EXTIP --icmp-type 8 -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF1 -p icmp -s $INTNET1 --icmp-type 8 -m state --state NEW -j ACCEPT
$IPT -A FORWARD -i $INTIF2 -p icmp -s $INTNET2 --icmp-type 8 -m state --state NEW -j ACCEPT
# Allow firewall to ping internal systems
$IPT -A OUTPUT -o $INTIF1 -p icmp -s $INTNET1 --icmp-type 8 -m state --state NEW -j ACCEPT
$IPT -A OUTPUT -o $INTIF2 -p icmp -s $INTNET2 --icmp-type 8 -m state --state NEW -j ACCEPT
$IPT -A INPUT -i $INTIF1 -p tcp --dport 22 --syn -m state --state NEW -j ACCEPT
$IPT -t nat -A PREROUTING -j ACCEPT
$IPT -t nat -A POSTROUTING -o $EXTIF -s $INTNET1 -j MASQUERADE
$IPT -t nat -A POSTROUTING -o $EXTIF -s $INTNET2 -j MASQUERADE
$IPT -t nat -A POSTROUTING -j ACCEPT
$IPT -t nat -A OUTPUT -j ACCEPT
$IPT -A INPUT -p tcp --dport auth --syn -m state --state NEW -j ACCEPT
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# Block and log what me may have forgot
$IPT -A INPUT -j DROPl
$IPT -A OUTPUT -j REJECTl
$IPT -A FORWARD -j DROPl



Another iptables startup script
Another iptables startup script designed for a local linux router / linux server.





File: /etc/init.d/iptables



#! /sbin/runscript

depend() {
before net
}

start() {
ebegin "Starting firewall"

modprobe ip_conntrack_ftp

# reset all tables
iptables -t filter -F
iptables -t nat -F

# delete all user chains
iptables -t filter -X
iptables -t nat -X

# drop all packets by default
iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -P OUTPUT DROP

# create needed user-chains
iptables -N drop_bad_packets

# create a chain, that filters all bad packets:
# drop all tcp-packets, that are not established and don't request a
# new connection and drop every "unclean" package
iptables -A drop_bad_packets -p tcp ! --syn -m state \
--state NEW -j DROP
iptables -A drop_bad_packets -m state --state INVALID -j DROP

# do not accept, send or forward illegal packets
iptables -A INPUT -j drop_bad_packets
iptables -A OUTPUT -j drop_bad_packets
iptables -A FORWARD -j drop_bad_packets

# drop all packets that are comming from/going to 127.0.0.1 and
# are not going through loopback device
iptables -A INPUT -i ! lo -s 127.0.0.1 -j DROP
iptables -A INPUT -i ! lo -d 127.0.0.1 -j DROP
iptables -A OUTPUT -o ! lo -s 127.0.0.1 -j DROP
iptables -A OUTPUT -o ! lo -d 127.0.0.1 -j DROP

# allow masqueraded forwarding for eth0 device
for i in $MASQUERADINGDEVICES ; do
iptables -t nat -A POSTROUTING -o "$i" -j MASQUERADE
done

# allow forwarding connections
for i in $FORWARDINGDEVICES ; do
src="`echo $i | awk -F: '{ print $1 }'`"

dest="`echo $i | awk -F: '{ print $2 }'`"

if [ -z "$src" ] || [ -z "$dest" ] ; then
ewarn "wrong FORWARDINGDEVICES entry (ignored): '$i'"
continue
fi

iptables -A FORWARD -i "$src" -o "$dest" -j ACCEPT
iptables -A FORWARD -i "$dest" -o "$src" -m state \
--state ESTABLISHED,RELATED -j ACCEPT
done

# allow all connections that are comming from or going to the
# loopback device and are from local host (other hosts wont be
# able to write to our loopback device)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

for i in $NETDEVICES ; do
# allow incoming data for established or related connections
iptables -A INPUT -i "$i" -m state \
--state ESTABLISHED,RELATED -j ACCEPT
# allow incoming ping requests
iptables -A INPUT -i "$i" -m state \
--state NEW --protocol icmp \
--icmp-type 8 -j ACCEPT
# allow all outging data
iptables -A OUTPUT -o "$i" -j ACCEPT
done


# allow all traffic from FULLACCESSIPS
for i in $FULLACCESSIPS ; do
device="`echo $i | awk -F: '{ print $1 }'`"

ip="`echo $i | awk -F: '{ print $2 }'`"

if [ -z "$ip" ] || [ -z "$device" ] ; then
ewarn "wrong FULLACCESSIPS entry (ignored): '$i'"
continue
fi

iptables -A INPUT -i "$device" -m state \
--state NEW \
--source "$ip" -j ACCEPT
done

# allow incomming connections to tcp ports
for i in $INCOMINGPORTS ; do
device="`echo $i | awk -F: '{ print $1 }'`"

proto="`echo $i | awk -F: '{ print $2 }'`"
ports="`echo $i | awk -F: '{ print $3 }'`"

if [ -z "$device" ] || [ -z "$ports" ] || [ -z "$proto" ]; then
ewarn "wrong INCOMINGPORTS entry (ignored): '$i'"

continue
fi
iptables -A INPUT -i "$device" -m state -m multiport \
--state NEW --protocol "$proto" \
--dport "$ports" -j ACCEPT
done

# reject all other incoming data instead of just dropping them
iptables -A INPUT -j REJECT

echo 0 >/proc/sys/net/ipv4/tcp_ecn
echo 1 >/proc/sys/net/ipv4/tcp_syncookies
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo 1 >"$f"
done

# activate IP-Forwarding
echo 1 >/proc/sys/net/ipv4/ip_dynaddr
echo 1 >/proc/sys/net/ipv4/ip_forward

eend 0
}

stop() {
echo 0 >/proc/sys/net/ipv4/tcp_ecn
echo 0 >/proc/sys/net/ipv4/tcp_syncookies
echo 0 >/proc/sys/net/ipv4/ip_forward
echo 0 >/proc/sys/net/ipv4/ip_dynaddr

for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo 0 >"$f"

done

ebegin "Stopping firewall"
for a in `cat /proc/net/ip_tables_names`; do
/sbin/iptables -F -t "$a"
/sbin/iptables -X -t "$a"

if [ "$a" == nat ]; then
/sbin/iptables -t nat -P PREROUTING ACCEPT
/sbin/iptables -t nat -P POSTROUTING ACCEPT
/sbin/iptables -t nat -P OUTPUT ACCEPT
elif [ "$a" == mangle ]; then
/sbin/iptables -t mangle -P PREROUTING ACCEPT
/sbin/iptables -t mangle -P INPUT ACCEPT
/sbin/iptables -t mangle -P FORWARD ACCEPT
/sbin/iptables -t mangle -P OUTPUT ACCEPT
/sbin/iptables -t mangle -P POSTROUTING ACCEPT
elif [ "$a" == filter ]; then
/sbin/iptables -t filter -P INPUT ACCEPT
/sbin/iptables -t filter -P FORWARD ACCEPT
/sbin/iptables -t filter -P OUTPUT ACCEPT
fi
done
eend $?
}




Note the following file is an EXAMPLE - DO NOT USE IT WITHOUT MODIFICATION






File: /etc/conf.d/iptables



# open incoming ports (device:proto:ports)
INCOMINGPORTS="eth0:tcp:22,80,443,1500-1510 eth0:udp:53"

# allow data connections through these devices
NETDEVICES="eth0 ppp0 tun1"

# allow forwardings on these devices (src:dest)
FORWARDINGDEVICES="eth0:ppp0 eth0:tun1"

# masquerade ips on these devices
MASQUERADINGDEVICES="ppp0"

# allow all traffic from these ips (device:ip)
FULLACCESSIPS="eth0:192.168.0.4"



Author's Original Script





File: firewall.sh



#!/bin/bash
IPTABLES='/sbin/iptables'
# Set interface values
EXTIF='ppp0'
INTIF1='eth1'
INTIF2='eth2'
# enable ip forwarding in the kernel
/bin/echo 1 > /proc/sys/net/ipv4/ip_forward
# flush rules and delete chains
$IPTABLES -F
$IPTABLES -X
# enable masquerading to allow LAN internet access
$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE
# forward LAN traffic from $INTIF1 to Internet interface $EXTIF
$IPTABLES -A FORWARD -i $INTIF1 -o $EXTIF -m state --state NEW,ESTABLISHED -j ACCEPT
# forward LAN traffic from $INTIF2 to Internet interface $EXTIF
$IPTABLES -A FORWARD -i $INTIF2 -o $EXTIF -m state --state NEW,ESTABLISHED -j ACCEPT
#echo -e " - Allowing access to the SSH server"
$IPTABLES -A INPUT --protocol tcp --dport 22 -j ACCEPT
#echo -e " - Allowing access to the HTTP server"
$IPTABLES -A INPUT --protocol tcp --dport 80 -j ACCEPT
# block out all other Internet access on $EXTIF
$IPTABLES -A INPUT -i $EXTIF -m state --state NEW,INVALID -j DROP
$IPTABLES -A FORWARD -i $EXTIF -m state --state NEW,INVALID -j DROP




Note: This script was written by someone on another forum....I've since lost the address to the thread or forum..., but thanks goes to him.

It can be found on: HOWTO_Iptables_and_stateful_firewalls


Reset iptables

iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F
iptables -X


Hardware Related Information

Interface configuration
The author created this document is using a PPPoE connection to the internet and the 2.6.x kernel.

However, the only adaptation that would need to be made is to replace 'ppp0' with 'eth0' (or whatever NIC you have facing the internet -- this will become clear later).

In my set up, I have three NIC's, one is connected to the WAN through PPPoE, the other two to my internal network. In order for them all to play nicely with iptables and masquerading (NAT'ing), they must be set to different subnets. For example, the two NIC's connected to my internal computers, e.g., the “internal NIC's”, are assigned: 192.168.1.1 and 192.168.2.1 respectively. It should be noted here that it is perfectly acceptable to connect these internal NIC's to any network capable device, such as a switch or hub. For pppoe connections we make sure the NIC connected to the outside world, e.g. the external NIC is not assigned any ip....its entries in /etc/conf.d/net should be left blank. This is due to pppoe acting as a virtual device which handles bringing up the NIC. We must also assign proper netmasks and broadcast values to these interfaces. Your /etc/conf.d/net should look like these:






File: /etc/conf.d/net


Server:


# For pppoe connections you do not want to set values for eth0, simply add
# net.ppp0 or rp-pppoe to your default runlevel
config_eth1=( "192.168.1.1 broadcast 192.168.1.255 netmask 255.255.255.0" )
config_eth2=( "192.168.2.1 broadcast 192.168.2.255 netmask 255.255.255.0" )


Client One:


config_eth0=( "192.168.1.77 broadcast 192.168.1.255 netmask 255.255.255.0" )
gateway_eth0=( "default via 192.168.1.1" )

Client Two:


config_eth0=( "192.168.2.77 broadcast 192.168.2.255 netmask 255.255.255.0" )
gateway_eth0=( "default via eth0/192.168.2.1" )




The gateways for the clients are set to the internal ip's of the NIC on the server as should be expected. Now add all the interfaces to the default run level and restart connections:

Start network cards

rc-update add net.eth1 default; rc-update add net.eth2 default; rc-update add net.ppp0 default;
/etc/init.d/net.eth1 restart; /etc/init.d/net.eth2 restart; /etc/init.d/net.ppp0 restart;
Now verify that you are connected to the internet on the server machine (the clients will not be.....yet) and that all the interfaces can ping each other.

Server

ping www.google.com;
ping 192.168.1.78
ping 192.168.2.78
ping 192.168.1.77
ping 192.168.2.77
Next ensure that your clients have appropriate DNS's set in your /etc/resolv.conf.

Troubleshooting

Failure on COMMIT lines
iptables failures will nearly always occur on the COMMIT lines. This is because while the rules are read earlier, iptables does not check the match (-m) option until this point. The actual error will be somewhere between the COMMIT line where the error occurred and the previous COMMIT line.

The first things to check for when you get errors are typos and that you have the correct modules loaded (if you're unsure, the easiest way is to build all the features into the kernel - you might want to skip features marked experimental for this as they may cause issues and you're unlikely to be using them).

One way to locate the line causing the problem is to disable all your rules (this can be done by commenting them out by placing a # at the beginning of the line) and then re-enabling them one-by-one until the error occurs.