iptables防火墙详解

一、iptables概念

1、防火墙基础

1.1 防火墙概念

从逻辑上讲,防火墙可以大体分为主机防火墙和网络防火墙。网络防火墙和主机防火墙并不冲突,可以理解为,网络防火墙主外(集体), 主机防火墙主内(个人)

  • 主机防火墙:针对于单个主机进行防护
  • 网络防火墙:往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网

从物理上讲,防火墙可以分为硬件防火墙和软件防火墙

  • 硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高
  • 软件防火墙:应用软件处理逻辑运行于通用硬件平台之上的防火墙,性能低,成本低

Linux防火墙体系主要工作在网络层,针对TCP/IP数据包实施过滤和限制,属于典型的包过滤防火墙(也称网络层防火墙);Linux防火墙体系基于内核编码实现,具有非常稳定的性能和高效率,因此被广泛的应用

1.2 Netfilter和iptables的区别

Netfilter:指的是Linux内核中实现包过滤防火墙的内部结构,不以程序或文件的形式存在,属于“内核态”(KernelSpace,又称内核空间)的防火墙功能体系(filter是过滤器的意思,netfilter即网络层过滤);Netfilter是Linux操作系统核心层内部的一个数据包处理模块,它具有网络地址转换(Network Address Translate)、数据包内容修改以及数据包过滤的防火墙功能

Iptables:指的是用来管理Linux防火墙的命令程序,通常位于/sbin/iptables,属于“用户态”(UserSpace,又称用户空间)的防火墙管理体系(iptables: IP信息包过滤系统)。虽然我们使用service iptables start启动iptables服务,但是其实准确的来说,iptables并没有一个守护进程,所以并不能算是真正意义上的服务,而应该算是内核提供的功能

2、Iptables的表、链结构

包过滤主要是网络层,针对IP数据包;体现在对包内的IP地址、端口等信息的处理上;而iptables作用是为包过滤机制的实现提供规则(或策略),通过各种不同的规则,告诉netfilter对来自某些源、前往某些目的或具有某些协议特征的数据包应该如何处理。iptables 默认维护着 4 个表和 5 个链,所有的防火墙策略规则都被分别写入这些表与链中

2.1 规则链

规则链上可能不止有一条规则,而是有很多条规则,当我们把这些规则串到一个链条上的时候,就形成了链,ip请求将这条链上的所有规则匹配一遍,如果有符合条件的规则,则执行规则对应的动作。

规则的作用是对数据包进行过滤或处理;链的作用是容纳各种防火墙规则;链的分类依据是处理数据包的不同时机

总共有五种5种规则链,分别是

  • INPUT:处理入站数据包
  • OUTPUT:处理出站数据包
  • FORWARD:处理转发数据包
  • POSTROUTING链:在进行路由选择后处理数据包(对数据链进行源地址修改转换)
  • PREROUTING链:在进行路由选择前处理数据包(做目标地址转换)

INPUT、OUTPUT链主要用在"主机型防火墙"中,即主要针对服务器本机进行保护的防火墙;而FORWARD、PREROUTING、POSTROUTING链多用在"网络型防火墙"中

2.2 规则表

表的作用是容纳各种规则链;表的划分依据是防火墙规则的作用相似,默认包括4个规则表

  • raw表

    确定是否对该数据包进行状态跟踪以及处理异常,表内包含两个链:OUTPUT、PREROUTING

  • mangle表

    为数据包的TOS(服务类型)、TTL(生命周期)值,或者为数据包设置Mark标记,以实现流量整形、策略路由等高级应用。其对应iptable_mangle,表内包含五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD

  • nat表

    修改数据包中的源、目标IP地址或端口;其对应的模块为iptable_nat,表内包括三个链:PREROUTING、POSTROUTING、OUTPUT(centos7中还有INPUT,centos6中没有)

    PREROUTING链 – 处理刚到达本机并在路由转发前的数据包。它会转换数据包中的目标IP地址(destination ip address),通常用于DNAT(destination NAT)。POSTROUTING链 – 处理即将离开本机的数据包。它会转换数据包中的源IP地址(source ip address),通常用于SNAT(source NAT)。OUTPUT链 – 处理本机产生的数据包

  • filter表

    确定是否放行该数据包(过滤);其对应的内核模块为iptable_filter,表内包含三个链:INPUT、FORWARD、OUTPUT

    INPUT链 – 处理来自外部的数据。OUTPUT链 – 处理向外发送的数据。FORWARD链 – 将数据转发到本机的其他网卡设备上。

2.3 规则表之间的顺序

  • raw->mangle->nat->filter

  • 规则链之间的顺序

    • 入站:PREROUTING->INPUT
    • 出站:OUTPUT->POSTROUTING
    • 转发:PREROUTING->FORWARD->POSTROUTING
  • 规则链内的匹配顺序

    按顺序依次检查,匹配即停止(LOG策略例外),若找不到相匹配的规则,则按该链的默认策略处理

  • 表和链的关系:表下面是链,表容纳链

3、规则

根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,则由规则后面指定的处理动作进行处理

3.1 匹配条件

基本匹配条件

  • 源地址Source IP,目标地址 Destination IP

扩展匹配条件

  • 除了上述的条件可以用于匹配,还有很多其他的条件可以用于匹配,这些条件泛称为扩展条件,这些扩展条件其实也是netfilter中的一部分,只是以模块的形式存在,如果想要使用这些条件,则需要依赖对应的扩展模块。
  • 源端口Source Port, 目标端口Destination Port

3.2 处理动作

处理动作在iptables中被称为target,动作也可以分为基本动作和扩展动作。此处列出一些常用的动作

ACCEPT:允许数据包通过

DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应

REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息

SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题

MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上

DNAT:目标地址转换

REDIRECT:在本机做端口映射

LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配

二、iptables规则管理

1、iptables规则操作

1.1 iptables信息查询

# filter负责过滤功能,比如允许哪些IP地址访问,拒绝哪些IP地址访问,允许访问哪些端口,禁止访问哪些端口
# filter表会根据我们定义的规则进行过滤,filter表应该是我们最常用到的表了
# 下面两种都可以
# 默认不加-t就是指的filter表
iptables -t filter --list
iptables -t raw -L
iptables -t mangle -L
iptables -t nat -L

# -v是显示详细的信息,列出INPUT链的详细信息
iptables -vL INPUT
# 不让IP进行反解
iptables -nvL INPUT
# 显示规则的序号,--line-numbers选项表示显示规则的序号,注意,此选项为长选项,不能与其他短选项合并,不过此选项可以简写为--line
iptables --line-numbers -t 表名 -L
# 表示查看表中的所有规则,并且显示更详细的信息(-v选项),不过,计数器中的信息显示为精确的计数值,而不是显示为经过可读优化的计数值,-x选项表示显示计数器的精确值
iptables -t 表名 -v -x -L
# 可以合起来,不过-L在最后
iptables --line -t filter -nvxL INPUT

# -----------------------显示界面解释-----------------------
# Chain INPUT (policy ACCEPT 170M packets, 33G bytes)
# policy表示当前链的默认策略,policy ACCEPT表示INPUT的链的默认动作为ACCEPT,换句话说就是,默认接受通过INPUT关卡的所有请求,所以我们在配置INPUT链的具体规则时,应该将需要拒绝的请求配置到规则中
# 说白了就是”黑名单”机制,默认所有人都能通过,只有指定的人不能通过,当我们把INPUT链默认动作设置为接受(ACCEPT),就表示所有人都能通过这个关卡,此时就应该在具体的规则中指定需要拒绝的请求,就表示只有指定的人不能通过这个关卡,这就是黑名单机制
# packets表示当前链(上例为INPUT链)默认策略匹配到的包的数量,0 packets表示默认策略匹配到0个包。
# bytes表示当前链默认策略匹配到的所有包的大小总和。
# 其实,我们可以把packets与bytes称作”计数器”,上图中的计数器记录了默认策略匹配到的报文数量与总大小,”计数器”只会在使用-v选项时,才会显示出来

# pkts:对应规则匹配到的报文的个数。
# bytes:对应匹配到的报文包的大小总和。
# target:规则对应的target,往往表示规则对应的”动作”,即规则匹配成功后需要采取的措施。
# prot:表示规则对应的协议,是否只针对某些协议应用此规则。
# opt:表示规则对应的选项。
# in:表示数据包由哪个接口(网卡)流入,即从哪个网卡来。
# out:表示数据包将由哪个接口(网卡)流出,即到哪个网卡去。
# source:表示规则对应的源头地址,可以是一个IP,也可以是一个网段。
# destination:表示规则对应的目标地址。可以是一个IP,也可以是一个网段

1.2 规则添加

注意:添加规则时,规则的顺序非常重要,哪个先匹配就执行哪个,后面就算有一模一样的也不会执行

# 在指定表的指定链的尾部添加一条规则,-A选项表示在对应链的末尾添加规则,省略-t选项时,表示默认操作filter表中的规则
iptables -t 表名 -A 链名 匹配条件 -j 动作
# 举例,表示丢弃来自192.168.1.146的数据包
# 使用-s选项,指明”匹配条件”中的”源地址”,即如果报文的源地址属于-s对应的地址,那么报文则满足匹配条件,-s为source之意,表示源地址
iptables -t filter -A INPUT -s 192.168.1.146 -j DROP

# 在指定表的指定链的首部添加一条规则,-I选型表示在对应链的开头添加规则
iptables -t 表名 -I 链名 匹配条件 -j 动作
# 举例
iptables -t filter -I INPUT -s 192.168.1.146 -j ACCEPT

# 在指定表的指定链的指定位置添加一条规则
iptables -t 表名 -I 链名 规则序号 匹配条件 -j 动作
iptables -t filter -I INPUT 5 -s 192.168.1.146 -j REJECT

# 设置指定表的指定链的默认策略(默认动作),并非添加规则。
iptables -t 表名 -P 链名 动作
# 表示将filter表中FORWARD链的默认策略设置为ACCEPT
iptables -t filter -P FORWARD ACCEPT

1.3 规则删除

注意:如果没有保存规则,删除规则时请慎重

# 按照规则序号删除规则,删除指定表的指定链的指定规则,-D选项表示删除对应链中的规则
iptables -nvL --line-numbers
iptables -t 表名 -D 链名 规则序号
# 表示删除filter表中INPUT链中序号为3的规则
iptables -t filter -D INPUT 3

# 按照具体的匹配条件与动作删除规则,删除指定表的指定链的指定规则
iptables -t 表名 -D 链名 匹配条件 -j 动作
# 表示删除filter表中INPUT链中源地址为192.168.1.146并且动作为DROP的规则
iptables -t filter -D INPUT -s 192.168.1.146 -j DROP

# 删除指定表的指定链中的所有规则,-F选项表示清空对应链中的规则,执行时需三思
iptables -t 表名 -F 链名
iptables -t filter -F INPUT

# 删除指定表中的所有规则,执行时需三思
iptables -t 表名 -F
iptables -t filter -F

1.4 规则修改

注意:如果使用-R选项修改规则中的动作,那么必须指明原规则中的原匹配条件,例如源IP,目标IP等,如果不写明会变成默认,建议直接新增后删除

# 修改指定表中指定链的指定规则,-R选项表示修改对应链中的规则,使用-R选项时要同时指定对应的链以及规则对应的序号,并且规则中原本的匹配条件不可省略
iptables -t 表名 -R 链名 规则序号 规则原本的匹配条件 -j 动作
# 修改filter表中INPUT链的第3条规则,将这条规则的动作修改为ACCEPT, -s 192.168.1.146为这条规则中原本的匹配条件,如果省略此匹配条件,修改后的规则中的源地址可能会变为0.0.0.0/0
iptables -t filter -R INPUT 3 -s 192.168.1.146 -j ACCEPT
# 其他修改规则的方法:先通过编号删除规则,再在原编号位置添加一条规则

# 修改指定表的指定链的默认策略(默认动作),并非修改规则,可以使用如下命令
iptables -t 表名 -P 链名 动作
# 将filter表中FORWARD链的默认策略修改为ACCEPT
iptables -t filter -P FORWARD ACCEPT

1.5 规则保存

在默认的情况下,我们对"防火墙"所做出的修改都是"临时的",换句话说就是,当重启iptables服务或者重启服务器以后,我们平常添加的规则或者对规则所做出的修改都将消失,为了防止这种情况的发生,我们需要将规则"保存"

# centos6中,使用"service iptables save"命令即可保存规则,规则默认保存在/etc/sysconfig/iptables文件中
service iptables save
# 如果误操作了规则,但是并没有保存,那么使用service iptables restart命令重启iptables以后,规则会再次回到上次保存/etc/sysconfig/iptables文件时的模样
service iptables restart

# centos7中,已经不再使用init风格的脚本启动服务,而是使用unit文件
# 使用firewall替代了原来的iptables service,不过不用担心,我们只要通过yum源安装iptables与iptables-services即可(iptables一般会被默认安装,但是iptables-services在centos7中一般不会被默认安装)
#配置好yum源以后安装iptables-service
yum install -y iptables-services
#停止firewalld
systemctl stop firewalld
#禁止firewalld自动启动
systemctl disable firewalld
#启动iptables
systemctl start iptables
#将iptables设置为开机自动启动,以后即可通过iptables-service控制iptables服务
systemctl enable iptables
# 上述配置过程只需一次,以后即可在centos7中愉快的使用service iptables save命令保存iptables规则了


# 然后是ubuntu的安装
# 首先安装iptables-persistent工具
sudo apt install iptables-persistent
# 每当设置了新的iptables规则后,使用如下命令保存规则即可,规则会根据ipv4和ipv6分别保存在了/etc/iptables/rules.v4和/etc/iptables/rules.v6文件中
netfilter-persistent  save
# 由于 ipt­a­bles-per­sis­tent 在安装时已经把它作为一个服务设置为开机启动了,它在开机后会自动加载已经保存的规则,所以也就达到了永久保存的目的

最后是通用的方法,使用另一种方法保存iptables规则,就是使用iptables-save命令

# 使用iptables-save并不能保存当前的iptables规则,但是可以将当前的iptables规则以”保存后的格式”输出到屏幕上
# 我们可以使用iptables-save命令,再配合重定向,将规则重定向到/etc/sysconfig/iptables文件中即可
iptables-save > /etc/sysconfig/iptables

# 可以将/etc/sysconfig/iptables中的规则重新载入为当前的iptables规则,但是注意,未保存入/etc/sysconfig/iptables文件中的修改将会丢失或者被覆盖
# 使用iptables-restore命令可以从指定文件中重载规则
iptables-restore < /etc/sysconfig/iptables

2、iptables匹配条件

2.1 常用基本匹配条件

当规则中同时存在多个匹配条件时,多个条件之间默认存在"与"的关系,即报文必须同时满足所有条件,才能被规则匹配

# --------------------匹配条件:目标IP地址
# -s用于匹配报文的源地址,可以同时指定多个源地址,每个IP之间用逗号隔开,也可以指定为一个网段
# 逗号两侧均不能包含空格,多个IP之间必须与逗号相连
iptables -t filter -I INPUT -s 192.168.1.111,192.168.1.118 -j DROP
iptables -t filter -I INPUT -s 192.168.1.0/24 -j ACCEPT
# 只要发往本机的报文的源地址不是192.168.1.146,就接受报文
iptables -t filter -I INPUT ! -s 192.168.1.0/24 -j ACCEPT

# -d用于匹配报文的目标地址,可以同时指定多个目标地址,每个IP之间用逗号隔开,也可以指定为一个网段
# 所有IP发送往111,118的报文都将被丢弃
iptables -t filter -I OUTPUT -d 192.168.1.111,192.168.1.118 -j DROP
iptables -t filter -I INPUT -d 192.168.1.0/24 -j ACCEPT
# 不管是-s选项还是-d选项,取反操作与同时指定多个IP的操作不能同时使用
iptables -t filter -I INPUT ! -d 192.168.1.0/24 -j ACCEPT

# -------------------匹配条件:协议类型
# -p用于匹配报文的协议类型,可以匹配的协议类型tcp、udp、udplite、icmp、esp、ah、sctp等(centos7中还支持icmpv6、mh)
iptables -t filter -I INPUT -p tcp -s 192.168.1.146 -j ACCEPT
iptables -t filter -I INPUT ! -p udp -s 192.168.1.146 -j ACCEPT

# ---------------匹配条件:网卡接口
# -i用于匹配报文是从哪个网卡接口流入本机的,由于匹配条件只是用于匹配报文流入的网卡
# 所以在OUTPUT链与POSTROUTING链中不能使用此选项
# 拒绝由网卡eth4流入的ping请求报文
iptables -t filter -I INPUT -p icmp -i eth4 -j DROP
iptables -t filter -I INPUT -p icmp ! -i eth4 -j DROP

# -o用于匹配报文将要从哪个网卡接口流出本机,于匹配条件只是用于匹配报文流出的网卡,所以在INPUT链与PREROUTING链中不能使用此选项。
iptables -t filter -I OUTPUT -p icmp -o eth4 -j DROP
iptables -t filter -I OUTPUT -p icmp ! -o eth4 -j DROP

2.2 扩展匹配条件(基本)

基本匹配条件我们可以直接使用,而如果想要使用扩展匹配条件,则需要依赖一些扩展模块,或者说在使用扩展匹配条件之前,需要指定相应的扩展模块,使用-m 来选择扩展模块

# 常用的扩展匹配条件,tcp扩展模块
# -m tcp表示使用tcp扩展模块,–dport表示tcp扩展模块中的一个扩展匹配条件,可用于匹配报文的目标端口。
# 注意,-p tcp与 -m tcp并不冲突,-p用于匹配报文的协议,-m 用于指定扩展模块的名称,正好,这个扩展模块也叫tcp,那就可以省略
# 如果-p对应的值为udp,那么默认调用的扩展模块就为-m udp
# -p tcp -m tcp –sport 用于匹配tcp协议报文的源端口,可以使用冒号指定一个连续的端口范围
# -p tcp -m tcp –dport 用于匹配tcp协议报文的目标端口,可以使用冒号指定一个连续的端口范围
#示例如下
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22:25 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport :22 -j REJECT
# 匹配80号端口以及其以后的所有端口(直到65535)
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp --dport 80: -j REJECT
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPT


# multiport扩展模块
# -m multiport –dports 22,36,80表示使用了multiport扩展模块的–dports扩展条件,以同时指定了多个离散的端口,每个端口之间用逗号隔开
# -m multiport是不能省略的,如果你省略了-m multiport,就相当于在没有指定扩展模块的情况下,使用了扩展条件(”–dports”),那么上例中,iptables会默认调用”-m tcp”,但是,”–dports扩展条件”并不属于”tcp扩展模块”,而是属于”multiport扩展模块”,所以,这时就会报错
# -p tcp -m multiport –sports 用于匹配报文的源端口,可以指定离散的多个端口号,端口之间用”逗号”隔开
# -p udp -m multiport –dports 用于匹配报文的目标端口,可以指定离散的多个端口号,端口之间用”逗号”隔开
#示例如下
iptables -t filter -I OUTPUT -d 192.168.1.146 -p udp -m multiport --sports 137,138 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport ! --dports 22,80 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 80:88 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80:88 -j REJECT

2.3 扩展匹配条件(其他)

  • iprange模块

-s选项与-d选项并不能一次性的指定一段连续的IP地址范围,如果我们需要指定一段连续的IP地址范围,可以使用iprange扩展模块。使用iprange扩展模块可以指定"一段连续的IP地址范围",用于匹配报文的源地址或者目标地址

—src-range:指定连续的源地址范围

—dst-range:指定连续的目标地址范围

#示例
iptables -t filter -I INPUT -m iprange --src-range 192.168.1.127-192.168.1.146 -j DROP
iptables -t filter -I OUTPUT -m iprange --dst-range 192.168.1.127-192.168.1.146 -j DROP
iptables -t filter -I INPUT -m iprange ! --src-range 192.168.1.127-192.168.1.146 -j DROP
  • string模块

使用string扩展模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件,比如,如果报文中包含字符”OOXX”,我们就丢弃当前报文

—algo:指定对应的匹配算法,可用算法为bm、kmp,此选项为必需选项。

—string:指定需要匹配的字符串

# -m string表示使用string模块,–algo bm表示使用bm算法去匹配指定的字符串,–string"OOXX"则表示我们想要匹配的字符串为"OOXX"
iptables -t filter -I INPUT -p tcp --sport 80 -m string --algo bm --string "OOXX" -j REJECT
iptables -t filter -I INPUT -p tcp --sport 80 -m string --algo bm --string "OOXX" -j REJECT
  • time模块

我们可以通过time扩展模块,根据时间段区匹配报文,如果报文到达的时间在指定的时间范围以内,则符合匹配条件

—timestart:用于指定时间范围的开始时间,不可取反

—timestop:用于指定时间范围的结束时间,不可取反

—weekdays:用于指定”星期几”,可取反

—monthdays:用于指定”几号”,可取反

—datestart:用于指定日期范围的开始日期,不可取反

—datestop:用于指定日期范围的结束时间,不可取反

# "-m time"表示使用time扩展模块,–timestart选项用于指定起始时间,–timestop选项用于指定结束时间
# 每天早上9点到下午6点不能看网页
iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 443 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
# 只有周六日不能看网页
# 使用–weekdays选项可以指定每个星期的具体哪一天,可以同时指定多个,用逗号隔开,除了能够数字表示”星期几”,还能用缩写表示,例如:Mon, Tue, Wed, Thu, Fri, Sat, Sun
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --weekdays 6,7 -j REJECT
# 具体指定的每个月的哪一天
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time ! --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT
# 可以使用–datestart 选项与-datestop选项,指定具体的日期范围
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --datestart 2017-12-24 --datestop 2017-12-27 -j REJECT
  • connlimit 模块

使用connlimit扩展模块,可以限制每个IP地址同时链接到server端的链接数量,注意:我们不用指定IP,其默认就是针对"每个客户端IP",即对单IP的并发连接数限制

—connlimit-above:单独使用此选项时,表示限制每个IP的链接数量。

—connlimit-mask:此选项不能单独使用,在使用–connlimit-above选项时,配合此选项,则可以针对"某类IP段内的一定数量的IP"进行连接数量的限制,如果不明白可以参考上文的详细解释。

# 限制每个IP地址最多只能占用两个ssh链接远程到server端
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
# –connlimit-mask 24表示某个C类网段,没错,mask为掩码之意,所以将24转换成点分十进制就表示255.255.255.0
# 一个最多包含254个IP的C类网络中,同时最多只能有20个ssh客户端连接到当前服务器
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j REJECT
# –connlimit-mask 27表示某个C类网段,通过计算后可以得知,这个网段中最多只能有30台机器(30个IP),这30个IP地址最多只能有10个ssh连接同时连接到服务器端,当然,这样并不能避免某个IP占用所有连接的情况发生
# 假设,报文来自192.168.1.40这个IP,按照掩码为27进行计算,这个IP属于192.168.1.32/27网段,如果192.168.1.40同时占用了10个ssh连接,那么当192.168.1.51这个IP向服务端发起ssh连接请求时,同样会被拒绝,因为192.168.1.51这个IP按照掩码为27进行计算,也是属于192.168.1.32/27网段,所以他们共享这10个连接名额
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 --connlimit-mask 27 -j REJECT
# 在不使用–connlimit-mask的情况下,连接数量的限制是针对”每个IP”而言的,当使用了–connlimit-mask选项以后,则可以针对”某类IP段内的一定数量的IP”进行连接数量的限制
  • limit模块

connlimit模块是对连接数量进行限制的,limit模块是对"报文到达速率"进行限制的。用大白话说就是,如果我想要限制单位时间内流入的包的数量,就能用limit模块,我们可以以秒为单位进行限制,也可以以分钟、小时、天作为单位进行限制,比如,限制每秒中最多流入3个包,或者限制每分钟最多流入30个包都可以

—limit-burst:类比”令牌桶”算法,此选项用于指定令牌桶中令牌的最大数量,上文中已经详细的描述了”令牌桶”的概念,方便回顾

—limit:类比”令牌桶”算法,此选项用于指定令牌桶中生成新令牌的频率,可用时间单位有second、minute 、hour、day

#示例 #注意,如下两条规则需配合使用,具体原因上文已经解释过,忘记了可以回顾
# ”–limit-burst”可以指定”空闲时可放行的包的数量”,用了令牌桶的方法,所以前几个都会接收,后面满了才会按照指定速率
# 3/second表示每秒生成3个”令牌”,30/minute表示每分钟生成30个”令牌”
# 外部主机对本机进行ping操作时,本机最多每6秒中放行一个ping包
iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT
iptables -t filter -A INPUT -p icmp -j REJECT

2.4 扩展匹配条件tcp-flags

—tcp-flags指的就是tcp头中的标志位,看来,在使用iptables时,我们可以通过此扩展匹配条件,去匹配tcp报文的头部的标识位,然后根据标识位的实际情况实现访问控制的功能

# 复习之前的内容,这个也是tcp模块里的
# --sport用于匹配tcp协议报文的源端口,可以使用冒号指定一个连续的端口范围
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECT
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22:25 -j REJECT
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPT

# --dport 用于匹配tcp协议报文的目标端口,可以使用冒号指定一个连续的端口范围
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22:25 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport :22 -j REJECT
iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 80: -j REJECT

# --tcp-flags,用于匹配报文的tcp头的标志位
# 匹配到”第一次握手”的报文
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
# 匹配tcp头中的第二次握手时的标志位
iptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK -j REJECT
# 上两条命令的简写
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECT
iptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags ALL SYN,ACK -j REJECT

# --syn 用于匹配tcp新建连接的请求报文,相当于使用”–tcp-flags SYN,RST,ACK,FIN  SYN”
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --syn -j REJECT

2.5 udp扩展与icmp扩展

udp扩展模块,这个扩展模块中能用的匹配条件比较少,只有两个,就是–sport与–dport,即匹配报文的源端口与目标端口。

# 放行samba服务的137与138这两个UDP端口
iptables -t filter -I INPUT -p udp -m udp --dport 137 -j ACCEPT
iptables -t filter -I INPUT -p udp -m udp --dport 137:157 -j ACCEPT
#可以结合multiport模块指定多个离散的端口
# 但是udp中的–sport与–dport也只能指定连续的端口范围,并不能一次性指定多个离散的端口,使用之前总结过的multiport扩展模块,即可指定多个离散的UDP端口

ICMP协议的全称为Internet Control Message Protocol,翻译为互联网控制报文协议,它主要用于探测网络上的主机是否可用,目标是否可达,网络是否通畅,路由是否可用等。—icmp-type:匹配icmp报文的具体类型

我们平常使用ping命令ping某主机时,如果主机可达,对应主机会对我们的ping请求做出回应(此处不考虑禁ping等情况),也就是说,我们发出ping请求,对方回应ping请求,虽然ping请求报文与ping回应报文都属于ICMP类型的报文,但是如果在概念上细分的话,它们所属的类型还是不同的,我们发出的ping请求属于类型8的icmp报文,而对方主机的ping回应报文则属于类型0的icmp报文

# 要禁止所有icmp类型的报文进入本机
# 我们只想要ping通别人,但是不想让别人ping通我们
# –icmp-type 8/0表示icmp报文的type为8,code为0才会被匹配到,也就是只有ping请求类型的报文才能被匹配到
# 别人对我们发起的ping请求将会被拒绝通过防火墙,而我们之所以能够ping通别人,是因为别人回应我们的报文的icmp type为0,code也为0,所以无法被上述规则匹配到,所以我们可以看到别人回应我们的信息
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECT
# 因为type为8的类型下只有一个code为0的类型,所以我们可以省略对应的code
iptables -t filter -I INPUT -p icmp --icmp-type 8 -j REJECT
iptables -t filter -I OUTPUT -p icmp -m icmp --icmp-type 0/0 -j REJECT
iptables -t filter -I OUTPUT -p icmp --icmp-type 0 -j REJECT
# 除了能够使用对应type/code匹配到具体类型的icmp报文以外,我们还能用icmp报文的描述名称去匹配对应类型的报文
iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT

2.6 state扩展

state模块可以让iptables实现"连接追踪"机制,对于state模块而言的"连接"并不能与tcp的"连接"画等号,在TCP/IP协议簇中,UDP和ICMP是没有所谓的连接的,但是对于state模块来说,tcp报文、udp报文、icmp报文都是有连接状态的,我们可以这样认为,对于state模块而言,只要两台机器在"你来我往"的通信,就算建立起了连接,其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED

  • NEW:连接中的第一个包,状态就是NEW,我们可以理解为新连接的第一个包的状态为NEW。
  • ESTABLISHED:我们可以把NEW状态包后面的包的状态理解为ESTABLISHED,表示连接已建立。
  • RELATED:从字面上理解RELATED译为关系,但是这样仍然不容易理解,我们举个例子,比如FTP服务,FTP服务端会建立两个进程,一个命令进程,一个数据进程。命令进程负责服务端与客户端之间的命令传输(我们可以把这个传输过程理解成state中所谓的一个"连接",暂称为"命令连接")。数据进程负责服务端与客户端之间的数据传输 ( 我们把这个过程暂称为"数据连接" )。但是具体传输哪些数据,是由命令去控制的,所以,"数据连接"中的报文与"命令连接"是有关系的。那么,"数据连接"中的报文可能就是RELATED状态,因为这些报文与"命令连接"中的报文有关系。(注:如果想要对ftp进行连接追踪,需要单独加载对应的内核模块nf_conntrack_ftp,如果想要自动加载,可以配置/etc/sysconfig/iptables-config文件)
  • INVALID:如果一个包没有办法被识别,或者这个包没有任何状态,那么这个包的状态就是INVALID,我们可以主动屏蔽状态为INVALID的报文。
  • UNTRACKED:报文的状态为untracked时,表示报文未被追踪,当报文的状态为Untracked时通常表示无法找到相关的连接。
# 只要放行状态为ESTABLISHED的报文即可,因为如果报文的状态为ESTABLISHED,那么报文肯定是之前发出的报文的回应
# 如果你还不放心,可以将状态为RELATED或ESTABLISHED的报文都放行,这样,就表示只有回应我们的报文能够通过防火墙,如果是别人主动发送过来的新的报文,则无法通过防火墙
# 这样就可以保证主机安全
iptables -F
iptables -t filter -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT -j REJECT
# 当前主机IP为104,当放行ESTABLISHED与RELATED状态的包以后,并没有影响通过本机远程ssh到IP为77的主机上,但是无法从77上使用22端口主动连接到104上
# 对于其他端口与IP来说,也是相同的,可以从104主动发送报文,并且能够收到响应报文,但是其他主机并不能主动向104发起请求。

# 现在更推荐conntrack代替state的,不过两者都能使用,区别不大
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -m conntrack --ctstate NEW -m tcp --dport 22 -j ACCEPT

2.7 mac扩展

# mac扩展用来匹配某个mac地址
# 用法 -m mac --mac-source MAC
# 阻断来自某MAC地址的数据包通过本机
iptables -A FORWARD -m mac --mac-source xx:xx:xx:xx -j DROP
# 注意
# 报文经过路由后,数据包中原有的mac信息会被替换,所以在路由后的iptables中使用mac模块是没有意义的

三、iptables进阶与提高

1、iptables的黑白名单机制

报文在经过iptables的链时,会匹配链中的规则,遇到匹配的规则时,就执行对应的动作,如果链中的规则都无法匹配到当前报文,则使用链的默认策略(默认动作),链的默认策略通常设置为ACCEPT或者DROP

那么,当链的默认策略设置为ACCEPT时,如果对应的链中没有配置任何规则,就表示接受所有的报文,如果对应的链中存在规则,但是这些规则没有匹配到报文,报文还是会被接受。同理,当链的默认策略设置为DROP时,如果对应的链中没有配置任何规则,就表示拒绝所有报文,如果对应的链中存在规则,但是这些规则没有匹配到报文,报文还是会被拒绝。

  • 黑名单机制:当链的默认策略为ACCEPT时,链中的规则对应的动作应该为DROP或者REJECT,表示只有匹配到规则的报文才会被拒绝,没有被规则匹配到的报文都会被默认接受
  • 白名单机制:当链的默认策略为DROP时,链中的规则对应的动作应该为ACCEPT,表示只有匹配到规则的报文才会被放行,没有被规则匹配到的报文都会被默认拒绝
# 白名单机制
iptables -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
# 将INPUT链的默认策略改为DROP
iptables -nvL INPUT
iptables -P INPUT DROP


# 如果此时iptables -F清空了的话,那么将拒绝所有请求
# 这就是默认策略设置为DROP的缺点,在对应的链中没有设置任何规则时,这样使用默认策略为DROP是非常不明智的,因为管理员也会把自己拒之门外
# 所以,我们如果想要使用”白名单”的机制,最好将链的默认策略保持为”ACCEPT”,然后将”拒绝所有请求”这条规则放在链的尾部,将”放行规则”放在前面
# 这样做,既能实现”白名单”机制,又能保证在规则被清空时,管理员还有机会连接到主机
iptables -P INPUT ACCEPT
# 当所有放行规则设置完成后,在INPUT链的尾部,设置一条拒绝所有请求的规则
iptables -A INPUT -j REJECT

2、iptables自定义链

自定义链可以方便的管理不同的规则,方便后期规则的修改,但是需要注意的是,自定义链并不能直接使用,而是需要被默认链引用才能够使用

# 创建自定义链
#示例:在filter表中创建IN_WEB自定义链,省略-t选项时,缺省操作的就是filter表
iptables -t filter -N IN_WEB
# 可以看到,这条自定义链的引用计数为0 (0 references),就是说,这条自定义链还没有被任何默认链所引用
iptables -nvL

# 自定义链中配置规则,和其他一样
iptables -t filter -I IN_WEB -s 192.168.1.139 -j REJECT
iptables -I IN_WEB -s 192.168.1.188 -j REJECT
iptables -t filter --line -nvL IN_WEB


# 引用自定义链
#示例:在INPUT链中引用刚才创建的自定义链
iptables -t filter -I INPUT -p tcp --dport 80 -j IN_WEB

# 重命名自定义链
#示例:将IN_WEB自定义链重命名为WEB
iptables -E IN_WEB WEB

# 删除自定义链
# 删除自定义链需要满足两个条件:自定义链没有被引用;自定义链中没有任何规则
#示例:删除引用计数为0并且不包含任何规则的WEB链
iptables -D INPUT 1
iptables -t filter -F WEB
# 使用”-X”选项可以删除一个引用计数为0的、空的自定义链
iptables -X WEB

3、iptables之网络防火墙

3.1 概述

网络防火墙: 往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网(有点类似路由器),网络防火墙往往处于网络的入口或者边缘,那么,如果想要使用iptables充当网络防火墙,iptables所在的主机则需要处于网络入口处。

不管是由外部主机发往内部主机的报文,还是由内部主机发往外部主机的报文,都需要经过iptables所在的主机,由iptables所在的主机进行"过滤并转发",所以,防火墙主机的主要工作就是"过滤并转发"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOPMRPW4-1680865857920)(http://qnypic.shawncoding.top/blog/%E8%BD%AC%E5%8F%91%E5%9B%BE_ziB0kUlrCp.png)]

前文中,iptables都是作为**“主机防火墙”**的角色出现的,所以我们举例时,只用到了上图中的INPUT链与OUTPUT链,因为拥有"过滤功能"的链只有3条,INPUT、OUTPUT、FORWARD,当报文发往本机时,如果想要过滤,只能在INPUT链与OUTPUT链中实现,而此时,iptables的角色发生了转变,我们想要将iptables所在的主机打造成"网络防火墙",而刚才已经说过,网络防火墙的职责就是"过滤并转发",要想"过滤",只能在INPUT、OUTPUT、FORWARD三条链中实现,要想"转发",报文则只会经过FORWARD链(发往本机的报文才会经过INPUT链),所以,综上所述,iptables的角色变为"网络防火墙"时,规则只能定义在FORWARD链中。

3.2 实战demo

此处所描述的内网、外网与我们平常所说的公网、私网不同。此处描述的内外部网络你可以理解成两个网段,A网络与B网络,为了方便描述,我们把圆形内的主机称为内部主机,把上图中圆形所表示的网络称为内部网络,把圆形外的网络称为外部网络。

ifconfig | awk '/inet/{print $1,$2}'
# route命令配置的路由条目在网络重启后将会失效
# 现在A主机通往10.1网络的网关已经指向了B主机
# 因为A发往内网的网关是默认的,所以再加一个从内网到A的默认网关即可
route add -net 10.1.0.0/16 gw 192.168.1.146
route -n
# 如果A ping 10.1.0.3会有反应,因为这两个网卡都是它自己,故会反应
# 但ping内网中的其他机器就不会有回应了,因为还没配置规则

# -----------------------开启转发----------------------------

#如果想要iptables作为网络防火墙,iptables所在主机开启核心转发功能,以便能够转发报文。
#使用如下命令查看当前主机是否已经开启了核心转发,0表示未开启,1表示已开启
cat /proc/sys/net/ipv4/ip_forward
#使用如下两种方法均可临时开启核心转发,立即生效,但是重启网络配置后会失效。
方法一:echo 1 > /proc/sys/net/ipv4/ip_forward
方法二:sysctl -w net.ipv4.ip_forward=1

#使用如下方法开启核心转发功能,重启网络服务后永久生效。
# 配置/etc/sysctl.conf文件(centos7中配置/usr/lib/sysctl.d/00-system.conf文件),在配置文件中将 net.ipv4.ip_forward设置为1
# ubuntu中
# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p
# 总之原理就是把net.ipv4.ip_forward = 1开启
# 这样内外网都可以ping通了

# -------------------------转发规则------------------------------
#由于iptables此时的角色为"网络防火墙",所以需要在filter表中的FORWARD链中设置规则。
#可以使用"白名单机制",先添加一条默认拒绝的规则,然后再为需要放行的报文设置规则。
#配置规则时需要考虑"方向问题",针对请求报文与回应报文,考虑报文的源地址与目标地址,源端口与目标端口等。
#示例为允许网络内主机访问网络外主机的web服务与sshd服务
# 白名单机制,先添加最后一个为拒绝
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -d 10.1.0.0/16 -p tcp --sport 22 -j ACCEPT
 
#可以使用state扩展模块,对上述规则进行优化,使用如下配置可以省略许多"回应报文放行规则"。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -s 10.1.0.0/16 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

4、iptables动作总结

4.1 常用动作之REJECT

之前用到了一些常用动作,比如ACCEPT、DROP、REJECT等。"动作"与"匹配条件"一样,也有"基础"与"扩展"之分。同样,使用扩展动作也需要借助扩展模块,但是,扩展动作可以直接使用,不用像使用"扩展匹配条件"那样指定特定的模块。之前用到的ACCEPT与DROP都属于基础动作;而REJECT则属于扩展动作。

# -----------------------------动作REJECT----------------
# REJECT动作的常用选项为--reject-with,使用--reject-with选项,可以设置提示信息,当对方被拒绝时,会提示对方为什么被拒绝
# 可用值如下
# icmp-net-unreachable
# icmp-host-unreachable
# icmp-port-unreachable
# icmp-proto-unreachable
# icmp-net-prohibited
# icmp-host-pro-hibited
# icmp-admin-prohibited
# 当不设置任何值时,默认值为icmp-port-unreachable

iptables -F
iptables -t filter -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -j REJECT
iptables -nvL INPUT
# 当没有明确设置–reject-with的值时,默认提示信息为icmp-port-unreachable,即端口不可达之意

# 修改拒绝报文,发ping就会显示主机不可达
iptables -I INPUT 2 -j REJECT --reject-with icmp-host-unreachable

4.2 常用动作之LOG

使用LOG动作,可以将符合条件的报文的相关信息记录到日志中,但当前报文具体是被"接受",还是被"拒绝",都由后面的规则控制,换句话说,LOG动作只负责记录匹配到的报文的相关信息,不负责对报文的其他处理,如果想要对报文进行进一步的处理,可以在之后设置具体规则,进行进一步的处理。

# 举例
iptables -F
# 将发往22号端口的报文相关信息记录在日志中
iptables -I INPUT -p tcp --dport 22 -j LOG
# 都会被记录到日志中,查看/var/log/messages即可看到对应报文的相关信息
tail -f /var/log/messages
# 但匹配条件过于宽泛,所以在使用LOG动作时,匹配条件应该尽量写的精确一些,先删除这条

# 当然,我们也可以将相关信息记录在指定的文件中,以防止iptables的相关信息与其他日志信息相混淆
# 修改/etc/rsyslog.conf文件(或者/etc/syslog.conf),在rsyslog配置文件中添加如下配置即可
vim /etc/rsyslog.conf
# 末尾添加
kern.warning /var/log/iptables.log
# 加入上述配置后,报文的相关信息将会被记录到/var/log/iptables.log文件中
# 完成上述配置后,重启rsyslog服务(或者syslogd)
service rsyslog restart


# LOG动作也有自己的选项,常用选项如下
# --log-level选项可以指定记录日志的日志级别,可用级别有emerg,alert,crit,error,warning,notice,info,debug
# –-log-prefix选项可以给记录到的相关信息添加”标签”之类的信息,以便区分各种记录到的报文信息,方便在分析时进行过滤
# 注:-–log-prefix对应的值不能超过29个字符
# 举例将主动连接22号端口的报文的相关信息都记录到日志中,并且把这类记录命名为want-in-from-port-22
iptables -F INPUT
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -j LOG --log-prefix "want-in-from-port-22"

# 可以连接ssh进行测试,查看iptables.log日志,发现日志中有标签,还有网卡信息,时间等

4.3 NAT相关动作(重要)

图中圆形所示的逻辑区域表示公司内网,网段为10.1.0.0/16,主机B、C、D都属于内网主机,主机B比较特殊,同时扮演了网关与防火墙,主机B持有公司唯一的公网IP(我们用了一个假的公网IP),局域网内主机如果想与公网主机通讯,需要共享此公网IP,由B主机进行NAT,所以,我们为主机B准备了两块网卡,公网IP与私网IP分别配置到这两块网卡中

# 如果想要NAT功能能够正常使用,需要开启Linux主机的核心转发功能。
# -----------------------开启转发----------------------------
#使用如下命令查看当前主机是否已经开启了核心转发,0表示未开启,1表示已开启
cat /proc/sys/net/ipv4/ip_forward
#使用如下两种方法均可临时开启核心转发,立即生效,但是重启网络配置后会失效。
方法一:echo 1 > /proc/sys/net/ipv4/ip_forward
方法二:sysctl -w net.ipv4.ip_forward=1
#使用如下方法开启核心转发功能,重启网络服务后永久生效。
# 配置/etc/sysctl.conf文件(centos7中配置/usr/lib/sysctl.d/00-system.conf文件),在配置文件中将 net.ipv4.ip_forward设置为1
# ubuntu中
# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p

# -------------------SNAT相关操作----------------------
# 网络内部的主机可以借助SNAT隐藏自己的IP地址,同时还能够共享合法的公网IP,让局域网内的多台主机共享公网IP访问互联网
# 而此时的主机B就扮演了拥有NAT功能的设备,我们使用iptables的SNAT动作达到刚才所说的目的
# 我们将来自于10.1.0.0/16网段的报文的源地址改为公司的公网IP地址
# -t nat表示操作nat表,我们之前一直在灌输一个概念,就是不同的表有不同的功能,filter表的功能是过滤,nat表的功能就是地址转换,所以我们需要在nat表中定义nat规则。
# -A POSTROUTING表示将SNAT规则添加到POSTROUTING链的末尾,在centos7中,SNAT规则只能存在于POSTROUTING链与INPUT链中,在centos6中,SNAT规则只能存在于POSTROUTING链中
# -s 10.1.0.0/16表示报文来自于10.1.0.0/16网段
# -j SNAT表示使用SNAT动作,对匹配到的报文进行处理,对匹配到的报文进行源地址转换
# –to-source 192.168.1.146表示将匹配到的报文的源IP修改为192.168.1.146,我们已经总结过,某些动作会有自己的选项,–to-source就是SNAT动作的常用选项,用于指定SNAT需要将报文的源IP修改为哪个IP地址
# 只是用于配置SNAT的话,我们并不用 手动的进行DNAT设置,iptables会自动维护NAT表,并将响应报文的目标地址转换回来
# 内外网可以相互ping通,iptables自动维护转换表

# 配置SNAT,可以隐藏网内主机的IP地址,也可以共享公网IP,访问互联网,如果只是共享IP的话,只配置如下SNAT规则即可
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP

# ---------------------------------动作MASQUERADE-----------------------------
# MASQUERADE和SNAT类似,也就是源地址转换
# MASQUERADE会动态的将源地址转换为可用的IP地址,其实与SNAT实现的功能完全一致,都是修改源地址
# 只不过SNAT需要指明将报文的源地址改为哪个IP,而MASQUERADE则不用指定明确的IP,会动态的将报文的源地址修改为指定网卡上可用的IP地址
# 通过外网网卡出去的报文在经过POSTROUTING链时,会自动将报文的源地址修改为外网网卡上可用的IP地址,这时,即使外网网卡中的公网IP地址发生了改变,也能够正常的、动态的将内部主机的报文的源IP映射为对应的公网IP
# 可以把MASQUERADE理解为动态的、自动化的SNAT,如果没有动态SNAT的需求,没有必要使用MASQUERADE,因为SNAT更加高效

# 如果公网IP是动态获取的,不是固定的,则可以使用MASQUERADE进行动态的SNAT操作,如下命令表示将10.1网段的报文的源IP修改为eth0网卡中可用的地址
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE

# ------------------------------DNAT相关操作---------------------------
# 配置DNAT,可以通过公网IP访问局域网内的服务
# -t nat -I PREROUTING表示在nat表中的PREROUTING链中配置DNAT规则,DNAT规则只配置在PREROUTING链与OUTPUT链中。
# 注:理论上来说,只要配置DNAT规则,不需要对应的SNAT规则即可达到DNAT效果
# 但是在测试DNAT时,对应SNAT规则也需要配置,才能正常DNAT,可以先尝试只配置DNAT规则
# 如果无法正常DNAT,再尝试添加对应的SNAT规则,SNAT规则配置一条即可,DNAT规则需要根据实际情况配置不同的DNAT规则
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 公网端口 -j DNAT --to-destination 私网IP:端口号
iptables -t nat -I PREROUTING -d 公网IP -p tcp --dport 8080 -j DNAT --to-destination 10.1.0.1:80
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP

# -------------------------------动作REDIRECT--------------------
# 使用REDIRECT动作可以在本机上进行端口映射
# REDIRECT规则只能定义在PREROUTING链或者OUTPUT链中
# 在本机进行目标端口映射时可以使用REDIRECT动作
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
# 配置完成上述规则后,其他机器访问本机的80端口时,会被映射到8080端口

四、总结

1、配置应用程序规则举例

1.1 SSH

#-m state: 启用状态匹配模块(state matching module)
#–-state: 状态匹配模块的参数。当SSH客户端第一个数据包到达服务器时,状态字段为NEW;建立连接后数据包的状态字段都是ESTABLISHED
#–sport 22: sshd监听22端口,同时也通过该端口和客户端建立连接、传送数据。因此对于SSH服务器而言,源端口就是22
#–dport 22: ssh客户端程序可以从本机的随机端口与SSH服务器的22端口建立连接。因此对于SSH客户端而言,目的端口就是22
# 1.允许接收远程主机的SSH请求
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
# 2.允许发送本地主机的SSH响应
iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
# 如果服务器也需要使用SSH连接其他远程主机,则还需要增加以下配置

# 1.送出的数据包目的端口为22
iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
# 2.接收的数据包源端口为22
iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

1.2 HTTP

# 1.删除现有规则
iptables -F

# 2.配置默认链策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# 3.允许远程主机进行SSH连接
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

# 4.允许本地主机进行SSH连接
iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

# 5.允许HTTP请求
iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

# 配置转发端口示例
iptables -t nat -I PREROUTING -p tcp --dport 3389 -j DNAT --to 38.X25.X.X02 
iptables -t nat -I POSTROUTING -p tcp --dport 3389 -j MASQUERADE

1.3 NAT规则实战

# 把本地的mysql 3306端口映射出去变成63306,外面连接的语句是
# 注:当访问63306的时候,会自动去请求3306,然后返回数据
mysql -uroot -p'password' -h xxxxx -P 63306

# 先允许数据包转发
echo 1 >/proc/sys/net/ipv4/ip_forward
# 注:这是允许所有外来的IP访问,慎用
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 63306 -j DNAT --to-destination 127.0.0.1:3306
# 修改规则(4代表编号, --line-number可查看对应编号, -s 指定来源IP)
iptables -t nat -R PREROUTING 4 -s 192.168.40.154 -p tcp -m tcp --dport 63306 -j DNAT --to-destination 127.0.0.1:3306
# 查看nat规则
iptables -L -t nat --line-number

2、iptables常用套路小结

  • 规则的顺序非常重要

    如果报文已经被前面的规则匹配到,IPTABLES则会对报文执行对应的动作,通常是ACCEPT或者REJECT,报文被放行或拒绝以后,即使后面的规则也能匹配到刚才放行或拒绝的报文,也没有机会再对报文执行相应的动作了(前面规则的动作为LOG时除外),所以,针对相同服务的规则,更严格的规则应该放在前面

  • 当规则中有多个匹配条件时,条件之间默认存在"与"的关系

    如果一条规则中包含了多个匹配条件,那么报文必须同时满足这个规则中的所有匹配条件,报文才能被这条规则匹配到。

  • 在不考虑1的情况下,应该将更容易被匹配到的规则放置在前面

    比如,你写了两条规则,一条针对sshd服务,一条针对web服务。假设,一天之内,有20000个请求访问web服务,有200个请求访问sshd服务,那么,应该将针对web服务的规则放在前面,针对sshd的规则放在后面,因为访问web服务的请求频率更高。如果将sshd的规则放在前面,当报文是访问web服务时,sshd的规则也要白白的验证一遍,由于访问web服务的频率更高,白白耗费的资源就更多;如果web服务的规则放在前面,由于访问web服务的频率更高,所以无用功会比较少。换句话说就是,在没有顺序要求的情况下,不同类别的规则,被匹配次数多的、匹配频率高的规则应该放在前面。

  • 当IPTABLES所在主机作为网络防火墙时,在配置规则时,应着重考虑方向性,双向都要考虑,从外到内,从内到外。

  • 在配置IPTABLES白名单时,往往会将链的默认策略设置为ACCEPT,通过在链的最后设置REJECT规则实现白名单机制,而不是将链的默认策略设置为DROP,如果将链的默认策略设置为DROP,当链中的规则被清空时,管理员的请求也将会被DROP掉。


参考文章:

https://www.zsythink.net/archives/tag/iptables/

https://zhuanlan.zhihu.com/p/279919870

https://zhuanlan.zhihu.com/p/465319846

https://www.cnblogs.com/hellowangbucuo/p/9617282.html
服务时,sshd的规则也要白白的验证一遍,由于访问web服务的频率更高,白白耗费的资源就更多;如果web服务的规则放在前面,由于访问web服务的频率更高,所以无用功会比较少。换句话说就是,在没有顺序要求的情况下,不同类别的规则,被匹配次数多的、匹配频率高的规则应该放在前面。

  • 当IPTABLES所在主机作为网络防火墙时,在配置规则时,应着重考虑方向性,双向都要考虑,从外到内,从内到外。
  • 在配置IPTABLES白名单时,往往会将链的默认策略设置为ACCEPT,通过在链的最后设置REJECT规则实现白名单机制,而不是将链的默认策略设置为DROP,如果将链的默认策略设置为DROP,当链中的规则被清空时,管理员的请求也将会被DROP掉。

参考文章:

https://www.zsythink.net/archives/tag/iptables/

https://zhuanlan.zhihu.com/p/279919870

https://zhuanlan.zhihu.com/p/465319846

https://www.cnblogs.com/hellowangbucuo/p/9617282.html

  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值