2012年2月15日 星期三

Building External Modules : /Documentation/kbuild/modules.txt

In this document you will find information about:
- how to build external modules
- how to make your module use the kbuild infrastructure
- how kbuild will install a kernel
- how to install modules in a non-standard location

=== Table of Contents

        === 1 Introduction
        === 2 How to build external modules
           --- 2.1 Building external modules
           --- 2.2 Available targets
           --- 2.3 Available options
           --- 2.4 Preparing the kernel tree for module build
           --- 2.5 Building separate files for a module
        === 3. Example commands
        === 4. Creating a kbuild file for an external module
        === 5. Include files
           --- 5.1 How to include files from the kernel include dir
           --- 5.2 External modules using an include/ dir
           --- 5.3 External modules using several directories
        === 6. Module installation
           --- 6.1 INSTALL_MOD_PATH
           --- 6.2 INSTALL_MOD_DIR
        === 7. Module versioning & Module.symvers
           --- 7.1 Symbols from the kernel (vmlinux + modules)
           --- 7.2 Symbols and external modules
           --- 7.3 Symbols from another external module
        === 8. Tips & Tricks
           --- 8.1 Testing for CONFIG_FOO_BAR



=== 1. Introduction

kbuild includes functionality for building modules both
within the kernel source tree and outside the kernel source tree.
The latter is usually referred to as external or "out-of-tree"
modules and is used both during development and for modules that
are not planned to be included in the kernel tree.

What is covered within this file is mainly information to authors
of modules. The author of an external module should supply
a makefile that hides most of the complexity, so one only has to type
'make' to build the module. A complete example will be presented in
chapter 4, "Creating a kbuild file for an external module".


=== 2. How to build external modules

kbuild offers functionality to build external modules, with the
prerequisite that there is a pre-built kernel available with full source.
A subset of the targets available when building the kernel is available
when building an external module.

--- 2.1 Building external modules

        Use the following command to build an external module:

                make -C M=`pwd`

        For the running kernel use:

                make -C /lib/modules/`uname -r`/build M=`pwd`

        For the above command to succeed, the kernel must have been
        built with modules enabled.

        To install the modules that were just built:

                make -C M=`pwd` modules_install

        More complex examples will be shown later, the above should
        be enough to get you started.

--- 2.2 Available targets

        $KDIR refers to the path to the kernel source top-level directory

        make -C $KDIR M=`pwd`
                Will build the module(s) located in current directory.
                All output files will be located in the same directory
                as the module source.
                No attempts are made to update the kernel source, and it is
                a precondition that a successful make has been executed
                for the kernel.

        make -C $KDIR M=`pwd` modules
                The modules target is implied when no target is given.
                Same functionality as if no target was specified.
                See description above.

        make -C $KDIR M=`pwd` modules_install
                Install the external module(s).
                Installation default is in /lib/modules//extra,
                but may be prefixed with INSTALL_MOD_PATH - see separate
                chapter.

        make -C $KDIR M=`pwd` clean
                Remove all generated files for the module - the kernel
                source directory is not modified.

        make -C $KDIR M=`pwd` help
                help will list the available target when building external
                modules.

--- 2.3 Available options:

        $KDIR refers to the path to the kernel source top-level directory

        make -C $KDIR
                Used to specify where to find the kernel source.
                '$KDIR' represent the directory where the kernel source is.
                Make will actually change directory to the specified directory
                when executed but change back when finished.

        make -C $KDIR M=`pwd`
                M= is used to tell kbuild that an external module is
                being built.
                The option given to M= is the directory where the external
                module (kbuild file) is located.
                When an external module is being built only a subset of the
                usual targets are available.

        make -C $KDIR SUBDIRS=`pwd`
                Same as M=. The SUBDIRS= syntax is kept for backwards
                compatibility.

--- 2.4 Preparing the kernel tree for module build

        To make sure the kernel contains the information required to
        build external modules the target 'modules_prepare' must be used.
        'modules_prepare' exists solely as a simple way to prepare
        a kernel source tree for building external modules.
        Note: modules_prepare will not build Module.symvers even if
        CONFIG_MODVERSIONS is set. Therefore a full kernel build
        needs to be executed to make module versioning work.

--- 2.5 Building separate files for a module
        It is possible to build single files which are part of a module.
        This works equally well for the kernel, a module and even for
        external modules.
        Examples (module foo.ko, consist of bar.o, baz.o):
                make -C $KDIR M=`pwd` bar.lst
                make -C $KDIR M=`pwd` bar.o
                make -C $KDIR M=`pwd` foo.ko
                make -C $KDIR M=`pwd` /


=== 3. Example commands

This example shows the actual commands to be executed when building
an external module for the currently running kernel.
In the example below, the distribution is supposed to use the
facility to locate output files for a kernel compile in a different
directory than the kernel source - but the examples will also work
when the source and the output files are mixed in the same directory.

# Kernel source
/lib/modules//source -> /usr/src/linux-

# Output from kernel compile
/lib/modules//build -> /usr/src/linux--up

Change to the directory where the kbuild file is located and execute
the following commands to build the module:

        cd /home/user/src/module
        make -C /usr/src/`uname -r`/source            \
                O=/lib/modules/`uname-r`/build        \
                M=`pwd`

Then, to install the module use the following command:

        make -C /usr/src/`uname -r`/source            \
                O=/lib/modules/`uname-r`/build        \
                M=`pwd`                               \
                modules_install

If you look closely you will see that this is the same command as
listed before - with the directories spelled out.

The above are rather long commands, and the following chapter
lists a few tricks to make it all easier.


=== 4. Creating a kbuild file for an external module

kbuild is the build system for the kernel, and external modules
must use kbuild to stay compatible with changes in the build system
and to pick up the right flags to gcc etc.

The kbuild file used as input shall follow the syntax described
in Documentation/kbuild/makefiles.txt. This chapter will introduce a few
more tricks to be used when dealing with external modules.

In the following a Makefile will be created for a module with the
following files:
        8123_if.c
        8123_if.h
        8123_pci.c
        8123_bin.o_shipped      <= Binary blob

--- 4.1 Shared Makefile for module and kernel

        An external module always includes a wrapper Makefile supporting
        building the module using 'make' with no arguments.
        The Makefile provided will most likely include additional
        functionality such as test targets etc. and this part shall
        be filtered away from kbuild since it may impact kbuild if
        name clashes occurs.

        Example 1:
                --> filename: Makefile
                ifneq ($(KERNELRELEASE),)
                # kbuild part of makefile
                obj-m  := 8123.o
                8123-y := 8123_if.o 8123_pci.o 8123_bin.o

                else
                # Normal Makefile

                KERNELDIR := /lib/modules/`uname -r`/build
                all::
                        $(MAKE) -C $(KERNELDIR) M=`pwd` $@

                # Module specific targets
                genbin:
                        echo "X" > 8123_bin.o_shipped

                endif

        In example 1, the check for KERNELRELEASE is used to separate
        the two parts of the Makefile. kbuild will only see the two
        assignments whereas make will see everything except the two
        kbuild assignments.

        In recent versions of the kernel, kbuild will look for a file named
        Kbuild and as second option look for a file named Makefile.
        Utilising the Kbuild file makes us split up the Makefile in example 1
        into two files as shown in example 2:

        Example 2:
                --> filename: Kbuild
                obj-m  := 8123.o
                8123-y := 8123_if.o 8123_pci.o 8123_bin.o

                --> filename: Makefile
                KERNELDIR := /lib/modules/`uname -r`/build
                all::
                        $(MAKE) -C $(KERNELDIR) M=`pwd` $@

                # Module specific targets
                genbin:
                        echo "X" > 8123_bin.o_shipped


        In example 2, we are down to two fairly simple files and for simple
        files as used in this example the split is questionable. But some
        external modules use Makefiles of several hundred lines and here it
        really pays off to separate the kbuild part from the rest.
        Example 3 shows a backward compatible version.

        Example 3:
                --> filename: Kbuild
                obj-m  := 8123.o
                8123-y := 8123_if.o 8123_pci.o 8123_bin.o

                --> filename: Makefile
                ifneq ($(KERNELRELEASE),)
                include Kbuild
                else
                # Normal Makefile

                KERNELDIR := /lib/modules/`uname -r`/build
                all::
                        $(MAKE) -C $(KERNELDIR) M=`pwd` $@

                # Module specific targets
                genbin:
                        echo "X" > 8123_bin.o_shipped

                endif

        The trick here is to include the Kbuild file from Makefile, so
        if an older version of kbuild picks up the Makefile, the Kbuild
        file will be included.

--- 4.2 Binary blobs included in a module

        Some external modules needs to include a .o as a blob. kbuild
        has support for this, but requires the blob file to be named
        _shipped. In our example the blob is named
        8123_bin.o_shipped and when the kbuild rules kick in the file
        8123_bin.o is created as a simple copy off the 8213_bin.o_shipped file
        with the _shipped part stripped of the filename.
        This allows the 8123_bin.o filename to be used in the assignment to
        the module.

        Example 4:
                obj-m  := 8123.o
                8123-y := 8123_if.o 8123_pci.o 8123_bin.o

        In example 4, there is no distinction between the ordinary .c/.h files
        and the binary file. But kbuild will pick up different rules to create
        the .o file.


=== 5. Include files

Include files are a necessity when a .c file uses something from other .c
files (not strictly in the sense of C, but if good programming practice is
used). Any module that consists of more than one .c file will have a .h file
for one of the .c files.

- If the .h file only describes a module internal interface, then the .h file
  shall be placed in the same directory as the .c files.
- If the .h files describe an interface used by other parts of the kernel
  located in different directories, the .h files shall be located in
  include/linux/ or other include/ directories as appropriate.

One exception for this rule is larger subsystems that have their own directory
under include/ such as include/scsi. Another exception is arch-specific
.h files which are located under include/asm-$(ARCH)/*.

External modules have a tendency to locate include files in a separate include/
directory and therefore need to deal with this in their kbuild file.

--- 5.1 How to include files from the kernel include dir

        When a module needs to include a file from include/linux/, then one
        just uses:

                #include

        kbuild will make sure to add options to gcc so the relevant
        directories are searched.
        Likewise for .h files placed in the same directory as the .c file.

                #include "8123_if.h"

        will do the job.

--- 5.2 External modules using an include/ dir

        External modules often locate their .h files in a separate include/
        directory although this is not usual kernel style. When an external
        module uses an include/ dir then kbuild needs to be told so.
        The trick here is to use either EXTRA_CFLAGS (take effect for all .c
        files) or CFLAGS_$F.o (take effect only for a single file).

        In our example, if we move 8123_if.h to a subdirectory named include/
        the resulting Kbuild file would look like:

                --> filename: Kbuild
                obj-m  := 8123.o

                EXTRA_CFLAGS := -Iinclude
                8123-y := 8123_if.o 8123_pci.o 8123_bin.o

        Note that in the assignment there is no space between -I and the path.
        This is a kbuild limitation:  there must be no space present.

--- 5.3 External modules using several directories

        If an external module does not follow the usual kernel style, but
        decides to spread files over several directories, then kbuild can
        handle this too.

        Consider the following example:

        |
        +- src/complex_main.c
        |   +- hal/hardwareif.c
        |   +- hal/include/hardwareif.h
        +- include/complex.h

        To build a single module named complex.ko, we then need the following
        kbuild file:

        Kbuild:
                obj-m := complex.o
                complex-y := src/complex_main.o
                complex-y += src/hal/hardwareif.o

                EXTRA_CFLAGS := -I$(src)/include
                EXTRA_CFLAGS += -I$(src)src/hal/include


        kbuild knows how to handle .o files located in another directory -
        although this is NOT recommended practice. The syntax is to specify
        the directory relative to the directory where the Kbuild file is
        located.

        To find the .h files, we have to explicitly tell kbuild where to look
        for the .h files. When kbuild executes, the current directory is always
        the root of the kernel tree (argument to -C) and therefore we have to
        tell kbuild how to find the .h files using absolute paths.
        $(src) will specify the absolute path to the directory where the
        Kbuild file are located when being build as an external module.
        Therefore -I$(src)/ is used to point out the directory of the Kbuild
        file and any additional path are just appended.

=== 6. Module installation

Modules which are included in the kernel are installed in the directory:

        /lib/modules/$(KERNELRELEASE)/kernel

External modules are installed in the directory:

        /lib/modules/$(KERNELRELEASE)/extra

--- 6.1 INSTALL_MOD_PATH

        Above are the default directories, but as always, some level of
        customization is possible. One can prefix the path using the variable
        INSTALL_MOD_PATH:

                $ make INSTALL_MOD_PATH=/frodo modules_install
                => Install dir: /frodo/lib/modules/$(KERNELRELEASE)/kernel

        INSTALL_MOD_PATH may be set as an ordinary shell variable or as in the
        example above, can be specified on the command line when calling make.
        INSTALL_MOD_PATH has effect both when installing modules included in
        the kernel as well as when installing external modules.

--- 6.2 INSTALL_MOD_DIR

        When installing external modules they are by default installed to a
        directory under /lib/modules/$(KERNELRELEASE)/extra, but one may wish
        to locate modules for a specific functionality in a separate
        directory. For this purpose, one can use INSTALL_MOD_DIR to specify an
        alternative name to 'extra'.

                $ make INSTALL_MOD_DIR=gandalf -C KERNELDIR \
                        M=`pwd` modules_install
                => Install dir: /lib/modules/$(KERNELRELEASE)/gandalf


=== 7. Module versioning & Module.symvers

Module versioning is enabled by the CONFIG_MODVERSIONS tag.

Module versioning is used as a simple ABI consistency check. The Module
versioning creates a CRC value of the full prototype for an exported symbol and
when a module is loaded/used then the CRC values contained in the kernel are
compared with similar values in the module. If they are not equal, then the
kernel refuses to load the module.

Module.symvers contains a list of all exported symbols from a kernel build.

--- 7.1 Symbols from the kernel (vmlinux + modules)

        During a kernel build, a file named Module.symvers will be generated.
        Module.symvers contains all exported symbols from the kernel and
        compiled modules. For each symbols, the corresponding CRC value
        is stored too.

        The syntax of the Module.symvers file is:
                               
        Sample:
                0x2d036834  scsi_remove_host   drivers/scsi/scsi_mod

        For a kernel build without CONFIG_MODVERSIONS enabled, the crc
        would read: 0x00000000

        Module.symvers serves two purposes:
        1) It lists all exported symbols both from vmlinux and all modules
        2) It lists the CRC if CONFIG_MODVERSIONS is enabled

--- 7.2 Symbols and external modules

        When building an external module, the build system needs access to
        the symbols from the kernel to check if all external symbols are
        defined. This is done in the MODPOST step and to obtain all
        symbols, modpost reads Module.symvers from the kernel.
        If a Module.symvers file is present in the directory where
        the external module is being built, this file will be read too.
        During the MODPOST step, a new Module.symvers file will be written
        containing all exported symbols that were not defined in the kernel.

--- 7.3 Symbols from another external module

        Sometimes, an external module uses exported symbols from another
        external module. Kbuild needs to have full knowledge on all symbols
        to avoid spitting out warnings about undefined symbols.
        Three solutions exist to let kbuild know all symbols of more than
        one external module.
        The method with a top-level kbuild file is recommended but may be
        impractical in certain situations.

        Use a top-level Kbuild file
                If you have two modules: 'foo' and 'bar', and 'foo' needs
                symbols from 'bar', then one can use a common top-level kbuild
                file so both modules are compiled in same build.

                Consider following directory layout:
                ./foo/ <= contains the foo module
                ./bar/ <= contains the bar module
                The top-level Kbuild file would then look like:

                #./Kbuild: (this file may also be named Makefile)
                        obj-y := foo/ bar/

                Executing:
                        make -C $KDIR M=`pwd`

                will then do the expected and compile both modules with full
                knowledge on symbols from both modules.

        Use an extra Module.symvers file
                When an external module is built, a Module.symvers file is
                generated containing all exported symbols which are not
                defined in the kernel.
                To get access to symbols from module 'bar', one can copy the
                Module.symvers file from the compilation of the 'bar' module
                to the directory where the 'foo' module is built.
                During the module build, kbuild will read the Module.symvers
                file in the directory of the external module and when the
                build is finished, a new Module.symvers file is created
                containing the sum of all symbols defined and not part of the
                kernel.

        Use make variable KBUILD_EXTRA_SYMBOLS in the Makefile
                If it is impractical to copy Module.symvers from another
                module, you can assign a space separated list of files to
                KBUILD_EXTRA_SYMBOLS in your Makfile. These files will be
                loaded by modpost during the initialisation of its symbol
                tables.

=== 8. Tips & Tricks

--- 8.1 Testing for CONFIG_FOO_BAR

        Modules often need to check for certain CONFIG_ options to decide if
        a specific feature shall be included in the module. When kbuild is used
        this is done by referencing the CONFIG_ variable directly.

                #fs/ext2/Makefile
                obj-$(CONFIG_EXT2_FS) += ext2.o

                ext2-y := balloc.o bitmap.o dir.o
                ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o

        External modules have traditionally used grep to check for specific
        CONFIG_ settings directly in .config. This usage is broken.
        As introduced before, external modules shall use kbuild when building
        and therefore can use the same methods as in-kernel modules when
        testing for CONFIG_ definitions.

不錯的iptables 文章

iptables官方網站:http://netfilter.org/

數據包經過防火牆的路徑

圖1比較完整地展示了一個數據包是如何經過防火牆的,考慮到節省空間,該圖實際上包了三種情況:
來自外部,以防火牆(本機)為目的地的包,在圖1中自上至下走左邊一條路徑。
由防火牆(本機)產生的包,在圖1中從“本地進程”開始,自上至下走左邊一條路徑
來自外部,目的地是其它主機的包,在圖1中自上至下走右邊一條路徑。

圖1
如果我們從上圖中略去比較少用的mangle表的圖示,就有圖2所顯示的更為清晰的路徑圖.

圖2

禁止端口的實例

  • 禁止ssh端口

只允許在192.168.62.1上使用ssh遠程登錄,從其它計算機上禁止使用ssh
#iptables -A INPUT -s 192.168.62.1 -p tcp --dport 22 -j ACCEPT
#iptables -A INPUT -p tcp --dport 22 -j DROP
  • 禁止代理端口

#iptables -A INPUT -p tcp --dport 3128 -j REJECT
  • 禁止icmp端口

除192.168.62.1外,禁止其它人ping我的主機
#iptables -A INPUT -i eth0 -s 192.168.62.1/32 -p icmp -m icmp --icmp-type echo-request -j ACCEPT
#iptables -A INPUT -i eth0 -p icmp --icmp-type echo- request –j ?DROP

#iptables -A INPUT -i eth0 -s 192.168.62.1/32 -p icmp -m icmp --icmp-type 8 -j ACCEPT
#iptables -A INPUT -i eth0 -p icmp -m icmp --icmp-type 8 -j DROP
注:可以用iptables --protocol icmp --help查看ICMP類型
還有沒有其它辦法實現?
  • 禁止QQ端口

#iptables -D FORWARD -p udp --dport 8000 -j REJECT

強制訪問指定的站點


圖3

要使192.168.52.0/24網絡內的計算機(這此計算機的網關應設為192.168.52.10)強制訪問指定的站點,在做為防火牆的計算機(192.168.52.10)上應添加以下規則:
1. 打開ip包轉發功能 
echo 1 > /proc/sys/net/ipv4/ip_forward
2. 在NAT/防火牆計算機上的NAT表中添加目的地址轉換規則:
iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 202.96.134.130:80
iptables -t nat -I PREROUTING -i eth0 -p udp --dport 80 -j DNAT --to-destination 202.96.134.130:80
3. 在NAT/防火牆計算機上的NAT表中添加源地址轉換規則: 
iptables -t nat -I POSTROUTING -o eth1 -p tcp --dport 80 -s 192.168.52.0/24 -j SNAT --to-source 202.96.134.10:20000-30000
iptables -t nat -I POSTROUTING -o eth1 -p udp --dport 80 -s 192.168.52.0/24 -j SNAT --to-source 202.96.134.10:20000-30000
4. 測試:在內部網的任一台計算機上打開瀏覽器,輸入任一非本網絡的IP,都將指向IP為202.96.134.130的網站.

發佈內部網絡服務器



圖4
要使因特網上的計算機訪問到內部網的FTP服務器、WEB服務器,在做為防火牆的計算機上應添加以下規則:
1. echo 1 > /proc/sys/net/ipv4/ip_forward
2.發佈內部網web服務器
iptables -t nat -I PREROUTING -p tcp -i eth1 -s 202.96.134.0/24 --dport 80 -j DNAT --to-destination 192.168.52.15:80
iptables -t nat -I POSTROUTING -p tcp -i eth0 -s 192.168.52.15 --sport 80 -j SNAT --to-source 202.96.134.10:20000-30000 
3.發佈內部網ftp服務器
iptables -t nat -I PREROUTING -p tcp -i eth1 -s 202.96.134.0/24 --dport 21 -j DNAT --to-destination 192.168.52.14:21
iptables -t nat -I POSTROUTING -p tcp -i eth0 -s 192.168.52.14 --sport 21 -j SNAT --to-source 202.96.134.10:40000-50000  
4. 注意:內部網的計算機網關要設置為防火牆的ip(192.168.52.1)
5. 測試: 用一台IP地址為202.96.134.0段的計算機虛擬因特網訪問,當在其瀏覽器中訪問http://202.96.134.10時,實際應看到的是192.168.52.15的的web服務;
當訪問ftp://202.96.134.10時,實際應看到的是192.168.52.14上的的ftp服務

智能DNS


圖5
1. echo 1 > /proc/sys/net/ipv4/ip_forward
2. 在NAT服務器上添加以下規則:
在PREROUTING鏈中添加目的地址轉換規則:
iptables -t nat -I PREROUTING -i eth0 -p tcp --dpor 53 -j DNAT --to-destination 202.96.134.130
iptables -t nat -I PREROUTING -i eth0 -p udp --dpor 53 -j DNAT --to-destination 202.96.134.130
在POSTROUTING鏈中添加源地址轉換規則:
iptables -t nat -I POSTROUTING -o eth1 -s 192.168.52.0/24 -p tcp --dpor 53 -j SNAT --to-source 202.96.134.10:40000-50000
iptables -t nat -I POSTROUTING -o eth1 -s 192.168.52.0/24 -p udp --dpor 53 -j SNAT --to-source 202.96.134.10:40000-50000
3. 測試
在內部網任一台計算機上,將DNS設置為任意的外網IP,就可以使用DNS測試工具如nslookup來解析DNS服務器202.96.134.130上的名稱.

端口映射

見上節透明代理設置
#iptables -t nat -A PREROUTING -i eth0 -p tcp -s 192.168.62.0/24 --dport 80 -j REDIRECT --to-ports 3128

通過NAT上網

  • 典型NAT上網

一般做為NAT的計算機同時也是局域網的網關,假定該機有兩塊網卡eth0、eth1,eth0連接外網,IP為202.96.134.134;eth1連接局域網,IP為192.168.62.10
1. 先在內核裡打開ip轉發功能
#echo 1 > /proc/sys/net/ipv4/ip_forward
2.?使局域網用戶能訪問internet所要做的nat
#iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to?202.96.134.134
如果上網的IP是動態IP,則使用以下規則:
#iptables -t nat -A POSTROUTING -o eth0 -s 192.168.62.0/24 -j MASQUERADE
如果是通過ADSL上網,且公網IP是動態IP,則使用以下規則:
#iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.62.0/24 -j MASQUERADE
3. 使internet用戶可以訪問局域網內web主機所要做的nat
#iptables -t nat -A PREROUTING -p tcp -d 202.96.134.134 --dport 80 -j DNAT --to-destination 192.168.62.10
注:局域網內的客戶端需將默認網關、DNS設為防火牆的IP
  • 在我們的網絡機房實現NAT共享上網

工作環境:上層代理192.168.60.6(4480),只授予教師機(192.168.62.111)使用該代理的權限
目標:不使用squid代理上網,而是使用NAT的方式上網
方法:
1) 確保停止教師機(192.168.62.111)的squid或其它代理服務
2) 客戶端網關、DNS均指向192.168.62.111,瀏覽器代理設置為192.168.60.6(4480)。測試在當前情況下能否上網
3) 在教師機(192.168.62.111)上添加如下iptables規則:
#iptables -t nat -A POSTROUTING -p tcp -d 192.168.60.6/32 --dport 4480 -j SNAT --to-source 192.168.62.111:10000-30000
解釋:對於目的地為192.168.60.6、目的端口為4480的TCP包,在經過防火牆路由後,將其源地址轉換為192.168.62.111,端口轉換為10000-30000間的某個端口。
4) 客戶端測試能否上網

IP規則的保存與恢復

iptables-save把規則保存到文件中,再由目錄rc.d下的腳本(/etc/rc.d/init.d/iptables)自動裝載
使用命令iptables-save來保存規則。一般用
iptables-save > /etc/sysconfig/iptables
生成保存規則的文件/etc/sysconfig/iptables,
也可以用
service iptables save
它能把規則自動保存在/etc/sysconfig/iptables中。
當計算機啟動時,rc.d下的腳本將用命令iptables-restore調用這個文件,從而就自動恢復了規則。

iptables 指令語法

iptables [-t table] command [match] [-j target/jump]

[-t table] 指定規則表

-t 參數用來,內建的規則表有三個,分別是:nat、mangle 和filter,當未指定規則表時,則一律視為是filter。個規則表的功能如下:
nat:此規則表擁有PREROUTING 和POSTROUTING 兩個規則鏈,主要功能為進行一對一、一對多、多對多等網址轉換工作(SNAT、DNAT),這個規則表除了作網址轉換外,請不要做其它用途。
mangle:此規則表擁有PREROUTING、FORWARD 和POSTROUTING 三個規則鏈。除了進行網址轉換工作會改寫封包外,在某些特殊應用可能也必須去改寫封包(TTL、TOS)或者是設定MAR​​K(將封包作記號,以進行後續的過濾),這時就必須將這些工作定義在mangle 規則表中,由於使用率不高,我們不打算在這裡討論mangle 的用法。
filter: 這個規則表是默認規則表,擁有INPUT、FORWARD 和OUTPUT 三個規則鏈,這個規則表顧名思義是用來進行封包過濾的處理動作(例如:DROP、 LOG、 ACCEPT ​​或REJECT),我們會將基本規則都建立在此規則表中。

command 常用命令列表:

命令-A, --append
範例iptables -A INPUT ...
說明新增規則到某個規則鏈中,該規則將會成為規則鏈中的最後一條規則。
命令-D, --delete
範例iptables -D INPUT --dport 80 -j DROP
iptables -D INPUT 1
說明從某個規則鏈中刪除一條規則,可以輸入完整規則,或直接指定規則編號加以刪除。
命令-R, --replace
範例iptables -R INPUT 1 -s 192.168.0.1 -j DROP
說明取代現行規則,規則被取代後並不會改變順序。
命令-I, --insert
範例iptables -I INPUT 1 --dport 80 -j ACCEPT
說明插入一條規則,原本該位置上的規則將會往後移動一個順位。
命令-L, --list
範例1 iptables -L INPUT
說明列出某規則鏈中的所有規則。
範例2 iptables -t nat -L
說明列出nat表所有鏈中的所有規則。
命令-F, --flush
範例iptables -F INPUT
說明刪除filter表中INPUT鏈的所有規則。
命令-Z, --zero
範例iptables -Z INPUT
說明將封包計數器歸零。封包計數器是用來計算同一封包出現次數,是過濾阻斷式攻擊不可或缺的工具。
命令-N, --new-chain
範例iptables -N allowed
說明定義新的規則鏈。
命令-X, --delete-chain
範例iptables -X allowed
說明刪除某個規則鏈。
命令-P, --policy
範例iptables -P INPUT DROP
說明定義過濾政策。也就是未符合過濾條件之封包,默認的處理方式。
命令-E, --rename-chain
範例iptables -E allowed disallowed
說明修改某自定義規則鏈的名稱。

[match] 常用封包匹配參數

參數-p, --protocol
範例iptables -A INPUT -p tcp
說明匹配通訊協議類型是否相符,可以使用!運算符進行反向匹配,例如:
-p !tcp
意思是指除tcp以外的其它類型,如udp、icmp ...等。
如果要匹配所有類型,則可以使用all關鍵詞,例如:
-p all
參數-s, --src, --source
範例iptables -A INPUT -s 192.168.1.1
說明用來匹配封包的來源IP,可以匹配單機或網絡,匹配網絡時請用數字來表示子網掩碼,例如:
-s 192.168.0.0/24
匹配IP時可以使用!運算符進行反向匹配,例如:
-s !192.168.0.0/24。
參數-d, --dst, --destination
範例iptables -A INPUT -d 192.168.1.1
說明用來匹配封包的目的地IP,設定方式同上。
參數-i, --in-interface
範例iptables -A INPUT -i eth0
說明用來匹配封包是從哪塊網卡進入,可以使用通配字符+來做大範圍匹配,例如:
-i eth+
表示所有的ethernet網卡
也可以使用!運算符進行反向匹配,例如:
-i !eth0
參數-o, --out-interface
範例iptables -A FORWARD -o eth0
說明用來匹配封包要從哪塊網卡送出,設定方式同上。
參數--sport, --source-port
範例iptables -A INPUT -p tcp --sport 22
說明用來匹配封包的源端口,可以匹配單一端口,或是一個範圍,例如:
--sport 22:80
表示從22到80端口之間都算是符合條件,如果要匹配不連續的多個端口,則必須使用--multiport參數,詳見後文。匹配端口號時,可以使用!運算符進行反向匹配。
參數--dport, --destination-port
範例iptables -A INPUT -p tcp --dport 22
說明用來匹配封包的目的地端口號,設定方式同上
參數--tcp-flags
範例iptables -p tcp --tcp-flags SYN,FIN,ACK SYN
說明匹配TCP封包的狀態標誌,參數分為兩個部分,第一個部分列舉出想匹配的標誌,第二部分則列舉前述標誌中哪些有被設置,未被列舉的標誌必須是空的。TCP狀態標誌包括:SYN(同步)、ACK(應答)、FIN(結束)、RST(重設)、URG(緊急) 、PSH(強迫推送)等均可使用於參數中,除此之外還可以使用關鍵詞ALL和NONE進行匹配。匹配標誌時,可以使用!運算符行反向匹配。
參數--syn
範例iptables -p tcp --syn
說明用來表示TCP通信協議中,SYN位被打開,而ACK與FIN位關閉的分組,即TCP的初始連接,與iptables -p tcp --tcp -flags SYN,FIN,ACK SYN的作用完全相同,如果使用!運算符,可用來匹配非要求連接封包。
參數-m multiport --source-port
範例iptables -A INPUT -p tcp -m multiport --source-port 22,53,80,110
說明用來匹配不連續的多個源端口,一次最多可以匹配15個端口,可以使用!運算符進行反向匹配。
參數-m multiport --destination-port
範例iptables -A INPUT -p tcp -m multiport --destination-port 22,53,80,110
說明用來匹配不連續的多個目的地端口號,設定方式同上
參數-m multiport --port
範例iptables -A INPUT -p tcp -m multiport --port 22,53,80,110
說明這個參數比較特殊,用來匹配源端口和目的端口號相同的封包,設定方式同上。注意:在本範例中,如果來源端口號為80目的地端口號為110,這種封包並不算符合條件。
參數--icmp-type
範例iptables -A INPUT -p icmp --icmp-type 8
說明用來匹配ICMP的類型編號,可以使用代碼或數字編號來進行匹配。請打iptables -p icmp --help來查看有哪些代碼可用。
參數-m limit --limit
範例iptables -A INPUT -m limit --limit 3/hour
說明用來匹配某段時間內封包的平均流量,上面的例子是用來匹配:每小時平均流量是否超過一次3個封包。除了 ​​每小時平均次外,也可以每秒鐘、每分鐘或每天平均一次,默認值為每小時平均一次,參數如後: /second、 /minute、/day。除了 ​​進行封包數量的匹配外,設定這個參數也會在條件達成時,暫停封包的匹配動作,以避免因駭客使用洪水攻擊法,導致服務被阻斷。
參數--limit-burst
範例iptables -A INPUT -m limit --limit-burst 5
說明用來匹配瞬間大量封包的數量,上面的例子是用來匹配一次同時湧入的封包是否超過5個(這是默認值),超過此上限的封包將被直接丟棄。使用效果同上。
參數-m mac --mac-source
範例iptables -A INPUT -m mac --mac-source 00:00:00:00:00:01
說明用來匹配封包來源網絡接口的硬件地址,這個參數不能用在OUTPUT和POSTROUTING規則鏈上,這是因為封包要送到網卡後,才能由網卡驅動程序透過ARP通訊協議查出目的地的MAC地址,所以iptables在進行封包匹配時,並不知道封包會送到哪個網絡接口去。
參數--mark
範例iptables -t mangle -A INPUT -m mark --mark 1
說明用來匹配封包是否被表示某個號碼,當封包被匹配成功時,我們可以透過MARK處理動作,將該封包標示一個號碼,號碼最大不可以超過4294967296。
參數-m owner --uid-owner
範例
iptables -A OUTPUT -m owner --uid-owner 500
說明用來匹配來自本機的封包,是否為某特定使用者所產生的,這樣可以避免服務器使用root或其它身分將敏感數據傳送出,可以降低系統被駭的損失。可惜這個功能無法匹配出來自其它主機的封包。
參數-m owner --gid-owner
範例iptables -A OUTPUT -m owner --gid-owner 0
說明用來匹配來自本機的封包,是否為某特定使用者群組所產生的,使用時機同上。
參數-m owner --pid-owner
範例
iptables -A OUTPUT -m owner --pid-owner 78
說明用來匹配來自本機的封包,是否為某特定進程所產生的,使用時機同上。
參數-m owner --sid-owner
範例
iptables -A OUTPUT -m owner --sid-owner 100
說明用來匹配來自本機的封包,是否為某特定連接(Session ID)的響應封包,使用時機同上。
參數-m state --state
範例
iptables -A INPUT -m state --state RELATED,ESTABLISHED
說明用來匹配連接狀態,連接狀態共有四種:INVALID、ESTABLISHED、NEW和RELATED。
INVALID表示該封包的連接編號(Session ID)無法辨識或編號不正確。
ESTABLISHED表示該封包屬於某個已經建立的連接。
NEW表示該封包想要起始一個連接(重設連接或將連接重導向)。
RELATED表示該封包是屬於某個已經建立的連接,所建立的新連接。例如:FTP-DATA連接必定是源自某個FTP連接。

[-j target/jump] 常用的處理動作:

-j 參數用來指定要進行的處理動作,常用的處理動作包括:ACCEPT、REJECT、DROP、REDIRECT、MASQUERADE、LOG、DNAT、SNAT、MIRROR、QUEUE、RETURN、MARK,分別說明如下:
ACCEPT: 將封包放行,進行完此處理動作後,將不再匹配其它規則,直接跳往下一個規則鏈(natostrouting)。
REJECT:攔阻該封包,並傳送封包通知對方,可以傳送的封包有幾個選擇:ICMP port-unreachable、ICMP echo-reply或是tcp-reset(這個封包會要求對方關閉連接),進行完此處理動作後,將不再匹配其它規則,直接中斷過濾程序。範例如下:
iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
DROP: 丟棄封包不予處理,進行完此處理動作後,將不再匹配其它規則,直接中斷過濾程序。
REDIRECT:將封包重新導向到另一個端口(PNAT),進行完此處理動作後,將會繼續匹配其它規則。這個功能可以用來實現透明代理或用來保護web服務器。例如:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
MASQUERADE:改寫封包來源IP為防火牆NIC IP,可以指定port對應的範圍,進行完此處理動作後,直接跳往下一個規則鏈(manglepostrouting)。這個功能與SNAT略有不同,當進行IP偽裝時,不需指定要偽裝成哪個IP,IP會從網卡直接讀取,當使用撥號接連時,IP通常是由ISP公司的DHCP服務器指派的,這個時候MASQUERADE特別有用。範例如下:
iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 1024-31000
LOG:將封包相關訊息紀錄在/var/log中,詳細位置請查閱/etc/syslog.conf配置文件,進行完此處理動作後,將會繼續匹配其規則。例如:
iptables -A INPUT -p tcp -j LOG --log-prefix "INPUT packets"
SNAT:改寫封包來源IP為某特定IP或IP範圍,可以指定port對應的範圍,進行完此處理動作後,將直接跳往下一個規則(mangleostrouting)。範例如下:
iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source?194.236.50.155-194.236.50.160:1024-32000 
DNAT:改寫封包目的地IP為某特定IP或IP範圍,可以指定port對應的範圍,進行完此處理動作後,將會直接跳往下一個規則鏈(filter:input或filter:forward)。範例如下:
iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10:80-100
MIRROR: 鏡射封包,也就是將來源IP 與目的地IP 對調後,將封包送回,進行完此處理動作後,將會中斷過濾程序。
QUEUE: 中斷過濾程序,將封包放入隊列,交給其它程序處理。通過自行開發的處理程序,可以進行其它應用,例如:計算連接費用等。
RETURN: 結束在目前規則鏈中的過濾程序,返回主規則鏈繼續過濾,如果把自定義規則鏈看成是一個子程序,那麼這個動作,就相當於提前結束子程序並返回到主程序中。
MARK:將封包標上某個代號,以便提供作為後續過濾的條件判斷依據,進行完此處理動作後,將會繼續匹配其它規則。範例如下:
iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2

iptables實例

單個規則實例

iptables -F?
# -F是清除的意思,作用就是把FILTRE TABLE的所有鏈的規則都清空
iptables -A INPUT -s 172.20.20.1/32 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
#在FILTER表的INPUT鏈匹配源地址是172.20.20.1的主機,狀 ​​態分別是NEW,ESTABLISHED,RELATED的都放行。
iptables -A INPUT -s 172.20.20.1/32 -m state --state NEW,ESTABLISHED -p tcp -m multiport --dport 123,110 -j ACCEPT
# -p指定協議,-m指定模塊,multiport模塊的作用就是可以連續匹配多各不相鄰 ​​的端口號。完整的意思就是源地址是172.20.20.1的主機,狀 ​​態分別是NEW, ESTABLISHED,RELATED的,TCP協議,目的端口分別為123和110的數據包都可以通過。
iptables -A INPUT -s 172.20.22.0/24 -m state --state NEW,ESTABLISHED -p tcp -m multiport --dport 123,110 -j ACCEPT
iptables -A INPUT -s 0/0 -m state --state NEW -p tcp -m multiport --dport 123,110 -j DROP
#這句意思為源地址是0/0的NEW狀態的的TCP數據包都禁止訪問我的123和110端口。
iptables -A INPUT -s ! 172.20.89.0/24 -m state --state NEW -p tcp -m multiport --dport 1230,110 -j DROP
# "!"號的意思取反。就是除了172.20.89.0這個IP段的地址都DROP。
iptables -R INPUT 1 -s 192.168.6.99 -p tcp --dport 22 -j ACCEPT
替換INPUT鏈中的第一條規則
iptables -t filter -L INPUT -vn
以數字形式詳細顯示filter表INPUT鏈的規則

#-------------------------------NAT IP---------------- ----------------------
#以下操作是在NAT TABLE裡面完成的。請大家注意。
iptables -t nat -F
iptables -t nat -A PREROUTING -d 192.168.102.55 -p tcp --dport 90 -j DNAT --to 172.20.11.1:800
#-A PREROUTING 指定在路由前做的。完整的意思是在NAT TABLE 的路由前處理,目的地為192.168.102.55 的目的端口為90的我們做DNAT處理,給他轉向到172.20.11.1:800那裡去。
iptables -t nat -A POSTROUTING -d 172.20.11.1 -j SNAT --to 192.168.102.55
#-A POSTROUTING 路由後。意思為在NAT TABLE 的路由後處理,凡是目的地為172.20.11.1 的,我們都給他做SNAT轉換,把源地址改寫成192.168.102.55 。

iptables -A INPUT -d 192.168.20.0/255.255.255.0 -i eth1 -j DROP
iptables -A INPUT -s 192.168.20.0/255.255.255.0 -i eth1 -j DROP
iptables -A OUTPUT -d 192.168.20.0/255.255. 255.0 -o eth1 -j DROP
iptables -A OUTPUT -s 192.168.20.0/255.255.255.0 -o eth1 -j DROP
# 上例中,eth1是一個與外部Internet相連,而192.168.20.0則是內部網的網絡號,上述規則用來防止IP欺騙,因為出入eth1的包的ip應該是公共IP
iptables -A INPUT -s 255.255.255.255 -i eth0 -j DROP
iptables -A INPUT -s 224.0.0.0/224.0.0.0 -i eth0 -j DROP
iptables -A INPUT -d 0.0.0.0 -i eth0 -j DROP
# 防止廣播包從IP代理服務器進入局域網:
iptables -A INPUT -p tcp -m tcp --sport 5000 -j DROP
iptables -A INPUT -p udp -m udp --sport 5000 -j DROP
iptables -A OUTPUT -p tcp -m tcp --dport 5000 -j DROP
iptables -A OUTPUT -p udp -m udp --dport 5000 -j DROP
# 屏蔽端口5000
iptables -A INPUT -s 211.148.130.129 -i eth1 -p tcp -m tcp --dport 3306 -j DROP
iptables -A INPUT -s 192.168.20.0/255.255.255.0 -i eth0 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 211.148.130.128/255.255.255.240 -i eth1 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 3306 -j DROP
# 防止Internet 網的用戶訪問MySQL 服務器(就是3306 端口)
iptables -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
#REJECT, 類似於DROP,但向發送該包的主機回復由--reject-with指定的信息,從而可以很好地隱藏防火牆的存在

www的iptables實例

#!/bin/bash
export PATH=/sbin:/usr/sbin:/bin:/usr/bin
#加載相關模塊
modprobe iptable_nat
modprobe ip_nat_ftp
modprobe ip_nat_irc
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc
modprobe ipt_limit
echo 1 >;/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 0 >;/proc/sys/net/ipv4/conf/all/accept_source_route
echo 0 >;/proc/sys/net/ipv4/conf/all/accept_redirects
echo 1 >;/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 1 >;/proc/sys/net/ipv4/conf/all/log_martians
echo 1 >;/proc/sys/net/ipv4/tcp_syncookies
iptables -F
iptables -X
iptables -Z
##允許本地迴路?Loopback - Allow unlimited traffic
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
##防止SYN洪水?SYN-Flooding Protection
iptables -N syn-flood
iptables -A INPUT -i ppp0 -p tcp --syn -j syn-flood
iptables -A syn-flood -m limit --limit 1/s - -limit-burst 4 -j RETURN
iptables -A syn-flood -j DROP
##確保新連接是設置了SYN標記的包?Make sure that new TCP connections are SYN packets
iptables -A INPUT -i eth0 -p tcp ! --syn -m state --state NEW -j DROP
##允許HTTP的規則
iptables -A INPUT -i ppp0 -p tcp -s 0/0 --sport 80 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp -s 0 /0 --sport 443 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp -d 0/0 --dport 80 -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp -d 0/0 --dport 443 -j ACCEPT
##允許DNS的規則
iptables -A INPUT -i ppp0 -p udp -s 0/0 --sport 53 -m state --state ESTABLISHED -j ACCEPT
iptables -A INPUT -i ppp0 -p udp -d 0/0 --dport 53 -j ACCEPT
## IP包流量限制?IP packets limit
iptables -A INPUT -f -m limit --limit 100/s --limit-burst 100 -j ACCEPT
iptables -A INPUT -i eth0 -p icmp -j DROP
##允許SSH
iptables -A INPUT -p tcp -s ip1/32 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s ip2/32 --dport 22 -j ACCEPT
##其它情況不允許?Anything else not allowed
iptables -A INPUT -i eth0 -j DROP

一個包過濾防火牆實例

環境:redhat9 加載了string time等模塊
eth0接外網──ppp0
eth1接內網──192.168.0.0/24
#!/bin/sh
#
modprobe ipt_MASQUERADE
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
iptables -F
iptables -t nat -F
iptables -X
iptables -t nat -X
################### ########INPUT鍵###################################
iptables -P INPUT DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 110,80,25 -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.0.0/ 24 --dport 139 -j ACCEPT
#允許內網samba,smtp,pop3,連接
iptables -A INPUT -i eth1 -p udp -m multiport --dports 53 -j ACCEPT
#允許dns連接
iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
iptables -A INPUT -p gre -j ACCEPT
#允許外網vpn連接
iptables -A INPUT -s 192.186.0.0/24 -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp --syn -m connlimit --connlimit-above 15 -j DROP
#為了防止DoS太多連接進來,那麼可以允許最多15個初始連接,超過的丟棄
iptables -A INPUT -s 192.186.0.0/24 -p tcp --syn -m connlimit --connlimit-above 15 -j DROP
#為了防止DoS太多連接進來,那麼可以允許最多15個初始連接,超過的丟棄
iptables -A INPUT -p icmp -m limit --limit 3/s -j LOG --log-level INFO --log-prefix "ICMP packet IN: "
iptables -A INPUT -p icmp -j DROP
#禁止icmp通信-ping不通
iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.0.0/24 -j MASQUERADE
#內網轉發
iptables -N syn-flood
iptables -A INPUT -p tcp --syn -j syn-flood
iptables -I syn- flood -p tcp -m limit --limit 3/s --limit-burst 6 -j RETURN
iptables -A syn-flood -j REJECT
#防止SYN攻擊輕量
############# ##########FORWARD鏈###########################
iptables -P FORWARD DROP
iptables -A FORWARD -p tcp -s 192.168.0.0/24 -m multiport --dports 80,110,21,25,1723 -j ACCEPT
iptables -A FORWARD -p udp -s 192.168.0.0/24 --dport 53 -j ACCEPT
iptables -A FORWARD - p gre -s 192.168.0.0/24 -j ACCEPT
iptables -A FORWARD -p icmp -s 192.168.0.0/24 -j ACCEPT
#允許vpn客戶走vpn網絡連接外網
iptables -A FORWARD -m state --state ESTABLISHED ,RELATED -j ACCEPT
iptables -I FORWARD -p udp --dport 53 -m string --string "tencent" -m time --timestart 8:15 --timestop 12:30 --days Mon,Tue,Wed,Thu ,Fri,Sat -j DROP
#星期一到星期六的8:00-12:30禁止qq通信
iptables -I FORWARD -p udp --dport 53 -m string --string "TENCENT" -m time --timestart 8:15 --timestop 12:30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP
#星期一到星期六的8:00-12:30禁止qq通信
iptables -I FORWARD -p udp --dport 53 -m string --string "tencent" -m time --timestart 13:30 --timestop 20:30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP
iptables -I FORWARD - p udp --dport 53 -m string --string "TENCENT" -m time --timestart 13:30 --timestop 20:30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP
#星期一到星期六的13:30-20:30禁止QQ通信
iptables -I FORWARD -s 192.168.0.0/24 -m string --string "qq.com" -m time --timestart 8:15 --timestop 12: 30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP
#星期一到星期六的8:00-12:30禁止qq網頁
iptables -I FORWARD -s 192.168.0.0/24 -m string - -string "qq.com" -m time --timestart 13:00 --timestop 20:30 --days Mon,Tue,Wed,Thu,Fri,Sat -j DROP
#星期一到星期六的13:30- 20:30禁止QQ網頁
iptables -I FORWARD -s 192.168.0.0/24 -m string --string "ay2000.net" -j DROP
iptables -I FORWARD -d 192.168.0.0/24 -m string --string "寬頻影院" -j DROP
iptables -I FORWARD -s 192.168.0.0/24 -m string --string "色情" -j DROP
iptables -I FORWARD -p tcp --sport 80 -m string --string "廣告" -j DROP
#禁止ay2000.net,寬頻影院,色情,廣告網頁連接!但中文不是很理想
iptables -A FORWARD -m ipp2p --edk --kazaa --bit -j DROP
iptables -A FORWARD -p tcp -m ipp2p --ares -j DROP
iptables -A FORWARD -p udp -m ipp2p --kazaa -j DROP
#禁止BT連接
iptables -A FORWARD -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 --connlimit-mask 24 -j DROP
#只允許每組ip同時15個80端口轉發
############################################## #########################
sysctl -w net.ipv4.ip_forward=1 &>/dev/null
#打開轉發
###### ################################################## ###############
sysctl -w net.ipv4.tcp_syncookies=1 &>/dev/null
#打開syncookie (輕量級預防DOS攻擊)
sysctl -w net.ipv4.netfilter .ip_conntrack_tcp_timeout_established=3800 &>/dev/null
#設置默認TCP連接癡呆時長為3800秒(此選項可以大大降低連接數)
sysctl -w net.ipv4.ip_conntrack_max=300000 &>/dev/null
#設置支持最大連接樹為30W(這個根據你的內存和iptables版本來,每個connection需要300多個字節)
######################## ###############################################
iptables -I INPUT -s 192.168.0.50 -j ACCEPT
iptables -I FORWARD -s 192.168.0.50 -j ACCEPT
#192.168.0.50是我的機子,全部放行!

squid+iptables

[原創] squid+iptables實現網關防火牆
http://www.chinaunix.net作者:jackylau發表於:2007-05-27 10:40:01
【發表評論】【查看原文】【Proxy服務器討論區】【關閉】
需求說明:此服務器用作網關、MAIL(開啟web、smtp、pop3)、FTP、DHCP服務器,內部一台機器(192.168.0.254)對外提供dns服務,為了不讓無意者輕易看出此服務器開啟了ssh服務器,故把ssh端口改為2018.另把proxy的端口改為60080
eth0:218.28.20.253,外網口
eth1:192.168.0.1/24,內網口
[jackylau@proxyserver init.d]$cat /etc/squid/squid.conf(部份如下)
http_port 192.168.0.1:60080
httpd_accel_port 80
httpd_accel_host virtual
httpd_accel_with_proxy on
httpd_accel_uses_host_header on
acl allow_lan src 192.168.0.0/24
http_access allow allow_lan
visible_hostname proxyserver
[jackylau@proxyserver init.d]$ cat firewall
#!/bin/sh
# Author: jackylau
# chkconfig: 2345 08 92
# description: firewall
# Time on 2005.08.02
# killproc
# Set ENV
INET_IP="218.28.20.253"
INET_IFACE="eth0"
LAN_IP="192.168.0.1"
LAN_IP_RANGE="192.168.0.0/24"
LAN_BROADCAST_ADDRESS="192.168.0.255"
LAN_IFACE="eth1"
LO_IFACE="lo"
LO_IP="127.0.0.1"
IPTABLES="/sbin/iptables"
start(){
echo -n $"Starting firewall:"
/sbin/depmod -a
/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/ sbin/modprobe ipt_limit
/sbin/modprobe ipt_state
echo "1" >; /proc/sys/net/ipv4/ip_forward
# Set policies
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
# Add bad_tcp_packets, allowed and icmp_packets
$IPTABLES -N bad_tcp_packets
$IPTABLES -N tcp_packets
$IPTABLES -N udp_packets
$IPTABLES -N allowed
$IPTABLES -N icmp_packets
# bad_tcp_packets
$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j LOG --log-level INFO --log-prefix "New not syn:"
$IPTABLES -A bad_tcp_packets -p TCP ! --syn -m state --state NEW -j DROP
# allowed
$IPTABLES -A allowed -p TCP --syn -j ACCEPT
$IPTABLES -A allowed -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A allowed -p TCP -j DROP
$IPTABLES -A INPUT -p ALL -i $LAN_IFACE -d $LAN_BROADCAST_ADDRESS -j ACCEPT
# TCP rules
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 20 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 21 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 25 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 80 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 110 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 2018 -j allowed
# UDP rules
$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 67 -j ACCEPT
# ICMP rules
$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT
$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT
# INPUT chain
$IPTABLES -A INPUT -p tcp -j bad_tcp_packets
$IPTABLES -A INPUT -p ALL -i $LAN_IFACE -s $LAN_IP_RANGE -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LO_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LAN_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $INET_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -d $INET_IP -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -p TCP -i $INET_IFACE -j tcp_packets
$IPTABLES -A INPUT -p UDP -i $INET_IFACE -j udp_packets
$IPTABLES -A INPUT -p ICMP -i $INET_IFACE -j icmp_packets
$IPTABLES -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT INPUT packet died: "
# FORWARD chain
$IPTABLES -A FORWARD -p tcp -j bad_tcp_packets
$IPTABLES -A FORWARD -i $LAN_IFACE -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -m limit --limit 3/minute --limit-burst 3 - j LOG --log-level DEBUG --log-prefix "IPT FORWARD packet died: "
# OUTPUT chain
$IPTABLES -A OUTPUT -p tcp -j bad_tcp_packets
$IPTABLES -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $LAN_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $INET_IP -j ACCEPT
$IPTABLES -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT OUTPUT packet died: "
# SNAT table
$IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP
# DNAT table
$IPTABLES -t nat -A PREROUTING -p ! icmp -d $INET_IP -dport 53 -j DNAT --to-destination 192.168.0.254:53
# REDIRECT
$IPTABLES -t nat -A PREROUTING -i $LAN_IFACE -p tcp -s $LAN_IP_RANGE --dport 80 -j REDIRECT --to-ports 60080
touch /var/lock/subsys/firewall
}
stop(){
echo -n $"Stoping firewall:"
echo "0">;/proc/sys/net/ipv4/ip_forward
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES - t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
$IPTABLES -t mangle -P PREROUTING ACCEPT
$IPTABLES -t mangle -P OUTPUT ACCEPT
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F
$IPTABLES -X
$IPTABLES -t nat -X
$IPTABLES -t mangle -X
rm -f /var/lock/subsys/firewall
}
status(){
clear
echo "------------------------------------------- ------------------------"
$IPTABLES -L
echo "------------------- ------------------------------------------------"
$ IPTABLES -t nat -L POSTROUTING
echo "----------------------------------------- --------------------------"
$IPTABLES -t nat -L PREROUTING
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "$0 [start|stop|restart|status]"
;;
esac
cp firewall /etc/init.d/
chmod 700 /etc/init.d/firewall
chkconfig --add firewall

rc.firewall腳本代碼


#!/bin/sh
#
# rc.firewall - Initial SIMPLE IP Firewall script for Linux 2.4.x and iptables
#
# Copyright (C) 2001?Oskar Andreasson  
#
# This program is free software; you can redistribute it and /or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.?See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program or from the site that you downloaded it
# from; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA?02111-1307?USA
#
################################################## #########################
#
# 1.配置選項.
#
#
# 1.1 Internet相關變量設置.
#
INET_IP="194.236.50.155"
INET_IFACE="eth0"
INET_BROADCAST="194.236.50.255"
#
# 1.1.1 DHCP相關設置
#
#
# 1.1.2 PPPoE相關設置
#
#
# 1.2局域網相關變量設置.
#
LAN_IP="192.168.0.2" #防火牆連接局域網的IP地址
LAN_IP_RANGE="192.168.0.0/16" #局域網地址
LAN_IFACE="eth1" #防火牆連接局域網的網絡接口
#
# 1.3 DMZ非軍事區相關變量設置.
#
#
# 1.4本機相關變量設置.
#
LO_IFACE="lo" #本地接口名稱
LO_IP="127.0.0.1" #本地接口IP 
#
# 1.5 IPTables路徑設置.
#
IPTABLES="/usr/sbin/iptables"
#
# 1.6其它配置.
#
################################################## #########################
#
# 2.要加載的模塊.
#
#
#初始加載的模塊
#
/sbin/depmod -a
#
# 2.1需加載的模塊
#
/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_state
#
# 2.2不需加載的模塊
#
#/sbin/modprobe ipt_owner
#/sbin/modprobe ipt_REJECT
#/sbin/modprobe ipt_MASQUERADE
#/sbin/modprobe ip_conntrack_ftp
#/sbin/modprobe ip_conntrack_irc
#/sbin/modprobe ip_nat_ftp
#/sbin/modprobe ip_nat_irc
################################################## #########################
#
# 3. /proc設置.
#
#
# 3.1需要的proc配置
#
echo "1" > /proc/sys/net/ipv4/ip_forward
#
# 3.2不需要的proc配置
#
#echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
#echo "1" > /proc/sys/net/ipv4/conf/all/proxy_arp
#echo "1" > /proc/sys /net/ipv4/ip_dynaddr
################################################## #########################
#
# 4.建立規則.
#
######
# 4.1 Filter表
#
#
# 4.1.1建立策略
#
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
#
# 4.1.2創建自定義鏈Create userspecified chains
#
#
#為不可靠的tcp包建立自定義鏈Create chain for bad tcp packets
#
$IPTABLES -N bad_tcp_packets
#
#分別為ICMP, TCP和UDP協議建立自定義鏈Create separate chains for ICMP, TCP and UDP to traverse
#
$IPTABLES -N allowed
$IPTABLES -N tcp_packets
$IPTABLES -N udp_packets
$IPTABLES -N icmp_packets
#
# 4.1.3在自定義鏈建立規則Create content in userspecified chains
#
#
# bad_tcp_packets鏈bad_tcp_packets chain
#
#這條鏈包含的規則檢查進入包(incoming packet)的包頭是否不正常或有沒有其他問題,並進行相應地處理。但事實上,我們使用它只是為了過濾掉一些特殊的包:沒有設置SYN位但又是NEW狀態的TCP包,還有那些設置了SYN/ACK但也被認為是NEW狀態的TCP包。這條鏈可以用來檢查所有可能的不一致的東西
$IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j REJECT --reject-with tcp-reset
$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "New not syn:"
$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP
#
# allowed鏈?allowed chain
#
$IPTABLES -A allowed -p TCP --syn -j ACCEPT
$IPTABLES -A allowed -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A allowed -p TCP -j DROP
#
# TCP規則?TCP rules
#
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 21 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 22 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 80 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 113 -j allowed
#
# UDP端口?UDP ports
#
#$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 53 -j ACCEPT
#$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 123 -j ACCEPT
$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 2074 -j ACCEPT
$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 4000 -j ACCEPT
#
#如果網絡中存在Microsoft網絡的話,你會遭遇洪水一樣的廣播信息,下面的指令將阻止這些廣播並在日誌中#記錄.?In Microsoft Networks you will be swamped by broadcasts. These lines
# will prevent them from showing up in the logs.
#
#$IPTABLES -A udp_packets -p UDP -i $INET_IFACE -d $INET_BROADCAST --destination-port?135:139 -j DROP
#
#如果有來自我們網絡之外的DHCP請求的話,就會很快把我們的日誌塞滿,下面的指令If we get DHCP requests from the Outside of our network, our logs will
# be swamped as well. This rule will block them from getting logged.
#
#$IPTABLES -A udp_packets -p UDP -i $INET_IFACE -d 255.255.255.255 --destination-port 67:68 -j DROP
#
#ICMP規則?ICMP rules
#
$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT
$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT
#
# 4.1.4 INPUT鏈?INPUT chain
#
#
#排除不良TCP包?Bad TCP packets we don't want.
#
$IPTABLES -A INPUT -p tcp -j bad_tcp_packets
#
#非internet網絡部分的規則?Rules for special networks not part of the Internet
#
$IPTABLES -A INPUT -p ALL -i $LAN_IFACE -s $LAN_IP_RANGE -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LO_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LAN_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $INET_IP -j ACCEPT
#
#有關本地DHCP的特殊規則?Special rule for DHCP requests from LAN, which are not caught properly
# otherwise.
#
$IPTABLES -A INPUT -p UDP -i $LAN_IFACE --dport 67 --sport 68 -j ACCEPT
#
#來自因特網的進入包的規則Rules for incoming packets from the internet.
#
$IPTABLES -A INPUT -p ALL -d $INET_IP -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -p TCP -i $INET_IFACE -j tcp_packets
$IPTABLES -A INPUT -p UDP -i $ INET_IFACE -j udp_packets
$IPTABLES -A INPUT -p ICMP -i $INET_IFACE -j icmp_packets
#
#如果防火牆外存在Microsoft網絡的話,你會遭遇洪水一樣的多播信息,下面的指令將丟棄這些包,所以日誌就不會被這些東西淹沒#記錄If you have a Microsoft Network on the outside of your firewall, you may
# also get flooded by Multicasts. We drop them so we do not get flooded by
# logs
#
#$IPTABLES -A INPUT -i $INET_IFACE -d 224.0.0.0/8 -j DROP
#
#將不滿足上述規則的形為怪異的包記錄在案Log weird packets that don't match the above.
#
$IPTABLES -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT INPUT packet died: "
#
# 4.1.5 FORWARD鏈?FORWARD chain
#
#
#排除不良TCP包?Bad TCP packets we don't want
#
$IPTABLES -A FORWARD -p tcp -j bad_tcp_packets
#
#接收想要轉發的TCP包?Accept the packets we actually want to forward
#
$IPTABLES -A FORWARD -i $LAN_IFACE -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
#
#將不滿足上述規則的形為怪異的包記錄在案?Log weird packets that don't match the above.
#
$IPTABLES -A FORWARD -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT FORWARD packet died: "
#
# 4.1.6?OUTPUT鏈?OUTPUT chain
#
#
#排除不良TCP包?Bad TCP packets we don't want.
#
$IPTABLES -A OUTPUT -p tcp -j bad_tcp_packets
#
#決定允許哪個IP包OUTPUT的規則?Special OUTPUT rules to decide which IP's to allow.
#
$IPTABLES -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $LAN_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $INET_IP -j ACCEPT
#
#將不滿足上述規則的形為怪異的包記錄在案?Log weird packets that don't match the above.
#
$IPTABLES -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG --log-level DEBUG --log-prefix "IPT OUTPUT packet died: "
######
# 4.2 nat表?nat table
#
#
# 4.2.1設置策略?Set policies
#
#
# 4.2.2創建用戶自定義鏈?Create user specified chains
#
#
# 4.2.3在用戶自定義鏈中建立規則?Create content in user specified chains
#
#
# 4.2.4 PREROUTING鏈?PREROUTING chain
#
#
# 4.2.5 POSTROUTING鏈?POSTROUTING chain
#
#
#允許簡單的IP轉發及網絡地址轉換?Enable simple IP Forwarding and Network Address Translation
#
$IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP
#
# 4.2.6 OUTPUT鏈?OUTPUT chain
#
######
# 4.3 mangle表?mangle table
#
#
# 4.3.1設置策略?Set policies
#
#
# 4.3.2創建用戶自定義鏈?Create user specified chains
#
#
# 4.3.3在用戶自定義鏈中建立規則?Create content in user specified chains
#
#
# 4.3.4 PREROUTING鏈?PREROUTING chain
#
#
# 4.3.5 INPUT鏈?INPUT chain
#
#
# 4.3.6 FORWARD鏈?FORWARD chain
#
#
# 4.3.7 OUTPUT鏈?OUTPUT chain
#
#
# 4.3.8 POSTROUTING鏈?POSTROUTING chain
#

初始化

IPTABLES -X
IPTABLES -t nat -X
IPTABLES -t mangle -X
iptables -Z 

定義策略(默認規則)

iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state RELATED -j ACCEPT

練習

1. 設置iptables規則,使某幾台計算機能訪問本機的web服務,其它計算機不能訪問本機的web服務.

How to use simple speedtest in RaspberryPi CLI

  pi@ChunchaiRPI2:/tmp $  wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py --2023-06-26 10:4...