0%

iptables使用教程

0. 前言

0.0 防火墙

  • 从逻辑上讲,防火墙可以大体分为主机防火墙和网络防火墙。

    • 主机防火墙:针对于单个主机进行防护。

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

    网络防火墙和主机防火墙并不冲突,可以理解为,网络防火墙主外(集体), 主机防火墙主内(个人)。

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

0.1 iptables

iptables其实不是真正的防火墙,我们可以把它理解成一个客户端代理,用户通过iptables这个代理,将用户的安全设定执行到对应的”安全框架”中,这个”安全框架”才是真正的防火墙,这个框架的名字叫netfilter

netfilter才是防火墙真正的安全框架(framework),netfilter位于内核空间。iptables其实是一个命令行工具,位于用户空间,我们用这个工具操作真正的框架。

netfilter/iptables(下文中简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。

0.2 netfilter

netfilter是Linux操作系统核心层内部的一个数据包处理模块,它具有如下功能:

  • 网络地址转换(Network Address Translate)
  • 数据包内容修改
  • 以及数据包过滤的防火墙功能

所以说,虽然我们使用service iptables start启动iptables”服务”,但是其实准确的来说,iptables并没有一个守护进程,所以并不能算是真正意义上的服务,而应该算是内核提供的功能。

1. iptables基础

我们知道iptables是按照规则来办事的,我们就来说说规则(rules),规则其实就是网络管理员预定义的条件,规则一般的定义为”如果数据包头符合这样的条件,就这样处理这个数据包”。

规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。

当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。

1.1 五链

1

  • PREROUTING 数据包刚进入网络层 , 路由之前
  • INPUT 路由判断,流入用户空间
  • OUTPUT 用户空间发出,后接路由判断出口的网络接口
  • FORWARD 路由判断不进入用户空间,只进行转发
  • POSTROUTING 数据包通过网络接口出去
1.1.1 举例:

到本机某进程的报文:PREROUTING –> INPUT

由本机转发的报文:PREROUTING –> FORWARD –> POSTROUTING

由本机的某进程发出报文(通常为响应报文):OUTPUT –> POSTROUTING

1.2 四表

我们把具有相同功能的规则的集合叫做”表”,所以说,不同功能的规则,我们可以放置在不同的表中进行管理,而iptables已经为我们定义了4种表,每种表对应了不同的功能,而我们定义的规则也都逃脱不了这4种功能的范围,所以,学习iptables之前,我们必须先搞明白每种表 的作用。

  • filter表:负责过滤功能,防火墙;内核模块:iptables_filter
  • nat表:network address translation,网络地址转换功能;内核模块:iptable_nat
  • mangle表:拆解报文,做出修改,并重新封装 的功能;iptable_mangle
  • raw表:关闭nat表上启用的连接追踪机制;iptable_raw

也就是说,我们自定义的所有规则,都是这四种分类中的规则,或者说,所有规则都存在于这4张”表”中。

1.3 表链关系

四表/五链PREROUTINGINPUTFORWARDOUTPUTPOSTROUTING
filter
nat√(centos7)
mangle
raw

表的优先级关系: raw –> mangle –> nat –> filter , raw 最高

1

1

2. 规则

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

2.1 匹配条件

匹配条件分为基本匹配条件与扩展匹配条件

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

2.2 处理动作

处理动作在iptables中被称为target(这样说并不准确,我们暂且这样称呼),动作也可以分为基本动作和扩展动作。
此处列出一些常用的动作,之后的文章会对它们进行详细的示例与总结:

  • ACCEPT:允许数据包通过。
  • DROP:直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求泥牛入海了,过了超时时间才会有反应。
  • REJECT:拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息。
  • SNAT:源地址转换,解决内网用户用同一个公网地址上网的问题。
  • MASQUERADE:是SNAT的一种特殊形式,适用于动态的、临时会变的ip上。
  • DNAT:目标地址转换。
  • REDIRECT:在本机做端口映射。
  • LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配。

补充一下DROP和REJECT的区别。DROP是直接把匹配到的报文丢弃,REJECT除了把报文丢弃还会给该报文中的源IP发一个ICMP报文说明目的不可达(直接回复不可达, 更强硬)。前者报文发送方只能等超时,而后者发送方因为收到了ICMP不可达所以马上就给出了提示。

3. filter过滤规则

filter负责过滤功能,比如允许哪些IP地址访问,拒绝哪些IP地址访问,允许访问哪些端口,禁止访问哪些端口,filter表会根据我们定义的规则进行过滤,filter表应该是我们最常用到的表了。

3.1 查看规则

怎样查看filter表中的规则呢?使用如下命令即可查看。

1
iptables -t filter -L

刚才提到,我们可以使用iptables -t filter -L命令列出filter表中的所有规则,那么举一反三,我们也可以查看其它表中的规则,示例如下。

1
2
3
iptables -t raw -L
iptables -t mangle -L
iptables -t nat -L

其实,我们可以省略-t filter,当没有使用-t选项指定表时,默认为操作filter表,即iptables -L表示列出filter表中的所有规则。

3.2 详细信息

我们还可以只查看指定表中的指定链的规则,比如,我们只查看filter表中INPUT链的规则,示例如下(注意大小写)。

1
2
3
4
5
6
# iptables --line-numbers  -nvL INPUT
Chain INPUT (policy ACCEPT 14M packets, 2062M bytes)
num pkts bytes target prot opt in out source destination
1 2697K 114M KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW /* kubernetes service portals */
2 2697K 114M KUBE-EXTERNAL-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW /* kubernetes externally-visible service portals */
3 906M 477G KUBE-FIREWALL all -- * * 0.0.0.0/0 0.0.0.0/0
  • 头含义

    上图中INPUT链后面的括号中包含policy ACCEPT ,0 packets,0bytes 三部分。

    1
    2
    3
    policy:表示当前链的默认策略,policy ACCEPT表示上图中INPUT的链的默认动作为ACCEPT
    packets:表示当前链(上例为INPUT链)默认策略匹配到的包的数量,0 packets表示默认策略匹配到0个包。
    bytes:表示当前链默认策略匹配到的所有包的大小总和。

    其实,我们可以把packets与bytes称作”计数器”,上图中的计数器记录了默认策略匹配到的报文数量与总大小,”计数器”只会在使用-v选项时,才会显示出来。

  • 字段含义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    pkts:对应规则匹配到的报文的个数。
    bytes:对应匹配到的报文包的大小总和。
    target:规则对应的target,往往表示规则对应的"动作",即规则匹配成功后需要采取的措施。
    prot:表示规则对应的协议,是否只针对某些协议应用此规则。
    opt:表示规则对应的选项。
    in:表示数据包由哪个接口(网卡)流入,我们可以设置通过哪块网卡流入的报文需要匹配当前规则。
    out:表示数据包由哪个接口(网卡)流出,我们可以设置通过哪块网卡流出的报文需要匹配当前规则。
    source:表示规则对应的源头地址,可以是一个IP,也可以是一个网段。
    destination:表示规则对应的目标地址。可以是一个IP,也可以是一个网段。

3.3 增加规则

为了准备一个从零开始的环境,使用iptables -F INPUT命令清空filter表INPUT链中的规则。

1
2
3
root@tencent:~# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 215 packets, 16538 bytes)
pkts bytes target prot opt in out source destination

清空INPUT链以后,filter表中的INPUT链已经不存在任何的规则,但是可以看出,INPUT链的默认策略是ACCEPT,也就是说,INPUT链默认”放行”所有发往本机的报文,当没有任何规则时,会接受所有报文,当报文没有被任何规则匹配到时,也会默认放行报文。

  • 增加
1
iptables -t filter -I INPUT -s 123.117.179.97 -j DROP

在目标服务器增加一条本地的 ip, 发现已经 ping不通了.

上图中,使用 -t选项指定了要操作的表,此处指定了操作filter表,与之前的查看命令一样,不使用-t选项指定表时,默认为操作filter表。
使用-I选项,指明将”规则”插入至哪个链中,-I表示insert,即插入的意思,所以-I INPUT表示将规则插入于INPUT链中,即添加规则之意。

使用-s选项,指明”匹配条件”中的”源地址”,即如果报文的源地址属于-s对应的地址,那么报文则满足匹配条件,-s为source之意,表示源地址。

使用-j选项,指明当”匹配条件”被满足时,所对应的动作,上例中指定的动作为DROP,在上例中,当报文的源地址为223.70.253.1时,报文则被DROP(丢弃)。

  • 查看

再次查看filter表中的INPUT链,发现规则已经被添加了,在iptables中,动作被称之为”target”,所以,上图中taget字段对应的动作为DROP。

1
2
3
4
root@tencent:~# iptables -vL INPUT
Chain INPUT (policy ACCEPT 2043 packets, 135K bytes)
pkts bytes target prot opt in out source destination
66 9796 DROP all -- any any 123.117.179.97 anywhere

注意看, 可以看到 bytes 的字节数, 说明已经匹配上了.

  • 顺序

规则的顺序很重要。

如果报文已经被前面的规则匹配到,iptables则会对报文执行对应的动作,即使后面的规则也能匹配到当前报文,很有可能也没有机会再对报文执行相应的动作。

3.4 删除规则

此刻,如果我们想要删除filter表中INPUT中的一条规则,该怎么做呢?有两种办法
方法一:根据规则的编号去删除规则
方法二:根据具体的匹配条件与动作删除规则

1
2
3
4
5
6
7
8
9
10
11
12
13
# 添加两种
iptables -t filter -A INPUT -s 1.1.1.1 -j DROP
iptables -t filter -A INPUT -s 1.1.1.2 -j DROP


iptables --line -nvL INPUT
3 0 0 DROP all -- * * 1.1.1.1 0.0.0.0/0
4 0 0 DROP all -- * * 1.1.1.2 0.0.0.0/0


# 两种删除方式
iptables -D INPUT 3
iptables -D INPUT -s 1.1.1.2 -j DROP
  • 删除所有

    而删除指定表中某条链中的所有规则的命令,我们在一开始就使用到了,就是”iptables -t 表名 -F 链名”
    -F选项为flush之意,即冲刷指定的链,即删除指定链中的所有规则,但是注意,此操作相当于删除操作,在没有保存iptables规则的情况下,请慎用。

3.5 修改规则

建议删除后再新增

  • 修改默认策略
    使用-t指定要操作的表,使用-P选项指定要修改的链,下例中,-P FORWARD ACCEPT表示将表中FORWRD链的默认策略改为ACCEPT。

    1
    2
    3
    4
    5
    6
    7
    8
    iptables --line -nvL FORWARD
    Chain FORWARD (policy DROP 0 packets, 0 bytes)

    # 执行修改默认
    iptables -P FORWARD ACCEPT

    iptables --line -nvL FORWARD
    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)

3.6 保存规则

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

  • centos

    centos6中,使用”service iptables save”命令即可保存规则,规则默认保存在/etc/sysconfig/iptables文件中

    1
    service iptables save

    centos7中,使用firewall替代了原来的iptables service

    1
    2
    3
    4
    5
    6
    7
    8
    firewall-cmd --zone=public --add-port=3000/tcp --permanent
    firewall-cmd --reload

    # 也可以安装 iptables-service
    yum install -y iptables-services
    systemctl disable firewalld
    systemctl enable iptables
    service iptables save

    还可以使用另一种方法保存iptables规则,就是使用iptables-save命令
    使用iptables-save并不能保存当前的iptables规则,但是可以将当前的iptables规则以”保存后的格式”输出到屏幕上。可以使用iptables-save命令,再配合重定向

    1
    2
    iptables-save > /etc/sysconfig/iptables
    iptables-restore < /etc/sysconfig/iptables
  • ubuntu

    1
    2
    3
    4
    5
    6
    7
    8
    sudo apt-get install iptables-persistent

    sudo /etc/init.d/iptables-persistent save
    sudo /etc/init.d/iptables-persistent reload

    # Ubuntu 16.04 Server
    sudo netfilter-persistent save
    sudo netfilter-persistent reload

4. 匹配条件

4.1 匹配方式

1
2
3
4
5
6
7
8
9
10
11
# 单个匹配
iptables -I INPUT -s 1.1.1.2 -j DROP

# 多个匹配
iptables -I INPUT -s 1.1.1.3,1.1.1.4 -j DROP

# 网段匹配
iptables -I INPUT -s 1.1.1.5/23 -j DROP

# 取反匹配
iptables -I INPUT ! -s 1.1.1.6 -j ACCEPT
  • 取反注意点

使用 “!” 取反后则表示,报文源地址IP只要不为1.1.1.6即满足条件,那么,上例中规则表达的意思就是,只要发往本机的报文的源地址不是1.1.1.6,就接受报文。

只要报文的源IP不是1.1.1.6,那么就接受此报文,但是,某些小伙伴可能会误会,把上例中的规则理解成如下含义,

只要报文的源IP是1.1.1.6,那么就不接受此报文,这种理解与上述理解看似差别不大,其实完全不一样,这样理解是错误的,上述理解才是正确的。

换句话说就是,报文的源IP不是1.1.1.6时,会被接收,并不能代表,报文的源IP是1.1.1.6时,会被拒绝。

4.2 匹配IP地址

1
2
# 只丢弃从 1.1.1.7 发往 1.1.1.8 这个IP的报文
iptables -I INPUT -s 1.1.1.7 -d 1.1.1.8 -j DROP

如果我们不指定任何目标地址,则目标地址默认为0.0.0.0/0,同理,如果我们不指定源地址,源地址默认为0.0.0.0/0,0.0.0.0/0表示所有IP,示例如下。

与-s选项一样,-d选项也可以使用”叹号”进行取反,也能够同时指定多个IP地址,使用”逗号”隔开即可。

但是请注意,不管是-s选项还是-d选项,取反操作与同时指定多个IP的操作不能同时使用。

需要明确的一点就是:当一条规则中有多个匹配条件时,这多个匹配条件之间,默认存在”与”的关系。也就是取其交集的意思。

4.3 匹配协议类型

我们可以使用-p选项,指定需要匹配的报文的协议类型。

拒绝来自 1.1.1.2的tcp类型的请求

1
2
3
4
5
6
7
iptables -I INPUT -s 1.1.1.2 -p tcp -j DROP


root@tencent:~# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- 1.1.1.2 anywhere

centos6中,-p选项支持如下协议类型

1
tcp, udp, udplite, icmp, esp, ah, sctp

centos7中,-p选项支持如下协议类型

1
tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh

当不使用-p指定协议类型时,默认表示所有类型的协议都会被匹配到,与使用-p all的效果相同。

  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    ping 49.234.15.70 # 服务器可以通

    ps -ef | grep sshd # 获取登录者 root@pts/1
    who -a | grep pts/0 # 获取登录者ip 20816 (223.70.253.1)

    iptables -I INPUT -s 223.70.253.1 -p icmp -j DROP # 服务器禁ping

    ping 49.234.15.70 # 服务器不通了

4.4 匹配网卡接口

  • 入口

使用-i选项,指定网卡名称, 表示丢弃由eth0网卡流入的icmp类型的报文。

1
iptables -I INPUT -s 223.70.253.1 -i eth0 -p icmp -j DROP

-i选项是用于匹配报文流入的网卡的,也就是说,从本机发出的报文是不可能会使用到-i选项的,因为这些由本机发出的报文压根不是从网卡流入的,而是要通过网卡发出的,从这个角度考虑,-i选项的使用是有限制的。

所以-i选项只能用于上图中的PREROUTING链、INPUT链、FORWARD链,这是-i选项的特殊性。

  • 出口

当主机有多块网卡时,可以使用-o选项,匹配报文将由哪块网卡流出,没错,-o选项与-i选项是相对的,-i选项用于匹配报文从哪个网卡流入,-o选项用于匹配报文将从哪个网卡流出。

-o选项只能用于FORWARD链、OUTPUT链、POSTROUTING链。

4.5 匹配端口

匹配端口属于扩展匹配条件, 需要依赖一些扩展模块.

4.5.1 端口 -m tcp

选项–dport可以匹配报文的目标端口,–dport意为destination-port,即表示目标端口。与之前的选项不同,–dport前有两条”横杠”,而且,使用–dport选项时,必须事先指定了使用哪种协议,即必须先使用-p选项

1
2
3
4
5
6
7
iptables -I INPUT -s 1.1.1.2 -p tcp -m tcp --dport 22 -j DROP


root@tencent:~# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 1631 packets, 1525K bytes)
pkts bytes target prot opt in out source destination
0 0 DROP tcp -- * * 1.1.1.2 0.0.0.0/0 tcp dpt:22

在使用–dport之前,我们使用-m选项,指定了对应的扩展模块为tcp,也就是说,如果想要使用–dport这个扩展匹配条件,则必须依靠某个扩展模块完成,上例中,这个扩展模块就是tcp扩展模块,最终,我们使用的是tcp扩展模块中的dport扩展匹配条件。

  • -m tcp表示使用tcp扩展模块,–dport表示tcp扩展模块中的一个扩展匹配条件,可用于匹配报文的目标端口。
  • -p tcp与 -m tcp并不冲突,-p用于匹配报文的协议,-m 用于指定扩展模块的名称,正好,这个扩展模块也叫tcp。

扩展匹配条件是可以取反的,同样是使用”!”进行取反,比如 “! –dport 22”,表示目标端口不是22的报文将会被匹配到。

代表”源端口”的扩展匹配条件为–sport, 不管是–sport还是–dsport,都能够指定一个端口范围,比如,–dport 22:25表示目标端口为22到25之间的所有端口,即22端口、23端口、24端口、25端口

4.5.1 多个端口 -m multiport

如果想要同时指定多个离散的端口,需要借助另一个扩展模块,”multiport”模块。

1
2
3
4
5
6
iptables -I INPUT -s 1.1.1.2 -p tcp -m multiport --dports 22,36,80 -j DROP

root@tencent:~# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 184 packets, 109K bytes)
pkts bytes target prot opt in out source destination
0 0 DROP tcp -- * * 1.1.1.2 0.0.0.0/0 multiport dports 22,36,80

5. 常用扩展

5.1 iprange扩展模块

使用iprange扩展模块可以指定”一段连续的IP地址范围”,用于匹配报文的源地址或者目标地址。

1
2
3
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

5.2 string扩展模块

使用string扩展模块,可以指定要匹配的字符串,如果报文中包含对应的字符串,则符合匹配条件。

–algo:用于指定匹配算法,可选的算法有bm与kmp,此选项为必须选项,我们不用纠结于选择哪个算法,但是我们必须指定一个。

–string:用于指定需要匹配的字符串。

1
iptables -t filter -I INPUT -p tcp --sport 80 -m string --algo bm --string "OOXX" -j REJECT

5.3 time扩展模块

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

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

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

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

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

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

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

1
2
3
4
5
6
7
8
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
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
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --datestart 2017-12-24 --datestop 2017-12-27 -j REJECT

5.4 connlimit扩展模块

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

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

–connlimit-mask:此选项不能单独使用,在使用–connlimit-above选项时,配合此选项,则可以针对”某类IP段内的一定数量的IP”进行连接数量的限制

1
2
3
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j REJECT
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 --connlimit-mask 27 -j REJECT

5.5 limit扩展模块

limit模块是对”报文到达速率”进行限制的。如果我想要限制单位时间内流入的包的数量,就能用limit模块。

–limit-burst:类比”令牌桶”算法,此选项用于指定令牌桶中令牌的最大数量。

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

1
2
3
#如下两条规则需配合使用
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

5.6 udp扩展

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

1
2
3
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模块指定多个离散的端口

5.7 icmp扩展

ICMP协议的全称为Internet Control Message Protocol,翻译为互联网控制报文协议,它主要用于探测网络上的主机是否可用,目标是否可达,网络是否通畅,路由是否可用等。

ping命令使用的就是icmp协议。

–icmp-type:匹配icmp报文的具体类型

1
2
3
4
5
iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECT
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
iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT

5.8 state扩展

我们为了让”提供服务方”能够正常的”响应”我们的请求,于是在主机上开放了对应的端口(80, 22),开放这些端口的同时,也出现了问题,别人利用这些开放的端口,”主动”的攻击我们,他们发送过来的报文并不是为了响应我们,而是为了主动攻击我们。

对于state模块的连接而言,”连接”其中的报文可以分为5种状态,报文状态可以为NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED。

  • 怎样判断报文是否是为了回应之前发出的报文?

我们只要放行状态为ESTABLISHED的报文即可,因为如果报文的状态为ESTABLISHED,那么报文肯定是之前发出的报文的回应,如果你还不放心,可以将状态为RELATED或ESTABLISHED的报文都放行,这样,就表示只有回应我们的报文能够通过防火墙,如果是别人主动发送过来的新的报文,则无法通过防火墙。

6. 黑白名单

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

链的默认策略为ACCEPT时,链中的规则对应的动作应该为DROP或者REJECT,表示只有匹配到规则的报文才会被拒绝,没有被规则匹配到的报文都会被默认接受,这就是”黑名单”机制。

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

当链的默认策略设置为DROP时,链中的规则对应的动作应该为ACCEPT,表示只有匹配到规则的报文才会被放行,没有被规则匹配到的报文都会被默认拒绝,这就是”白名单”机制。

6.1 默认DROP的问题

在对应的链中没有设置任何规则时,这样使用默认策略为DROP是非常不明智的,因为管理员也会把自己拒之门外,即使对应的链中存在放行规则,当我们不小心使用”iptables -F”清空规则时,放行规则被删除,则所有数据包都无法进入,这个时候就相当于给管理员挖了个坑,所以,我们如果想要使用”白名单”的机制,最好将链的默认策略保持为”ACCEPT”,然后将”拒绝所有请求”这条规则放在链的尾部,将”放行规则”放在前面,这样做,既能实现”白名单”机制,又能保证在规则被清空时,管理员还有机会连接到主机,示例如下。

1
2
iptables -I INPUT -s 192.168.1.111,192.168.1.118 -j DROP
iptables -A INPUT -j DROP

7. 自定义链

当默认链中的规则非常多时,不方便我们管理。

7.1 新建

1
2
3
4
5
iptables -N IN_WEB

iptables -nvL
Chain IN_WEB (0 references)
pkts bytes target prot opt in out source destination

7.2 添加规则

1
2
3
4
5
6
7
iptables -I IN_WEB -s 1.1.1.2 -j REJECT


iptables -nvL IN_WEB
Chain IN_WEB (0 references)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- * * 1.1.1.2 0.0.0.0/0 reject-with icmp-port-unreachable

7.3 增加引用

现在,自定义链中已经有了一些规则,但是目前,这些规则无法匹配到任何报文,因为我们并没有在任何默认链中引用它。

1
2
3
4
5
6
7
iptables -I INPUT -p tcp -j IN_WEB


iptables -nvL INPUT
Chain INPUT (policy ACCEPT 7813 packets, 5921K bytes)
pkts bytes target prot opt in out source destination
7614 5907K IN_WEB tcp -- * * 0.0.0.0/0 0.0.0.0/0

之前的示例中,我们使用”-j”选项指定动作,而此处,我们将”动作”替换为了”自定义链”

7.4 修改

1
iptables -E IN_WEB WEB

7.5 删除

1
2
iptables -X WEB
#iptables: Too many links.

因为有引用, 无法删除

1
2
3
iptables -D  INPUT 1
iptables -X WEB
# iptables: Directory not empty.

因为有规则, 无法删除

1
2
3
4
iptables -F WEB
iptables -X WEB

# 删除成功

8. 网络防火墙(filter表forward链)

网络防火墙的职责就是”过滤并转发”,要想”过滤”,只能在INPUT、OUTPUT、FORWARD三条链中实现,要想”转发”,报文则只会经过FORWARD链(发往本机的报文才会经过INPUT链)

1

iptables的角色变为”网络防火墙”时,规则只能定义在FORWARD链中。

8.1 用例

1

上图中的主机A充当了”外部网络主机”的角色,A主机的IP地址为192.168.1.147,我们使用主机A访问内部网络中的主机C,但是需要主机B进行转发,主机B在转发报文时会进行过滤,以实现网络防火墙的功能。

8.2 配置

要配置转发,则需在FORWAED链中定义规则,所以,我们应该在filter表中的FORWARD链中配置规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination


# 添加默认拒绝
iptables -A FORWARD -j REJECT


# 添加转发规则
iptables -I FORWARD -s 1.1.0.0/16 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -I FORWARD -d 1.1.0.0/16 -p tcp -m tcp --sport 80 -j ACCEPT


iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 1.1.0.0/16 tcp spt:80
0 0 ACCEPT tcp -- * * 1.1.0.0/16 0.0.0.0/0 tcp dpt:80
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable

当iptables作为”网络防火墙”时,在配置规则时,往往需要考虑”双向性”,也就是说,我们为了达成一个目的,往往需要两条规则才能完成。每次配置规则时都要考虑”双向”的问题, 可以考虑加下面的规则, 以后只加单向就可以了。

1
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

9. 动作

之前用到的ACCEPT与DROP都属于基础动作。使用-j可以指定动作,比如-j ACCEPT, -j DROP, -j REJECT

9.1 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。

9.2 LOG

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

9.3 SNAT(NAT表)

9.3.1 NAT介绍

内部网络的报文发送出去时,报文的源IP会被修改,也就是源地址转换:Source Network Address Translation,缩写为SNAT。

外部网络的报文响应时,响应报文的目标IP会再次被修改,也就是目标地址转换:Destinationnetwork address translation,缩写为DNAT。

整个过程被称为SNAT还是DNAT,取决于整个过程的前半段使用了SNAT还是DNAT。

9.3.2 操作
1
2
3
4
5
6
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 2.2.2.2

iptables -t nat -nvL POSTROUTING
Chain POSTROUTING (policy ACCEPT 357 packets, 21639 bytes)
pkts bytes target prot opt in out source destination
0 0 SNAT all -- * * 10.1.0.0/16 0.0.0.0/0 to:2.2.2.2

如上图所示,上图中的规则表示将来自于10.1.0.0/16网段的报文的源地址改为公网IP地址(2.2.2.2)。

  1. “-t nat”表示操作nat表,我们之前一直在灌输一个概念,就是不同的表有不同的功能,filter表的功能是过滤,nat表的功能就是地址转换,所以我们需要在nat表中定义nat规则。

  2. “-A POSTROUTING”表示将SNAT规则添加到POSTROUTING链的末尾,在centos7中,SNAT规则只能存在于POSTROUTING链与INPUT链中,在centos6中,SNAT规则只能存在于POSTROUTING链中。

  3. 为什么SNAT规则必须定义在POSTROUTING链中,我们可以这样认为,POSTROUTING链是iptables中报文发出的最后一个”关卡”,我们应该在报文马上发出之前,修改报文的源地址,否则就再也没有机会修改报文的源地址了。

  4. 如果只是用于配置SNAT的话,我们并不用手动的进行DNAT设置,iptables会自动维护NAT表,并将响应报文的目标地址转换回来。

9.4 DNAT(NAT表)

公司只有一个公网IP,但是公司的内网中却有很多服务器提供各种服务,我们对外宣称,公司的公网IP上既提供了web服务,也提供了windows远程桌面,不管是访问web服务还是远程桌面,只要访问这个公网IP就行了,我们利用DNAT,将公网客户端发送过来的报文的目标地址与端口号做了映射,将访问web服务的报文转发到了内网中的C主机中,将访问远程桌面的报文转发到了内网中的D主机中。

1
2
3
4
5
6
7
iptables -t nat -I PREROUTING -d 2.2.2.2 -p tcp --dport 3389 -j DNAT --to-destination 10.1.0.6:3389


iptables -t nat -vnL PREROUTING
Chain PREROUTING (policy ACCEPT 2 packets, 68 bytes)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- * * 0.0.0.0/0 2.2.2.2.146 tcp dpt:3389 to:10.1.0.6:3389
  1. “-t nat -I PREROUTING”表示在nat表中的PREROUTING链中配置DNAT规则,DNAT规则只配置在PREROUTING链与OUTPUT链中。

  2. “-d 2.2.2.2 -p tcp –dport 3389”表示报文的目标地址为公司的公网IP地址,目标端口为tcp的3389号端口,而我们知道,windows远程桌面使用的默认端口号就是3389,当外部主机访问公司公网IP的3389号端口时,报文则符合匹配条件。

  3. “-j DNAT –to-destination 10.1.0.6:3389”表示将符合条件的报文进行DNAT,也就是目标地址转换,将符合条件的报文的目标地址与目标端口修改为10.1.0.6:3389,”–to-destination”就是动作DNAT的常用选项。

    那么综上所述,当外网主机访问公司公网IP(2.2.2.2)的3389时,其报文的目标地址与端口将会被映射到10.1.0.6:3389上。

  4. 理论上只要完成上述DNAT配置规则即可,但是在测试时,只配置DNAT规则后,并不能正常DNAT,经过测试发现,将相应的SNAT规则同时配置后,即可正常DNAT,于是我们又配置了SNAT。

    1
    iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 2.2.2.2

9.5 MASQUERADE

当我们拨号网上时,每次分配的IP地址往往不同,不会长期分给我们一个固定的IP地址,如果这时,我们想要让内网主机共享公网IP上网,就会很麻烦,因为每次IP地址发生变化以后,我们都要重新配置SNAT规则,这样显示不是很人性化,我们通过MASQUERADE即可解决这个问题,MASQUERADE会动态的将源地址转换为可用的IP地址,其实与SNAT实现的功能完全一致,都是修改源地址。

只不过SNAT需要指明将报文的源地址改为哪个IP,而MASQUERADE则不用指定明确的IP,会动态的将报文的源地址修改为指定网卡上可用的IP地址。

1
2
3
4
iptables -t nat -I POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 2.2.2.2

# MASQUERADE的对比
iptables -t nat -I POSTROUTING -s 10.1.0.0/16 -o 网卡名字 -j MASQUERADE

可以把MASQUERADE理解为动态的、自动化的SNAT,如果没有动态SNAT的需求,没有必要使用MASQUERADE,因为SNAT更加高效。

9.6 REDIRECT

使用REDIRECT动作可以在本机上进行端口映射

比如,将本机的80端口映射到本机的8080端口上

1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

经过上述规则映射后,当别的机器访问本机的80端口时,报文会被重定向到本机的8080端口上。

REDIRECT规则只能定义在PREROUTING链或者OUTPUT链中。

10. 防火墙关系

10.1 firewalld 和 iptables 关系(Centos)

ConterOS7.0以上使用的是firewall,ConterOS7.0以下使用的是iptables

在RHEL7里有几种防火墙共存:firewalld、iptables、ebtables,默认是使用firewalld来管理netfilter子系统,不过底层调用的命令仍然是iptables等。

firewalld跟iptables比起来至少有两大好处:

1、firewalld可以动态修改单条规则,而不需要像iptables那样,在修改了规则后必须得全部刷新才可以生效;

2、firewalld在使用上要比iptables人性化很多,即使不明白“五张表五条链”而且对TCP/IP协议也不理解也可以实现大部分功能。

firewalld跟iptables比起来,不好的地方是每个服务都需要去设置才能放行,因为默认是拒绝。而iptables里默认是每个服务是允许,需要拒绝的才去限制。

10.2 ufw 和 iptables 关系(Ubuntu)

Uncomplicated Firewall,简称 UFW,是Ubuntu系统上默认的防火墙组件。UFW是为轻量化配置iptables而开发的一款工具。UFW 提供一个非常友好的界面用于创建基于IPV4,IPV6的防火墙规则。UFW 在 Ubuntu 8.04 LTS 后的所有发行版中默认可用。

当使用了 ufw 这类前端时,就最好不要再碰 iptables 了,尤其要慎重使用 iptables – 来清空所有链的规则。在不了解 iptables 的表、链、规则之前,盲目的清空 iptables”规则” 就是耍流氓!

试想,假如你在服务器上ufw enable,那么 INPUT 和 FORWARD 就是 DROP,那么当你iptables -F时,不仅仅是 SSH 的例外规则没了,所有出网的包也都出不去了!此时唯一能做的事情就是去 VNC、或者去机房插鼠标键盘显示器。

10.3 虚拟防火墙和安全组有什么差异

  • 云虚拟防火墙是互联网边界防火墙、VPC边界防火墙、主机边界防火墙的统称,为您提供互联网边界、VPC网络边界、ECS实例间的三重防护。

  • 安全组是ECS提供的虚拟主机防火墙,对ECS实例间的流量进行访问控制。

结论:

  1. 防火墙是在安全组之前生效的。

  2. 防火墙主要是做南北向的访问控制,作用范围是整个VPC,安全组主要是做东西向的访问控制,作用范围是虚拟机网卡,和防火墙形成互补的关系。

1

11. 命令总结

11.1 过滤查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#查看对应表的所有规则,-t选项指定要操作的表,省略"-t 表名"时,默认表示操作filter表,-L表示列出规则,即查看规则
iptables -t 表名 -L


#查看指定表的指定链中的规则
iptables -t 表名 -L 链名



# 查看指定表的所有规则,并且显示更详细的信息(更多字段),-v表示verbose,表示详细的,冗长的,当使用-v选项时,会显示出"计数器"的信息,由于上例中使用的选项都是短选项,所以一般简写为iptables -t 表名 -vL
iptables -t 表名 -v -L



#表示查看表的所有规则,并且在显示规则时,不对规则中的IP或者端口进行名称反解,-n选项表示不解析IP地址。
iptables -t 表名 -n -L


#表示查看表的所有规则,并且显示规则的序号,--line-numbers选项表示显示规则的序号,注意,此选项为长选项,不能与其他短选项合并,不过此选项可以简写为--line,注意,简写后仍然是两条横杠,仍然是长选项。
iptables --line-numbers -t 表名 -L


#表示查看表中的所有规则,并且显示更详细的信息(-v选项),不过,计数器中的信息显示为精确的计数值,而不是显示为经过可读优化的计数值,-x选项表示显示计数器的精确值。
iptables -t 表名 -v -x -L


# 实际使用中,为了方便,往往会将短选项进行合并,所以,如果将上述选项都糅合在一起,可以写成如下命令,此处以filter表为例。
iptables --line -t filter -nvxL INPUT

11.2 过滤增删存

  • 增加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#在指定表的指定链的尾部添加一条规则,-A选项表示在对应链的末尾添加规则,省略-t选项时,表示默认操作filter表中的规则
命令语法:iptables -t 表名 -A 链名 匹配条件 -j 动作
示例: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 链名 动作
示例:iptables -t filter -P FORWARD ACCEPT
  • 删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#按照规则序号删除规则,删除指定表的指定链的指定规则,-D选项表示删除对应链中的规则。
命令语法:iptables -t 表名 -D 链名 规则序号
示例:iptables -t filter -D INPUT 3


#按照具体的匹配条件与动作删除规则,删除指定表的指定链的指定规则。
命令语法:iptables -t 表名 -D 链名 匹配条件 -j 动作
示例: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
2
3
4
5
6
7
8
9
10
11
#修改指定表中指定链的指定规则,-R选项表示修改对应链中的规则,使用-R选项时要同时指定对应的链以及规则对应的序号,并且规则中原本的匹配条件不可省略。
命令语法:iptables -t 表名 -R 链名 规则序号 规则原本的匹配条件 -j 动作
示例:iptables -t filter -R INPUT 3 -s 192.168.1.146 -j ACCEPT


#其他修改规则的方法:先通过编号删除规则,再在原编号位置添加一条规则。


#修改指定表的指定链的默认策略(默认动作),并非修改规则,可以使用如下命令。
命令语法:iptables -t 表名 -P 链名 动作
示例:iptables -t filter -P FORWARD ACCEPT
  • 保存
1
2
3
4
5
6
7
8
9
10
# centos
yum install -y iptables-services
systemctl disable firewalld
systemctl enable iptables
service iptables save

# ubtuntu
sudo apt-get install iptables-persistent
sudo netfilter-persistent save
sudo netfilter-persistent reload

11.3 协议, 网卡匹配

-p用于匹配报文的协议类型,可以匹配的协议类型tcp、udp、udplite、icmp、esp、ah、sctp等(centos7中还支持icmpv6、mh)。

1
2
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链中不能使用此选项。

1
2
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链中不能使用此选项。

1
2
iptables -t filter -I OUTPUT -p icmp -o eth4 -j DROP
iptables -t filter -I OUTPUT -p icmp ! -o eth4 -j DROP

11.4 IP匹配

-s用于匹配报文的源地址,可以同时指定多个源地址,每个IP之间用逗号隔开,也可以指定为一个网段。

1
2
3
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
iptables -t filter -I INPUT ! -s 192.168.1.0/24 -j ACCEPT

-d用于匹配报文的目标地址,可以同时指定多个目标地址,每个IP之间用逗号隔开,也可以指定为一个网段。

1
2
3
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
iptables -t filter -I INPUT ! -d 192.168.1.0/24 -j ACCEPT

11.5 端口匹配

  • tcp扩展模块

    -p tcp -m tcp –sport 用于匹配tcp协议报文的源端口,可以使用冒号指定一个连续的端口范围

    -p tcp -m tcp –dport 用于匹配tcp协议报文的目标端口,可以使用冒号指定一个连续的端口范围

    1
    2
    3
    4
    5
    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
    iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 80: -j REJECT
    iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPT
  • multiport扩展模块

    -p tcp -m multiport –sports 用于匹配报文的源端口,可以指定离散的多个端口号,端口之间用”逗号”隔开

    -p udp -m multiport –dports 用于匹配报文的目标端口,可以指定离散的多个端口号,端口之间用”逗号”隔开

    1
    2
    3
    4
    5
    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

11.6 tcp头标志位匹配

1
2
3
4
5
6
7
8
9
10
11
#第一次握手
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
#第二次握手
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

#用于匹配tcp新建连接的请求报文,"第一次握手"
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --syn -j REJECT

11.7 网络防火墙(filter表forward链)

由于iptables此时的角色为”网络防火墙”,所以需要在filter表中的FORWARD链中设置规则。
可以使用”白名单机制”,先添加一条默认拒绝的规则,然后再为需要放行的报文设置规则。
配置规则时需要考虑”方向问题”,针对请求报文与回应报文,考虑报文的源地址与目标地址,源端口与目标端口等。

1
2
3
4
5
6
#示例为允许网络内主机访问网络外主机的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扩展模块,对上述规则进行优化,使用如下配置可以省略许多”回应报文放行规则”。

1
2
3
4
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

11.8 SNAT内网外出(nat表postrouting链)

1
2
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -o eth0 -j MASQUERADE

11.9 DNAT外网进来(nat表prerouting链)

1
2
3
4
5
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

# 但是在测试DNAT时,对应SNAT规则也需要配置,才能正常DNAT,可以先尝试只配置DNAT规则,如果无法正常DNAT,再尝试添加对应的SNAT规则,SNAT规则配置一条即可,DNAT规则需要根据实际情况配置不同的DNAT规则。
iptables -t nat -A POSTROUTING -s 10.1.0.0/16 -j SNAT --to-source 公网IP

11.10 本机目标端口映射

1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

配置完成上述规则后,其他机器访问本机的80端口时,会被映射到8080端口。

12. 参考资料

给作者打赏,鼓励TA抓紧创作!