CCL Home Page
Up Directory CCL mysetup.txt
Committed by Jan K. Labanowski ( in Aug. 2001.

How I installed the Firewall and IP Masquerading at home

I have a cable modem at home and about 4 computers working at a time
(I am usually plugged in as on Linux, and my wife and kids surf the net
with Windoz). My goal is to use a single IP address, and protect
my computers at home from attacks as it is feasible. I also plan
to move to DSL one day, and have static IP address. At that time,
I want to have a Web server and few other things on my firewall machine.

I started from reading. It all becomes clear after you read circa 100 pages.
Before that, you do not really know what you are doing.
When you read, take into account that this is bleeding edge technology,
that stuff which worked a year ago, need not to work today, since things
still change.

Nice collection of Netfilter documents is available at:

The Netfilter site: The Netfilter Project: Packet Mangling for Linux 2.4

Linux 2.4 Packet Filtering HOWTO
by Rusty Russel.

Linux Gets Stateful Firewalling:
by Jay Beale, 
Explains in a simple way the operation of the stateful firewall

Using Linux 2.4 Firewalling - Building a Firewall with Netfilter
by Jay Beale,
Explains how to use Netfilter

iptables Tutorial 1.0.7
by Oskar Andreasson

Common threads -- Dynamic iptables firewalls
by Daniel Robbins

James C. Stephens: Connection Tracking

Firewalling and Netfilter Terms

The quick guide to iptables (syntax only):

Kernel Recompilation

I took an old computer and installed Linux on it.
It had a cheap video card (S3 Virge), and 2 ether cards (an old ISA 3c509
and a tulip 10/100 clone which you can get at $10 a piece).

I installed 7.1 Red Hat from the first release CDs.
My PC had 78 Megs of memory, 20Gig drive, 200 Pentium MMX.
I had a Maxtor 20Gig drive. After I installed stuff, partitions looked like:

df -k
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/hda4             18295120   1474832  15890928   9% /
/dev/hda1               101089      3479     92391   4% /boot
/dev/hda3              1035692        20    983060   1% /ftp

Disk /dev/hda: 255 heads, 63 sectors, 2491 cylinders
Units = cylinders of 16065 * 512 bytes

   Device Boot    Start       End    Blocks   Id  System
/dev/hda1   *         1        13    104391   83  Linux
/dev/hda2            14        46    265072+  82  Linux swap
/dev/hda3            47       177   1052257+  83  Linux
/dev/hda4           178      2491  18587205   83  Linux

I created separate /ftp partition so in case I want to install ftp server
and do not want hackers to kill my computer by filling up the incoming

Started with stock RH 7.1 and made all the updates (but not
the kernel) until August 20, 2001.
I made sure that I boot in TTY console mode by changing the line
in /etc/inittab to be:


(you can do it by entering "linux single" on the LILO prompt when booting
which will put you in he single user mode). It will boot you to X-window
by default if you are not careful answering Xconfigurator queries.

Then installed 2 ether cards in my PC:
  a) old 3Com ISA 3C509 Etherlink III  (10BaseT)
  b) the cheap Tulip PCI card ($10) Linksys NC100 v 2.1  (10/100 BaseT)

Then, I put to /etc/modules.conf
alias eth0 3c509
alias eth1 tulip

I assume that eth0 will be pointing to outside internet (cable modem with
dynamic IP assignment) and eth1 will be my internal Ethernet (LAN).
BTW... If you are installing more than 1 Ethernet card in your box,
do yourself a favor. Install cards which use different modules. This
means that not only cards should be different, but also the drivers (i.e.,
modules) should be different. For example, there are tens of different
cards which use tulip.o driver. Use only one of these. It is my experience
that when cards are using the same module, they are not recognized/initialized
properly by the kernel, unless you compile them statically into the kernel.
Maybe I am missing something, but when cards use different drivers (modules)
they coexist sensibly. 

Then I rebooted the machine.

Then I logged in as root, and started X window


and configured my network interfaces by using: 


I clicked on Interfaces and as a result  I had the following table:

Interface         IP               proto   atboot      active
lo              none    yes         active
eth0                               dhcp    yes         active
eth1          none    yes         active

You can get there by clicking on Add/Edit/Remove/Activate and Save/Quit
at the bottom of the netcfg window. Or you can edit files yourself.

As a result I got:



You may (actually you must) want to read about kernel recompilation in
Brian Ward: The Linux Kernel HOWTO
It is available on many sites, but get some recent version
For example from:

Then, just in case, I made a copy of my /boot and /etc partition

mkdir /boot-old
cd /boot
tar cvf - . | ( cd /boot-old; tar xvf - )
mkdir /etc-old
cd /etc
tar cvf - . | ( cd /etc-old; tar xvf - )

I made a book diskette just in case
ls -l /boot            # find version of vmlinuz

mkinitrd /boot/initrd-2.4.2-2.img 2.4.2-2
fdformat /dev/fd0H1440
mkbootdisk --device /dev/fd0H1440 2.4.2-2

Now, saving configuration options for the current kernel

cd /usr/src
ls -l
lrwxrwxrwx    1 root     root           11 Aug 20 08:10 linux-2.4 -> linux-2.4.2
drwxr-xr-x   16 root     root         4096 Aug 21 08:15 linux-2.4.2
drwxr-xr-x    7 root     root         4096 Aug 20 08:07 redhat

I saved the config file from the /usr/src/linux-2.4.2/configs directory:
  cp /usr/src/linux-2.4.2/configs/kernel-2.4.2-i586.config  /root
since this was probably the file used to compile the default RH7.1 linux
for my MMX box.

Then removed the link in /usr/src
cd /usr/src
rm linux-2.4     # removed the link

I retrieved the latest version of linux kernel from using wget
(but you can start from


cd /usr/src
ls -l

drwxr-xr-x   16 root     root         4096 Aug 21 08:15 linux-2.4.2
-rw-r--r--    1 root     root     27474071 Aug 21 08:26 linux-2.4.9.tar.gz
drwxr-xr-x    7 root     root         4096 Aug 20 08:07 redhat

unpacked the tar achive
tar zxvf linux-2.4.9.tar.gz

renamed new directory
mv linux linux-2.4.9
ln -s linux-2.4.9 linux-2.4
ln -s linux-2.4.9 linux

My /usr/src is now:
ls -l 
total 26876
lrwxrwxrwx    1 root     root           11 Aug 21 09:38 linux -> linux-2.4.9
lrwxrwxrwx    1 root     root           11 Aug 21 08:30 linux-2.4 -> linux-2.4.9
drwxr-xr-x   16 root     root         4096 Aug 21 08:15 linux-2.4.2
drwxr-xr-x   14 1046     101          4096 Aug 16 14:13 linux-2.4.9
-rw-r--r--    1 root     root     27474071 Aug 21 08:26 linux-2.4.9.tar.gz
drwxr-xr-x    7 root     root         4096 Aug 20 08:07 redhat

Now, before you compile new linux kernel you need to remove the old
include files from /usr/include and put there the new include files

cd /usr/include
mv asm asm-2.4,2
mv linux linux-2.4.2
mv scsi scsi-2.4.2
ln -s /usr/src/linux-2.4/include/asm-i386 asm
ln -s /usr/src/linux-2.4/include/linux linux
ln -s /usr/src/linux-2.4/include/scsi scsi
Now, I wanted to reuse  the original RH7.1 kernel compilation config file
as much as possible file. Note that I am on Pentium MMX, so I use i586 configs.
This only asks me for new things which are new in the new kernel.

I did:

cd /usr/src/linux-2.4
cp /usr/src/linux-2.4.2/configs/kernel-2.4.2-i586.config .config
make oldconfig

Basically I accepted all m's (modules), since it is only compilation time,
and they are loaded only if they are needed. Now, I would probably be more
careful, since some of them have bugs, and you need to watch the compilation
(later) rather than leave it unattended and come back in a few hours.

I did not accept anything which requires additions to kernel. 
This is not very relevant, since I will have to go through these options
again with a  comb when I do configuration. This step is simply to make sure
that the
/usr/src/linux-2.4/.config file is in sync with the 2.4.9 kernel release.

I then saved the .config file just in case

cd /usr/src/linux-2.4
cp .config default.config

Now, I retrieved the iptables (v1.2.2) from
cd /root

It is bzipped tar. Check if you have bunzip2 installed:
If it tells you: "command not found", find it on your RH CDs or retrieve it
from the net, e.g.


and then 

rpm -Uhv bzip2-1.0.1-3.i386.rpm

Then, I unpacked the bzipped archive:

bunzip2 iptables-1.2.2.tar.bz2
tar xvf iptables-1.2.2.tar
(or you can just do it in one line as: tar jxvf iptables-1.2.2.tar,bz2 ).

Then I applied patches to kernel:

 make pending-patches KERNEL_DIR=/usr/src/linux

It told me:
Testing... 2.4.4.patch ALREADY APPLIED (6 rejects out of 96 hunks).

Excellent! Kernel is now ready for compilation.

Then I compiled kernel.

cd /usr/src/linux-2.4
make xconfig
and after going through questions, I clicked "Save and Exit"

This was an endless line of questioning. You have to make sure you
allow the Firewall and Masquerading options. To make it easy next time
to reproduce my answers, I saved my config file. Next time I only need
to Load it, change one item if needed, and then do Save and Exit.

cp /usr/src/linux-2.4/.config /root/config.nat
My config file is available together with this log from the index page.
You just copy it to 
and run old config on it just in case, you grabbed the newer kernel.

Then I executed regular steps for kernel compilation.

make dep
make clean

make bzImage

After about an hour, it finished and created bzImage:

-rw-r--r--    1 root     root       767981 Aug 21 12:46 bzImage

I copied the new bxImage it to /boot directory and changed its name:

cp -p /usr/src/linux-2.4.9/arch/i386/boot/bzImage /boot/vmlinuz-2.4.9-1

Then, I built modules:

make modules

Unfortunately, it gave me some errors for some modules:

gcc -D__KERNEL__ -I/usr/src/linux-2.4.9/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i586 -DMODULE -DMODVERSIONS -include /usr/src/linux-2.4.9/include/linux/modversions.h   -DEXPORT_SYMTAB -c miropcm20-rds-core.c
In file included from /usr/src/linux-2.4.9/include/asm/io.h:108,
                 from miropcm20-rds-core.c:23:
/usr/src/linux-2.4.9/include/linux/vmalloc.h: In function `vmalloc_dma':
/usr/src/linux-2.4.9/include/linux/vmalloc.h:45: Internal error: Segmentation fault.
Please submit a full bug report.
See  for instructions.
make[3]: *** [miropcm20-rds-core.o] Error 1
make[3]: Leaving directory `/usr/src/linux-2.4.9/drivers/media/radio'
make[2]: *** [_modsubdir_radio] Error 2
make[2]: Leaving directory `/usr/src/linux-2.4.9/drivers/media'
make[1]: *** [_modsubdir_media] Error 2
make[1]: Leaving directory `/usr/src/linux-2.4.9/drivers'
make: *** [_mod_drivers] Error 2

So I started again. You do not loose much, since make will not recompile
the stuff which has been already compiled.  

cd /usr/src/linux-2.4.9
make modules

It did it again few hours later:
gcc -D__KERNEL__ -I/usr/src/linux-2.4.9/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i586 -DMODULE -DMODVERSIONS -include /usr/src/linux-2.4.9/include/linux/modversions.h   -c -o pvr2fb.o pvr2fb.c
pvr2fb.c: In function `pvr2_update_display':
pvr2fb.c:876: warning: implicit declaration of function `ctrl_outl'
pvr2fb.c: In function `pvr2_init_display':
pvr2fb.c:930: warning: implicit declaration of function `ctrl_inl'
pvr2fb.c: In function `pvr2_init_cable':
pvr2fb.c:990: warning: implicit declaration of function `ctrl_inw'
pvr2fb.c: In function `pvr2fb_init':
pvr2fb.c:1009: `MACH_DREAMCAST' undeclared (first use in this function)
pvr2fb.c:1009: (Each undeclared identifier is reported only once
pvr2fb.c:1009: for each function it appears in.)
pvr2fb.c:1053: `HW_EVENT_VSYNC' undeclared (first use in this function)
make[2]: *** [pvr2fb.o] Error 1
make[2]: Leaving directory `/usr/src/linux-2.4.9/drivers/video'
make[1]: *** [_modsubdir_video] Error 2
make[1]: Leaving directory `/usr/src/linux-2.4.9/drivers'
make: *** [_mod_drivers] Error 2

so I did it again

cd /usr/src/linux-2.4.9
make modules

then again:
make[2]: Entering directory `/usr/src/linux-2.4.9/drivers/video'
gcc -D__KERNEL__ -I/usr/src/linux-2.4.9/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i586 -DMODULE -DMODVERSIONS -include /usr/src/linux-2.4.9/include/linux/modversions.h   -c -o pvr2fb.o pvr2fb.c
pvr2fb.c: In function `pvr2_update_display':
pvr2fb.c:876: warning: implicit declaration of function `ctrl_outl'
pvr2fb.c: In function `pvr2_init_display':
pvr2fb.c:930: warning: implicit declaration of function `ctrl_inl'
pvr2fb.c: In function `pvr2_init_cable':
pvr2fb.c:990: warning: implicit declaration of function `ctrl_inw'
pvr2fb.c: In function `pvr2fb_init':
pvr2fb.c:1009: `MACH_DREAMCAST' undeclared (first use in this function)
pvr2fb.c:1009: (Each undeclared identifier is reported only once
pvr2fb.c:1009: for each function it appears in.)
pvr2fb.c:1053: `HW_EVENT_VSYNC' undeclared (first use in this function)
make[2]: *** [pvr2fb.o] Error 1
make[2]: Leaving directory `/usr/src/linux-2.4.9/drivers/video'
make[1]: *** [_modsubdir_video] Error 2
make[1]: Leaving directory `/usr/src/linux-2.4.9/drivers'
make: *** [_mod_drivers] Error 2

so I did it again

cd /usr/src/linux-2.4.9
make modules

but it did not help... But do not worry, if this is not the module you really
need you can just cheat...

cd /usr/src/linux-2.4.9/drivers/video
mv pvr2fb.c pvr2fb.c.orig
cat > pvr2fb.c

(i.e., made empty file pvr2fb.c) since I will not be using this video card

And now, I asked the modules to be compiled again.
cd /usr/src/linux-2.4.9
make modules

So,finally, it finished after a few hours.

cd /usr/src/linux-2.4.9
make modules_install

Now, I had to make sure the new stuff is available for lilo to boot.

I already copied the bZimage there as vmlinuz-2.4.9-1.

cd /boot

# I removed links to old files: 
rm vmlinuz
rm module-info    (the module-info file is from RH *.rpm kernel distribution)
rm kernel.h

# I copied new fies to /boot directory
cp /usr/src/linux-2.4.9/
cp /usr/src/linux-2.4.9/include/linux/kernel.h kernel.h-2.4.9-1
cp /usr/src/linux-2.4.9/vmlinux vmlinux-2.4.9-1

# made new links
ln -s
ln -s vmlinuz-2.4.9-1 vmlinuz
ln -s kernel.h-2.4.9-1 /kernel.h

# made new ram disk image
mkinitrd /boot/initrd-2.4.9-1.img 2.4.9

To be consistent, I made a link in /lib/modules directory
cd /lib/modules
ln -s 2.4.9 2.4.9-1

edited /etc/lilo.conf to be:




and ran

 lilo -v

which updated the boot sector and boot maps, etc...

I also made a boot diskette in case I had problem booting from Hard Drive:

cd /boot
fdformat /dev/fd0H1440
mkbootdisk --device /dev/fd0 2.4.9-1

and then rebooted the machine.

It booted OK (Thank You My Lord...) and I logged in as root.

I installed the iptables package which came with RedHat since it is old..

First I stopped ipchains and removed init.d links which start ipchains
on boot
cd /etc/rc.d/init.d
./ipchains stop
chkconfig --del ipchains

Now, the
chkconfig --list ipchains
ipchains       	0:off	1:off	2:off	3:off	4:off	5:off	6:off

  rpm -q -a | grep iptables
  rpm  -e iptables-1.2.1a-1

As was described above, the new 1.2.2 version of iptables is already in:

cd /root/iptables-1.2.2
make KERNEL_DIR=/usr/src/linux BINDIR=/usr/bin LIBDIR=/usr/lib MANDIR=/usr/man
make install KERNEL_DIR=/usr/src/linux BINDIR=/usr/bin LIBDIR=/usr/lib MANDIR=/usr/man

Now, the Netfilter and all needed kernel modules are available.

I rebooted the machine

Networking arrangement
The goal was to make this:

 Internet---CableModem--[Ethernet Hub]--eth0(3C509)[Firewall/NAT Host]
                                                      eth1 []
                                 --------                 |
                                | Ether  | uplink         |
                                | Hub    |-----------------
                                |        |
                                |        |----------------------
                                |        |                      |
                                |        |-----------           |
                                |        |           |          |
                                |        |-----      |          |
                                |        |     |     |          |
                                |        |     |     |          |
                                |        |     |     |          |
                                |        |     |     |          |
                                 --------      |     |          |
                                               |     |          |
                                               |     |          |
                                 --------------      |          ------
                                 |                   |                |
                                 |                   |                |
                       Static IP address    Static IP address  Static IP add.
                          Linux Laptop          Windows 98       Windows 98
                             eth0                  eth0             eth0


Now, for testing, learning, and playing...

I had the setup which consisted of 200MMX PC[Firewall/NAT Host] and a laptop.
which was working as an "Internal Network" or LAN, during the test period.
The PC was connected to Cable modem and got its IP address via DHCP.
The laptop was running linux, and was configured to have static IP address.
It also ran Windoz (dual boot) so I could check windoz over NAT/Firewal.

Internet---CableModem--[Ethernet Hub]--eth0(3C509)[Firewall/NAT Host]
                                                     eth1 []  
                                                         |Cross over cable
                                                      eth0 []
                                                      (PCMCIA Ether Card)
                                                      My Laptop (Dell)

If you do not have the crossover cable, just use some Ethernet hub
and plug eth1 of Firewal/NAT and eth0 of laptop with straight through cables
as you would do normally (not to an uplink hub port). Make sure the LEDs on
the cards are glowing, since if your cables (or hub) are no good,
nothing will work. Repeat after me: Check your cables first...
You know how it is with cables... They work until you touch them. So check
your LEDs first to see if you do not have problems.

One more thing... I have put my slower (3C509) card on external eth0 interface.
My thinking was that I cannot get more juice from cable modem than 10 Mbits/s
while with a LAN, I may use additional bandwidth (e.g., remote printing,
file transfer, NFS, or access via MS shares, SAMBA, etc.).

The /sbin/ifconfig on my Firewall/NAT Host produced:
eth0      Link encap:Ethernet  HWaddr 00:20:AF:14:68:FD  
          inet addr:  Bcast:  Mask:
          RX packets:7177 errors:0 dropped:0 overruns:0 frame:0
          TX packets:77 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          Interrupt:10 Base address:0x300 

eth1      Link encap:Ethernet  HWaddr 00:03:6D:11:42:F9  
          inet addr:  Bcast:  Mask:
          RX packets:3142 errors:134 dropped:0 overruns:0 frame:147
          TX packets:100 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          Interrupt:11 Base address:0xe000 

lo        Link encap:Local Loopback  
          inet addr:  Mask:
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:22 errors:0 dropped:0 overruns:0 frame:0
          TX packets:22 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 


The /sbin/ifconfig on my laptop produced:

eth0      Link encap:Ethernet  HWaddr 00:10:A4:99:E1:5E  
          inet addr:  Bcast:  Mask:
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:2186 errors:0 dropped:0 overruns:0 frame:0
          TX packets:307 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          Interrupt:11 Base address:0x1800 

lo        Link encap:Local Loopback  
          inet addr:  Mask:
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:66 errors:0 dropped:0 overruns:0 frame:0
          TX packets:66 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 

Both the laptop and the Firewall/NAT were running RH7.1, but laptop
just had the stock RH7.1 installed. I could ssh from laptop to Firewall/NAT as
  ssh -l root
and from Firewall/NAT to laptop as:
  ssh -l root

On the laptop I was running X-window (KDE to be exact) and I started
tcpdump in one of the xterms as:

tcpdump -a -R -v -i all

It produced a lot of gibberish, but I could see that packets are flying
back and forth when I ssh. You can also monitor the packets conveniently
by using iptables/netfilter itself (it write the packet info to syslog --
check the startfw scripts for comments  -- it is available from the index page.

Now... knowing that laptop talks to Firewall/NAT host and vice versa
is a critical step. You may want to wait a few minutes after boot
before machines exchange ARP packets. You can also check if they
know about each another by executing arp on them:

   arp -a

The complication is also that at this moment I do not run the DNS for these
babies. To avoid DNS at this stage, I added the following to the /etc/hosts
on both machines
------------	firewall.test.domain	firewall	lan1.test.domain	lan1

If you are on Windoz, The HOSTS file should be located in C:\WINDOWS\HOSTS 

I am not sure if you need to reboot Windoz for new hosts to be recognized
in the host file. On Linux you do not need to reboot, AFAIK.

This way I could do 
  ping lan1
when on firewall and 
  ping firewall
when on lan1

I also check the connection with route
On the firewall machine:
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface     *        U     0      0        0 eth1   *        U     0      0        0 eth0       *            U     0      0        0 lo
default         UG    0      0        0 eth0

and on the lan1 machine:
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface     *        U     0      0        0 eth0       *            U     0      0        0 lo
default         firewall.test.d         UG    0      0        0 eth0

At the same time, I was checking if I can get to the Internet outside
by logging into one of the computers at my job.

I could ssh from firewall to outside. But, of course, could not log in to
outside machine from lan1.
ssh -l jkl
ssh Name or service not known

ssh -l jkl     (IP address of

sits there forever.

So, now is the time to learn and play with Netfilter.

Playing with Netfilter

Here is my brain process (assuming that I have a brain) which led to
some understanding of Netfilter.

You can list all netfilter modules by:
ls -l  /lib/modules/2.4.9/kernel/net/ipv4/netfilter

I have some description below. I use the word "firewall" as a shortcut
to "host which runs the netfilter". As you read on, the firewall does not
need to do any firewalling (e.g., can only do network address translation).

I read Rusty Russell's:  Linux 2.4 NAT HOWTO 
(Revision 1.15/2001/07/29), Linux netfilter Hacking HOWTO
(Revision:1.10 2001/05/04) and Linux 2.4 Packet Filtering HOWTO (Revision 1.21.
 2001/08/15) available at
and also many other pieces on the net. My conclusion is that there is
some naming confusion, at least for me. The so called historical reasons,
which keeps as chained to tables.

Picture below is based on the
by John Davidson (original site: does not
respond do me).

        ------------                   ------------        ------------
eth0-->| PREROUTING |   \           \ | FORWARD    |   \  | POSTROUTING|-->eth1
eth1-->|1) contrack |---->[route]---->|1) "filter" |----> |1) "nat" (S)|-->eth0
ppp0-->|2) "mangle" |   /    |      / |            |   /  |2) "nat" (M)|-->ppp0
lo? -->|3) "nat" (D)|        |        |            |  A   |3) contrack |--> lo?
        ------------         |        ------------   /|\   ------------
                             |                        |
                             |                        |
                             |                     [route]
                             |                        A
                            \|/                      /|\
                             V                        |
                       ------------             ------------
                      | INPUT      |           | OUTPUT     |
                      |1) "filter" |           |1) contrack |
                      |2) contrack |           |2) "mangle" |
                      |            |           |3) "nat"(D)*|
                       ------------            |4) "filter" | 
                             |                  ------------
                             |                        A
                             |                       /|\
                             |                        |
                            \|/                       |
                             V                        |
                          :     Local software            :
                          : telnet, RPC, NSF, FTP, ssh,   :
                          : HTTP, HTTPS, gopher, DNS, xfs :
                          : X-window, ping, chat, etc.,   : 

(D) -- destination. (S) -- source. (M) -- Masquerade.
1), 2)... order of application
Packet -- a chunk of data formatted according to one of the TCP/IP protocols

Interface -- a gate by which packets enter or exit the firewall machine. For
            example through 1st ethernet card (eth0), second ethernet
            card (eth1), 1st modem (ppp0 or slip0), and so on. The interface
            may be specified for the rule with a -i (--in-interface) or
            -o (--out-interface). You can also specify all interfaces of
            the given type by replacing the number with a "+" sign. For
            example -i eth+ means all packets which entered the firewall
            via ethernet card. You can also precede interface name with a !
            which means NOT. For example, -o ! eth0  means, packets which
            are not designated to exit via the eth0 interface.
Application software, or software -- software package other than the netfilter
            and kernel itself. When I say" "packets intended for software
            running on the firewall", I mean software like web server, or
            telnet, or whatever, but not netfilter and not the kernel itself,
            By definition, all packets go to netfilter and go via kernel.

Incoming packets -- packets which are coming to the firewall
Outgoing packets -- packets which are sent by the firewall outside
Forwarded packets -- packets which are not intended for the firewall itself,
      but routed from one interface to another.

Rule -- a sentence(clause) saying:

          PACKET TYPE                       ACTION
     if [packet is such and such] then [do this and that].

     For example: if packet destination is port 20, drop it.
     Examples of actions are: DENY, ACCEPT, DROP. There are also
     actions which result in changing the packet itself. This is probably not
     what the framers of Netfilter and other firewalls understand the term
     rule, but it helps me to see it like this.

Chain -- is an "operation room" inside the kernel where the
         rules are applied. These "operation rooms" are located in strategic
         points on the path of the packet inside the kernel. So why is it
         called a chain. Probably, because it is a "chain of rules", i.e.,
         chain of decisions is applied to the packet in the "operation room". 
         This is confusing, since you can define your own chains and attach
         them (branch to them) from the built-in chains. I think that naming
         is messed up here, since we should have the stuff presented as
         "decision points" and associated "chains of rules". But...
         The decisions may result in sending the packet elsewhere, in
         rejecting the packet, in dropping the packet, or in changing
         the packet. There are following built-in chains:  
     INPUT -- every packet which comes to the firewall and is designated
              for the firewall itself goes to this chain. You should try to
              do as much work as possible in the PREROUTING room (e.g.,
              dropped spoofed packets [packet claiming they came from
              internal network], malformed packets, etc, so the INPUT chain
              has less work to do. Moreover, if you do masquerading (DNAT),
              you should filter as much stuff as possible in the PREROUTING,
              or you would have to repeat the rules in the FORWARD chain.
              In INPUT, the packet can be either killed or sent to some
              application program running within the firewall (say, Web server
              or telnet server). Note that rules for INPUT chain cannot have
              -o (or --out-interface) since they do not go to any physical
              device. They can only have -i (--in-interface) specified. 

     OUTPUT -- every packet which is produced by the program running on the
               firewall itself and designated to go outside is entering this
               chain. From here it is either killed, or sent to POSTROUTING.
               Note that rules for the OUTPUT chain cannot have any
               -i (or --in-interface) since it does not come from the network
               device, but from the program running inside the firewall.

     PREROUTING -- every packet which comes to the firewall from outside
               goes first to this place before any other operations are made.
               The packet gets here before any routing decision is done.
               From this room, the packet can be sent to INPUT chain, or
               to the FORWARD chain, or killed.
     POSTROUTING -- every packet which is about to be sent out from the 
               firewall outside, comes to this chain. The packets which
               enter this chain, came either from the FORWARD chain, or
               from the OUTPUT chain. In here, the packet can be changed
               (or not) before being sent to the cloud, or killed.

     FORWARD -- Every packet which came to the firewall from outside on some
                interface, and is supposed to be send outside (on another or
                the same interface) comes to this room. The FORWARD chain
                is for packets which are not to be used by the application 
                software of the firewall itself, and were not created by the
                application software which runs on the firewall. Sometimes,
                decision may be to sent the packet out through the same
                interface it came from, but the key point is that the packet
                is not intended for the use of some program running on the
                firewall itself, and that the packet was not created from
                within the firewall. The rules for packets traversing
                FORWARD chain can have both -i (--in-interface) and 
                -o (--out-interface) specified.

     Note that in this topology packets coming to the firewall can traverse
     the following paths:
       outside --> PREROUTING --> FORWARD --> POSTROUTING --> outside
       outside --> PREROUTING --> INPUT --> internal program
       internal program --> OUTPUT --> POSTROUTING --> outside 

Built-in chains are locations in the path of processing packets. They
represent a collection of rules. The rules are applied to the packet in the
order in which they are placed in the chain. You can also define your own
chains (see examples section below) and jump to them from the current chain
in which packet is being processed. After you finished in your own chain,
the control comes back to the chain which called it just after the branching
rule (-j chain_name)..

Beside chains, there are "tables". Tables have names. They group the rules.
The rules in the table are executed as a group, but I am not sure about it
since I do not even think about looking up what actual code is doing..
See the diagram for the ordering in which the tables are executed in the
built-in chains (but I did not make this diagram, and I did not look in the
code). Table, as I see it, is a regime (a mode) under which the set of rules
is executed. Table is not just a collection of ordered elements which store 
rules, but rather a prescription how the rules of a given type should be
applied to the packet. A given rule (i.e., type of packet and action to take)
belongs only to one table. From this perspective, the table is just a type of
a rule and a prescription on how to deal with the rule. It is not just 
a placeholder for rules abut also an environment. You will not be able to
put some rules in some tables (e.g., "filter" table will not accept rules for
NAT, and "nat" table will not take the "-j REJECT", and, while I did not
test it, the packet mangling rules probably only work in the "mangle" table.
So you are putting rules to the table, but for a given chain (you can have
different rules in INPUT/filter table, and in OUTPUT/filter table).
Since chains have different roles and see different packets, they do not
have the same tables associated with them. So when you add your rule to
a chain, you actually add your rules to some table in this chain.
If you do not specify the table, the default is "filter". In two of
the decision rooms there is no filter table (POST and PREROUTING).
You have to specify the table in this case (usually -t nat)..
The same table in different chain has different rules but does a similar
thing. The built-in tables are associated with the chains. The same table
can be associated with more than one chain. Confused? Welcome to the club...
The tables are called tables probably for some historical reason.
I would call them modes, or regimes, or environments, or robots, or tracks
or manners or deportments. Below is the list of built-in tables:
   "filter"  -- table which collects rules which do not alter packets, but
                only filter them, i.e., either let them through, or stop
                them. The "filter" table is associated with FORWARD, INPUT,
                and OUTPUT chains. That is, every packet, either created
                inside the firewall or coming from outside goes through the
                "filter" table (i.e., rules of the filter table are applied
                to it). Note that the "filter" table is applied only once to
                the given packet, i.e., the packet can fall into the "decision
                room" where "filter" table is used only once on its travel
                through kernel. Look at the diagram. 

   "nat" --     table which changes the source or destination address/port and
                will alter where packets go. The "nat" table is applied
                in the PREROUTING and POSTROUTING chains. It can also be
                applied at the OUTPUT and INPUT chains if local NAT is 
                enabled. The "nat" table is special. When new connection
                is created, only the first packet traverses the table.
                The action resulting from this traversal is then applied to
                every packet in this connection. This is a place where SNAT
                (Source Network Address Translation), DNAT (Destination NAT),
                port forwarding, Masquerade, etc. are taking place. Note
                that "nat" table is applied in two places to each packet
                but the rules are different. In PREROUTING we do translation
                of destination address, i.e., we change the address/port of
                a packet which came from the outside (e.g., from address
                of a firewall to the address of the machine on local net).
                In the POSTROUTING we change the source address (e.g.,
                the packet going to the outside will carry the source
                address of the firewall, rather than the address of the 
                machine on the local LAN). Again, there are following NATs:
                DNAT -- destination address of the packet is modified. E.g.,
                    you have several web servers behind the firewall and you
                    want to spread the load. You can change the destination
                    IP address (which is the address of the firewall) of the
                    first SYN packet which wants to open the connection
                    to port 80 on the firewall to the address the webserver
                    which is behind the firewall. Then you want all
                    packets in the established TCP connection to go to this
                    machine until connection closes. 
                SNAT -- you have the internal network behind the firewall,
                    which you want to hide. Let us call it LAN. All
                    connections from LAN to the outside go via the firewall.
                    The firewall changes the source address in these packets 
                    (the address of host in the LAN) to its own address
                    (namely, the address it has on the interface facing
                    the outside network). This is a case of IP Masquerading.
                REDIRECT -- this is a specialized case of DNAT which changes
                    destination IP address of the packet intended for the
                    inside network to itself (like a reverse of DNAT described
                    above). It can be used, to redirect web traffic to a proxy
   "mangle" --  table which changes actual packet information, usually the
                flags in the packet header. It is used mostly to change TOS
                (type of service) flags to change packet priority for the 
                router. It is also used to mark packets as special so then
                one recognize them in other chains (decision rooms) and give
		them a special treatment. It is applied at PREROUTING and
                OUTPUT chain.

The contrack is not a table, it is a module which tracks the connection,
i.e., assigns them the property of NEW, ESTABLISHED, RELATED, or INVALID.
The NEW packet is the one which is trying to establish a new connection
(e.g., the SYN packed from client to server in TCP connection). The connection
is NEW until a reply to it has been seen by contrack (note that contrack is
also called in POSTROUTING). The ESTABLISHED packet is a part of established
connection. The reply to the TCP request for connection (ACK) is considered
as ESTABLISHED packet (though formally, it is not yet an established connection
according to the three-prone handshake). All packets but first are considered
ESTABLISHED until connection is closed. RELATED is a packed which is in some
way related to existing connection. For example, the packets which are
exchanged on the 2 ports of FTP protocol are considered related. To detect that
packets are related, you really need a special module which understands the
protocol. There are many different modules for chats, video services, 
server push, etc. You need to get them and load them before the packets
belonging to these application protocols are recognized as RELATED.
For example: the DNS response is related to DNS request even if this was done
over UDP (which is connectionless protocol and does not have SYN/ACK/FIN/RST
flags like TCP). Some ICMP packets are also RELATED if they result from
a previous request or report the error to the request. INVALID packet is
a packed which cannot be classified. This may be an attempt to spoof your
machine. DROP all INVALID packets.

You can create your own chains and then jump to them from your built-in
chains. Look up examples.

The table name in iptables command is given via -t option. If omitted, the
"filter" table is assumed.

I am not really even trying to give the overview of iptables command. Do:
   man iptables
and also read all example scripts. Then you will have known...

Netfilter Examples from various Sources
These examples are not in any order... Just when I found something, I added
it here.

Examples from: Iptables Basics NHF.

# Append the rule to INPUT chain to drop all packets coming from outside
#  on interface ppp0 and intended for the firewall's own telnet port
iptables -A INPUT -p tcp --destination-port telnet -p ppp0 -j DROP

# Append the rule to INPUT chain. It will drop packets coming from outside
# on interface eth0 and which want to start TCP connection with the firewall
iptables -A INPUT -o eth0 -p tcp --syn -j DROP 

# Append the rule to INPUT chain. Drop all packets coming from outside
# on interface eth0 which want to start TCP connection with the firewall
# except those address to port 80 (Web server).
iptables -A INPUT -o eth0 -p tcp --syn --destination-port ! 80 -j DROP

Examples: from Paul Russel, Networking Security with Linux 2.4

# limit log entries for packets coming from to firewall to 
# one per hour.
iptables -A INPUT -s -m limit -rate 1/hour -j LOG


# log packets which came from FORWARD chain from ether card source
# 00:60.08:91:CC:B7 
iptables -A FORWARD -m mac -mac-source 00:60.08:91:CC:B7 -j LOG


# append to FORWARD chain. Accept packets which are established or related
iptables -A FORWARD -m state -state ESTABLISHED, RELATED -j ACCEPT
   # append to FORWARD chain. DROP packets which are invalid
iptables -A FORWARD -m state -state INVALID -j DROP
   # if the 2 rules above were used, this rule will DROP all packets which
   # come from the external internet (ppp0) and try to establish NEW connection
   # this is a classic example of firewall which only allows connections to
   # be started from inside.
iptables -A FORWARD -i ppp0 -j DROP


# Example of using user-defined chains.
  # create new chain named INVALID-DROP
iptables -N INVALID-DROP  
  # limit logging rate to 5 per hour and record only to first 3. Use log prefix
iptables -A INVALID-DROP -m limit -rate 5/hour -limit-burst 3 -j LOG \
    -log-prefix "FW:invalid: "
  # after logging the packet, drop it
iptables -A INVALID-DROP -j DROP
  # define new chain called NEW-DROP
iptables -N NEW-DROP
  #limit logging and define prefix
iptables -A NEW-DROP -m limit -rate 5/hour -limit-burst 3 -j LOG \
    -log-prefix "FW:new: "
  #drop the new connection packet from outside
iptables -A NEW-DROP -j DROP
  # accept established connection packets
iptables -A FORWARD -m state -state ESTABLISHED,RELATED -j ACCEPT
  # forward the INVALID packets to INVALID-DROP chain
iptables -A FORWARD -m state -state INVALID -j INVALID-DROP
  # forward the NEW packets from the outside network (ppp0) to chain NEW-DROP
iptables -A FORWARD -i ppp0 -j NEW-DROP

Examples: from Linux Kernel 2.4 Firewalling Matures: netfilter

# reject packets which have either ALL flags set, or SYN and ACK flag set
iptables -A INPUT -p tcp --tcp-flags ALL SYN,ACK -j DROP

# block telnet, ftp, and finger on packets which come to firewall itself.
iptables -A INPUT -t DENY -p tcp --destport telnet,ftp,finger

# redirect traffic coming from internal LAN 192.168.1.* and intended for
# the web server at to a web server on machine
iptables -t nat -A POSTROUTING -s -d \
    -p tcp --dport 80 -j SNAT --to

# This will redirect traffic which comes to its eth0 interface (assuming it
# is the external interface to hosts,, 
iptables -t nat -A POSTROUTING -i eth0 -j DNAT --to

# log all packets which arrive to the IP address and put
# the prefix ## ROUTER ## in front of log lines.
iptables -A INPUT -s -j LOG --log-prefix '## ROUTER ##'

# log all ethernet packets which come from the MAC address 00:60:67:30:AC:E5
# and prefix them with ## My laptop ##.
iptables -I INPUT -m mac --mac-source 00:60:67:30:AC:E5 -j LOG \
      --log-prefix '## My laptop ##' 
Examples: from: Firewalling Using Netfilter

# script mylimit
# which shows nested user-defined chains. Note the use of RETURN jump
# which takes you to the next line after the rule which contained call
# to the user-defined chain (in this case lines which contain -j mylimit).
/usr/local/sbin/iptables -N mylimit
/usr/local/sbin/iptables -A mylimit -m limit --limit 2/s --limit-burst 10 \
     -j RETURN

/usr/local/sbin/iptables -A mylimit -m limit --limit 6/m -j LOG \
      --log-level info --log-prefix 'limitthwart '

/usr/local/sbin/iptables -A mylimit -j DROP
# set up a new chain to accept the good connections
# block incoming connections from ppp on ports other than desired
/usr/local/sbin/iptables -N myaccept
# Ping flood
/usr/local/sbin/iptables -A myaccept -p icmp --icmp-type echo-request \
   -j mylimit
# Syn-flood protection
/usr/local/sbin/iptables -A myaccept -p tcp --syn -j mylimit
# Furtive port scanner
/usr/local/sbin/iptables -A myaccept -p tcp --tcp-flags SYN,ACK,FIN,RST RST \
         -j mylimit

Example from
There are several examples which you can reach from the page:

   # Set all of the Policies on the filter table to accept
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -P OUTPUT ACCEPT
/sbin/iptables -P FORWARD ACCEPT
   # Flush all of the existing chains on the filter table
/sbin/iptables -F
   # Remove all of the user defined chains on the filter table
/sbin/iptables -X
   # Set all of the Policies on the nat table to accept
/sbin/iptables -t nat -P PREROUTING ACCEPT
/sbin/iptables -t nat -P OUTPUT ACCEPT
/sbin/iptables -t nat -P POSTROUTING ACCEPT
   # Flush all of the existing chains on the nat table
/sbin/iptables -t nat -F
   # Remove all of the user defined chains on the nat table
/sbin/iptables -t nat -X
   # Set all of the Policies on the mangle table to accept
/sbin/iptables -t mangle -P PREROUTING ACCEPT
/sbin/iptables -t mangle -P OUTPUT ACCEPT
   # Flush all of the existing chains on the mangle table
/sbin/iptables -t mangle -F
   # Remove all of the user defined chains on the mangle table
/sbin/iptables -t mangle -X
   # Not required:
   #       Stop forwarding and
   #       Remove all the iptables modules
echo 0 > /proc/sys/net/ipv4/ip_forward
/sbin/rmmod `lsmod | awk '{print $1}' | grep '^ip'`

Example from:

# list all tables
echo '                                   FILTER TABLE'
iptables -t filter -L -v --line-numbers
echo '                                   NAT TABLE'
iptables -t nat -L -v --line-numbers
echo '                                  MANGLE TABLE'

Example from:

   # Create a user defined chain
/sbin/iptables -N myaccept
   # If it is established or related, It's OK by me 
/sbin/iptables -A myaccept -m state --state ESTABLISHED,RELATED -j ACCEPT
   # If a connection attempt comes from localhost or eth0 It may pass the chain
/sbin/iptables -A myaccept -i ! ppp0 -m state --state NEW -j ACCEPT
   # If the connection comes from ppp0 log it.  With no more accepts after
   # this, it will be dropped
/sbin/iptables -A myaccept -i ppp0 -m state --state NEW,INVALID \
         -j LOG --log-level emerg --log-prefix 'newconthwart '
/sbin/iptables -A myaccept -j LOG --log-level emerg \
         --log-prefix 'idunnothwart '
Example from:

  # translate the incoming traffic for the webserver on the gateway
  # to the internal webserver
  # this one works on a dynamically assigned connection
/sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -i ppp0 \
    -j DNAT --to
  # translate the incoming traffic for the nameserver on the gateway to
  # the internal DNS server
  # this will work for statically assigned ip addresses (replace w.x.y.z)
/sbin/iptables -t nat -A PREROUTING -d w.x.y.z -p tcp --dport 53 \
     -i eth1 -j DNAT --to


Examples from Linux 2.4 Packet Filtering HOWTO By Rusty Russel.
# 5 DROPs packets which want to start connection from outside.
# Lets packets which were initiated from inside through. 
  # Insert connection-tracking modules (not needed if built into kernel).
insmod ip_conntrack
insmod ip_conntrack_ftp

  # Create chain which blocks new connections, except if coming from inside.
iptables -N block
iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A block -m state --state NEW -i ! ppp0 -j ACCEPT
iptables -A block -j DROP

  # Jump to that chain from INPUT and FORWARD chains.
iptables -A INPUT -j block
iptables -A FORWARD -j block

# 9 Mixing NAT and Packet Filtering

  # masquerade out ppp0 (packets which came from the LAN behind the firewall
  # will have their source addresses changed to the address of the
  #  ppp0 interface

 (so external word things it is firewall talking to it
  # directly)
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
  # Disallow NEW and INVALID incoming packets from ppp0 interface
iptables -A INPUT -i ppp0 -m state -- state NEW,INVALID -j DROP
  # Disallow NEW and INVALID incoming packets from ppp0 interface
iptables -A FORWARD -i ppp0 -m state -- state NEW,INVALID -j DROP
  #  Turn on the IP Forwarding
echo 1 > /proc/sys/net/ipvv4/ip_forward

# 11 Remove packets with your internal subnet addresses from coming from
  # outside
echo 1 > /proc/sys/net/ipv4/conf/ppp0/rp_filter

  # You can also do it for all interfaces:
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
  echo 1 > $f

# 11
  # Script where all connections which wanted to be initiated from
  # outside (ppp0) are junked

  # make a new chain no-conns-from-ppp0
iptables -N no-conns-from-ppp0

  # append the rule that packet which is ESTABLISHED or RELATED
  # should be accepted   
iptables -A no-conns-from-ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT

  # append the rule that allows new connections to be created from
  # interfaces other than ppp0 (packets starting connection locally are fine)
iptables -A no-conns-from-ppp0 -m state --state NEW -i ! ppp0 -j ACCEPT

  # since after the rules above only bad packet can be left, log them
iptables -A no-conns-from-ppp0 -i ppp0 -m limit -j LOG \
     --log-prefix "Bad packet from ppp0:"

  # if some bad packets are formed internally, log them
iptables -A no-conns-from-ppp0 -i ! ppp0 -m limit -j LOG \
     --log-prefix "Bad packet not from ppp0:"
  # DROP all packets which got to this point
iptables -A no-conns-from-ppp0 -j DROP

  # branch to no-conn-ppp0 from INPUT chain
iptables -A INPUT -j no-conns-from-ppp0

  # drop off all the packets which got that far.
iptables -A FORWARD -j no-conns-from-ppp0

Some examples which are to big to be included here:

From the index page were you got this page, you can get the:
   iptables-jkl -- a script which starts the iptables/netfilter on boot
           I put this script in the /etc/rc.d/init.d directory and do:
              cp .../iptables-jkl /etc/rc.d/init.d
              cd /etc/rc.d/init.d
              chmod 744 iptables-jkl
              chkconfig --add iptables-jkl
           so it starts the firewall/masquerading on boot

   startfw -- a LONG script which I use to set up firewall/masquerading 
            I put this script into /usr/sbin directory (if you want it
            elsewhere, you need to change iptables-jkl, since it expects it
            there. This loads all the necessary modules I use and sets the
            chains. You read the LONG comments there to see what it does.
            The startfw does not flush the chains on startup. To start with
            a clean slate, you need to use the flushfw script below.
            Remember about 
                   chmod 744 startfw
            after you copied it to /usr/sbin.

   flushfw -- flushes all the chains, deletes modules, and resets the kernel
            flags in /proc. It should reside in /usr/sbin (or if you want it
            elsewhere, change the iptables-jkl script, since it calls it).
            You need to use it before you run the startfw, or you will end up
            with messed up machine (you can always run it again, and then
            run startfw)..
            Remember about 
                   chmod 744 flushfw
            after you copied it to /usr/sbin.

   iplisting -- lists your chains and tables and tells you if the stuff is
            running. I keep it in /usr/sbin. Remember about 744 for it.

Assuming your firewall is up and running, you are ready to connect the local
network to the other site. I did few tests before this. I have a laptop
dual book with windows and linux on it. I had to modify my Linux and
Windows networking on them. They were configured originally to get their
IP addresses and nameserver info using DHCP client. Now, they will use
static addresses.

First, you will need some information for them which is on your firewall.
You need to see the file /etc/resolv.conf and see what is there. My has:
  cat /etc/resolv.conf


You will need the nameservers. 

If you have linux PC, and one card on it, it is easy:


and it displays you the questions, and you use your TAB key and arrow keys
to enter what it needs:
First, it asks you if you want to config the networking.You say yes.

Then the screen looked in my case like:

   [ ] Use dynamic IP configuration (BOOTP/DHCP)
       IP address:
       Netmask   :
       Default gateway IP:
       Primary Nameserver:

This stuff should end up in the file /etc/sysconfig/network-scripts/ifcfg-eth0
which in may case was:


Of course, you do not have to use netconfig GUI, you can enter the values
yourself, since this is what it does.

In the file /etc/resolv.conf should be your nameserver (i.e., addresses
of machines which change some hostname like to 
IP address like
In my case, there was only primary nameserver there,
so I added another one, and it looked like:

search test.domain

Then I rebooted the machine.

Of course you can play with things.
Assuming that you ran the combination of
on the firewall machine you can try pings outside on your laptop (local
network), For example:


and it worked for me.
I even looked at the OSU page with netscape:

So I tried a nasty stuff, Like ftp by using netscape with an URL

Worked... So I now tried using manual ftp in the xterm window:

Name: anonymous
Password: guest@guest

Worked in passive mode like charm.

Now, I wanted to start the Web server on the laptop and get to it through
the firewall.

On the laptop, I had the Apache installed with RH 7.1 distribution.

I started it by doing:
/etc/rc.d/init.d/httpd start
Then, I checked on the laptop if my Apache runs by giving an URL:


It gave me the test page.

I also tried the HTTPS
and it asked me for accepting certificate, and again showed the test page.

The httpd (Apache) was not running on the Firewall, which I checked by doing
ps -ef | grep httpd

Now, I wanted to fool the world that my web server is actually running on
the firewall machine, but I wanted to use Destination NAT and forward HTTP
and HTTPS request to the laptop.

I did the following:

1) Logged in to firewall as root

2) logged in  stopped my running "production" firewall:

3) Wrote a small script, chmoded it to 755 and ran it:


/sbin/modprobe ip_tables
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_unclean
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_REJECT
/sbin/modprobe ipt_MASQUERADE

iptables -A PREROUTING -t nat -p tcp -i eth0 --dport 80 -j DNAT \
iptables -A PREROUTING -t nat -p tcp -i eth0 --dport 443 -j DNAT \

4) I ran the hostname on the firewall to learn what is my actual name.
   It was at the time:
   (you need a fully qualified name)

5) I learned that its IP address assigned by DHCP:
   It was:
   (You can also get this by running:

6) I logged in from firewall to my office machines using ssh) and 
   I fired lynx (a text web browser --  you do not want netscape,
   since it will take a year to pass these pixels back to your firewall 
   machine) using the firewall machine name:


   You remember, that there is no Apache running on firewall, but one is
   running on laptop. Worked like charm. The tcpdump on the laptop was
   showing tons of packet with right ports going back and forth.
   This was the magic of Destination NAT.

7) Then I killed the  server on the laptop, and when I wanted to reach it
   again, it said: "No way, Jose". 

8) Then I restarted the "production" netfilter script on the firewall machine:
      /etc/rc.d/init.d/iptables-jkl restart

Configuring Windows to work behind the firewall

Double Clicked on "My computer"
Double Clicked on "Control Panel"
Double clicked on "Network"
Clicked on "Configuration Tab"
Clicked on TCP/IP -> Whatever-Ether-Card-You-Have-At-The-Bottom 
Clicked on "Properties"
Clicked on "IP address" Tab
   Chose "Specify and IP address"

        IP Address:
        Subnet Mask:

Clicked on "DNS Configuration" Tab
    Chose: "Enable DNS"
    Host: lan5
    Domain: test.domain
    DNS Server Search Order    Add    Add

Clicked on "Gateway" Tab       Add

Then clicked OK and OK and OK and it rebooted the PC

Then, Start->Run->winipcfg 
and chosen the Ether Card (It will often show PPP, if you also have a modem).

For the time being, this is it. I plan to install proxy server, squid,
Web server, dns server, and whatever on the firewall machine.
in my case, it is just my home PC, and I only have a single IP address,
so it more like giving me a way to have many computers at home with one
IP address on the exit, rather than the BIG SECURITY of my network.
But of course, if you are security conscious, you should make a DMZ setup,
and you will need 3 ether cards in your PC. Search for
DMZ iptables
and you will learn things.

Modified: Sat Nov 24 22:15:37 2001 GMT
Page accessed 11854 times since Tue Dec 11 21:34:19 2001 GMT