Committed by Jan K. Labanowski (jkl@ccl.net) 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: http://www.linuxguruz.org/iptables/ The Netfilter site: The Netfilter Project: Packet Mangling for Linux 2.4 http://netfilter.filewatcher.org/ Linux 2.4 Packet Filtering HOWTO by Rusty Russel. http://netfilter.samba.org/unreliable-guides/packet-filtering-HOWTO/packet-filtering-HOWTO.linuxdoc.html Linux Gets Stateful Firewalling: http://www.securityportal.com/cover/coverstory20010122.html by Jay Beale, Explains in a simple way the operation of the stateful firewall Using Linux 2.4 Firewalling - Building a Firewall with Netfilter http://securityportal.com/articles/netfilter20010219.html by Jay Beale, Explains how to use Netfilter iptables Tutorial 1.0.7 http://people.unix-fu.org/andreasson/index.html by Oskar Andreasson Common threads -- Dynamic iptables firewalls http://www-106.ibm.com/developerworks/linux/library/l-fw/ by Daniel Robbins James C. Stephens: Connection Tracking http://www.kalamazoolinux.org/presentations/20010417/conntrack.html Firewalling and Netfilter Terms http://www.kalamazoolinux.org/presentations/20010417/terms.html The quick guide to iptables (syntax only): http://www.kalamazoolinux.org/presentations/20010417/quick 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 fdisk p q 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 directory. 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: id:3:initdefault: (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 startx and configured my network interfaces by using: netcfg I clicked on Interfaces and as a result I had the following table: Interface IP proto atboot active lo 127.0.0.1 none yes active eth0 dhcp yes active eth1 192.168.0.1 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: /etc/sysconfig/network --------------- NETWORKING=yes HOSTNAME=localhost.localdomain GATEWAYDEV= GATEWAY= ---------------- /etc/sysconfig/network-scripts/ifcfg-eth0 ------------ DEVICE=eth0 ONBOOT=yes BOOTPROTO=dhcp --------------------- and /etc/sysconfig/network-scripts/ifcfg-eth1 ----------- DEVICE=eth1 USERCTL=no ONBOOT=yes BOOTPROTO=none BROADCAST=192.168.0.255 NETWORK=192.168.0.0 NETMASK=255.255.255.0 IPADDR=192.168.0.1 ---------- 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: http://www.linuxdoc.org/HOWTO/Kernel-HOWTO.html 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 kernel.org using wget (but you can start from http://www.kernel.org). wget ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-2.4.9.tar.gz 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 http://netfilter.samba.org/ cd /root wget http://netfilter.samba.org/iptables-1.2.2.tar.bz2 It is bzipped tar. Check if you have bunzip2 installed: bunzip2 If it tells you: "command not found", find it on your RH CDs or retrieve it from the net, e.g. wget ftp://rpmfind.net/linux/redhat/7.1/en/os/i386/RedHat/RPMS/bzip2-1.0.1-3.i386.rpm 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 /usr/src/linux-2.4/.config 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 ^D (i.e., made empty file pvr2fb.c) since I will not be using this video card anyhow. 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 System.map 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/System.map System.map-2.4.9-1 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 System.map-2.4.9-1 System.map 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: -------------------- boot=/dev/hda map=/boot/map install=/boot/boot.b prompt timeout=50 message=/boot/message linear default=linux-2.4.9-1 image=/boot/vmlinuz-2.4.9-1 label=linux-2.4.9-1 read-only root=/dev/hda4 image=/boot/vmlinuz-2.4.2-2 label=linux-2.4.2-2 read-only root=/dev/hda4 -------------------------- 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 shows: ipchains 0:off 1:off 2:off 3:off 4:off 5:off 6:off rpm -q -a | grep iptables iptables-1.2.1a-1 rpm -e iptables-1.2.1a-1 As was described above, the new 1.2.2 version of iptables is already in: /root/iptables-1.2.2 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] (Tulip) eth1 [192.168.0.1] | | | | -------- | | Ether | uplink | | Hub |----------------- | | | |---------------------- | | | | |----------- | | | | | | |----- | | | | | | | | | | | | | | | | | | | | | | -------- | | | | | | | | | -------------- | ------ | | | | | | 192.168.0.5 192.168.0.3 192.168.0.4 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. DHCP Internet---CableModem--[Ethernet Hub]--eth0(3C509)[Firewall/NAT Host] (Tulip) eth1 [192.168.0.1] | |Cross over cable | eth0 [192.168.0.5] (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:204.210.237.7 Bcast:255.255.255.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 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:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 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:127.0.0.1 Mask:255.0.0.0 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:192.168.0.5 Bcast:192.168.0.255 Mask:255.255.255.0 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:127.0.0.1 Mask:255.0.0.0 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 192.168.0.1 and from Firewall/NAT to laptop as: ssh -l root 192.168.0.5 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 ------------ 192.168.0.1 firewall.test.domain firewall 192.168.0.5 lan1.test.domain lan1 ----------- If you are on Windoz, The HOSTS file should be located in C:\WINDOWS\HOSTS (or in C:\WINNT\SYSTEM32\DRIVERS\ETC\HOSTS on Windows NT). 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: route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.0.0 * 255.255.255.0 U 0 0 0 eth1 204.210.237.0 * 255.255.255.0 U 0 0 0 eth0 127.0.0.0 * 255.0.0.0 U 0 0 0 lo default 204.210.237.1 0.0.0.0 UG 0 0 0 eth0 and on the lan1 machine: route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.0.0 * 255.255.255.0 U 0 0 0 eth0 127.0.0.0 * 255.0.0.0 U 0 0 0 lo default firewall.test.d 0.0.0.0 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 www.ccl.net ssh www.ccl.net: Name or service not known and ssh -l jkl 192.153.40.39 (IP address of www.ccl.net) 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 http://netfilter.filewatcher.org/unreliable-guides/ 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 http://www.knowplace.org/netfilter/ipt_flow_mirror.html or http://www.kalamazoolinux.org/presentations/20010417/iptflow.html by John Davidson (original site: http://ods.dyndns.org/ipt_flow.html 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 Definitions: 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 server. "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. from: http://www.linuxnewbie.org/nhf/intel/security/iptables_basics.html # 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 from: http://www.linux-mag.com/2000-01/bestdefense_01.html # limit log entries for packets coming from 192.168.0.1 to firewall to # one per hour. iptables -A INPUT -s 192.168.0.1 -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 from: http://www.linuxsecurity.com/feature_stories/kernel-netfilter.html # 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 192.168.1.1 to a web server on machine 192.168.1.100 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 192.168.1.1 \ -p tcp --dport 80 -j SNAT --to 192.168.1.100 # This will redirect traffic which comes to its eth0 interface (assuming it # is the external interface to hosts 192.168.1.10, 192.168.1.11, 192.168.1.12. iptables -t nat -A POSTROUTING -i eth0 -j DNAT --to 192.168.1.10-192.168.1.12. # log all packets which arrive to the IP address 192.168.1.1 and put # the prefix ## ROUTER ## in front of log lines. iptables -A INPUT -s 192.168.1.1 -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 http://www.kalamazoolinux.org/presentations/20010417/ # script mylimit http://www.kalamazoolinux.org/presentations/20010417/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 http://www.kalamazoolinux.org/presentations/20010417/flush There are several examples which you can reach from the page: http://www.kalamazoolinux.org/presentations/20010417/myrecommend.html # 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: http://www.kalamazoolinux.org/presentations/20010417/list # list all tables echo echo ' FILTER TABLE' echo iptables -t filter -L -v --line-numbers echo echo ' NAT TABLE' echo iptables -t nat -L -v --line-numbers echo echo ' MANGLE TABLE' echo =================== Example from: http://www.kalamazoolinux.org/presentations/20010417/conn # 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: http://www.kalamazoolinux.org/presentations/20010417/wwwdomain # translate the incoming traffic for the webserver on the gateway # to the internal webserver 192.168.0.1 # this one works on a dynamically assigned connection /sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -i ppp0 \ -j DNAT --to 192.168.0.1:80 # translate the incoming traffic for the nameserver on the gateway to # the internal DNS server 192.168.0.6:53 # 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 192.168.0.6:53 ------------------- Examples from Linux 2.4 Packet Filtering HOWTO By Rusty Russel. http://netfilter.samba.org/unreliable-guides/packet-filtering-HOWTO/packet-filtering-HOWTO.linuxdoc.html # 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 done ------------------------ # 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: http://www.kalamazoolinux.org/presentations/20010417/myfinal http://www.cs.princeton.edu/~jns/security/iptables/index.html http://people.unix-fu.org:8080/andreasson/rc.firewall.txt http://www-106.ibm.com/developerworks/linux/library/l-fw/dynfw-1.0.tar.gz ======================================================= 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 search columbus.rr.com rr.com nameserver 65.24.0.166 nameserver 65.24.0.167 You will need the nameservers. If you have linux PC, and one card on it, it is easy: netconfig 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: 192.168.0.5 Netmask : 255.255.255.0 Default gateway IP: 192.168.0.1 Primary Nameserver: 65.24.0.166 This stuff should end up in the file /etc/sysconfig/network-scripts/ifcfg-eth0 which in may case was: DEVICE=eth0 INBOOT=tes BOOTPROTO=static IPADDR=192.168.0.5 NETMASK=255.255.255.0 GATEWAY=192.168.0.1 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 www.something.big.com to IP address like 196.132.251.5). In my case, there was only primary nameserver there, 65.24.0.166 so I added another one, and it looked like: search test.domain nameserver 65.24.0.166 nameserver 65.24.0.167 Then I rebooted the machine. Testing ============ Of course you can play with things. Assuming that you ran the combination of /usr/sbin/flushfw /usr/sbin/startfw on the firewall machine you can try pings outside on your laptop (local network), For example: ping www.ccl.net and it worked for me. I even looked at the OSU page with netscape: http://www.ccl.net So I tried a nasty stuff, Like ftp by using netscape with an URL ftp://ftp.ccl.net Worked... So I now tried using manual ftp in the xterm window: ftp ftp.ccl.net 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: http://localhost:80/ It gave me the test page. I also tried the HTTPS http://localhost:443/ 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: /usr/sbin/flushfw 3) Wrote a small script, chmoded it to 755 and ran it: #!/bin/bash /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 \ --to 192.168.0.5:80 iptables -A PREROUTING -t nat -p tcp -i eth0 --dport 443 -j DNAT \ --to 192.168.0.5:443 4) I ran the hostname on the firewall to learn what is my actual name. It was at the time: dhcp237007.columbus.rr.com (you need a fully qualified name) 5) I learned that its IP address assigned by DHCP: nslookup dhcp237007.columbus.rr.com It was: 204.210.237.7 (You can also get this by running: /sbin/ifconfig ) 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: lynx http://dhcp237007.columbus.rr.com lynx https://dhcp237007.columbus.rr.com 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: 192.168.0.5 Subnet Mask: 255.255.255.0 Clicked on "DNS Configuration" Tab Chose: "Enable DNS" Host: lan5 Domain: test.domain DNS Server Search Order 65.24.0.166 Add 65.24.0.167 Add Clicked on "Gateway" Tab 192.168.0.1 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. While the firewall machine SHOULD NOT HAVE UNNECESSARY SERVICES RUNNING ON IT, 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 www.google.com for DMZ iptables and you will learn things.