netfilter/iptables
作用
用于保护内网安全的一种设备。
依据规则进行防护。
用户定义规则。(允许或拒绝外部用户访问)
分类
逻辑划分
- 主机防火墙(个人服务)
- 网络防火墙(集体服务)
物理划分
- 硬件防火墙(性能高)
- 软件防火墙(成本低)
性能指标
- 吞吐量
- 并发连接
- 新建连接
- 时延
- 抖动
iptables
- netfilter 位于内核空间,是 Linux 操作系统核心层内部的一个数据包处理模块。
- iptables 是位于用户空间对内核空间的 netfilter 进行操作的命令行工具。
netfilter 功能
- 数据包过滤
- 数据包转发(重定向)
- 网络地址转换:NAT
流程图
-
INPUT:处理入站数据包
-
OUT:处理出站数据包
-
FORWARD:处理转发数据包(主要是将数据包转发至本机其他网卡)
1当数据报文经过本机时,网卡接收数据报文至缓冲区,内核读取报文的ip首部,发现报文不是送到本机时(目的ip不是本机),由内核直接送到forward链做匹配,匹配之后若符合forward的规则,再经由postrouting送往下一跳或目的主机。
-
PREROUTING:在进行路由选择前处理数据包,修改到达防火墙数据包的目的 IP 地址,用于判断目标主机。(DNAT)
-
POSTROUTING:在进行路由选择后处理数据包,修改要离开防火墙数据包的源 IP 地址,判断经由哪一接口送往下一跳。(SNAT)
表的概念
每个“规则链”上都设置了一串规则,这样的话,我们就可以把不同的“规则链”组合成能够完成某一特定功能集合的分类,这个集合分类就称之为表,iptables 中有 5 张表,学习 iptables 需要搞明白每种表的作用。
表名 | 作用 | 内核模块 |
---|---|---|
filter | 过滤功能,确定是否放行该数据包,属于真正防火墙 | iptables_filter |
nat | 网络地址转换,修改数据包中的源、目标 IP 地址或端口 | iptable_nat |
mangle | 对数据包进行重新封装功能,为数据包设置标记 | iptable_mangle |
raw | 确定是否对数据包进行跟踪 | iptable_mangle |
security | 是否定义强制访问控制规则 | 后加上的 |
表与链之间的关系
应用防火墙是以表为操作入口,只要在相应的表中的规则链上添加规则即可实现某一功能。
应该知道哪张表包括哪些规则链,在规则链上操作即可。
表 | 规则链 |
---|---|
filter | INPUT、FORWARD、OUTPUT |
nat | PREROUTING、OUTPUT、POSTROUTING、INPUT |
mangle | PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING |
raw | PREROUTING、OUTPUT |
security | INPUT、FORWARD、OUTPUT |
数据包流经 iptable 流程
iptables 中表的优先级
security>raw>mangle>nat>filter
规则
基本匹配条件(无需加载扩展模块,匹配规则生效)
1源地址,目标地址,源端口,目标端口等
2
3-p 指定规则协议,tcp udp icmp all
4-s 指定数据包的源地址,ip hostname
5-d 指定目的地址
6-i 输入接口
7-o 输出接口
8! 取反
扩展匹配条件(无需加载扩展模块,匹配规则生效)
- 显示匹配:必须使用-m 选项指明要调用的扩展模块的扩展机制以及需要手动加载扩展模块。
1################ multiport 多端口 2#在INPUT链中开放本机tcp 22,tcp80端口 3iptables -I INPUT -d 192.168.2.10 -p tcp -m multiport --dports 22,80 -j ACCEPT 4 5#在OUTPUT链中开发源端口tcp 22,tcp80 6iptables -I OUTPUT -s 192.168.2.10 -p tcp -m multiport --sports 22,80 -j ACCEPT 7 8################ iprange 多ip地址 9iptables -A INPUT -d 192.168.2.10 -p tcp --dport 23 -m iprange --src-range 192.168.2.11-192.168.2.21 -j ACCEPT 10 11iptables -A OUTPUT -s 192.168.2.10 -p tcp --sport 23 -m iprange --dst-range 192.168.2.11-192.168.2.21 -j ACCEPT 12 13################ time 指定访问时间范围 14iptables -A INPUT -d 192.168.2.10 -p tcp --dport 901 -m time --weekdays Mon,Tus,Wed,Thu,Fri --timestart 08:00:00 --time-stop 18:00:00 -j ACCEPT 15 16iptables -A OUTPUT -s 192.168.2.10 -p tcp --sport 901 -j ACCEPT 17 18################ string 字符串,对报文中的应用层数据做字符串模式匹配检测(通过算法实现)。 19--algo {bm|kmp}:字符匹配查找时使用算法 20--string "STRING": 要查找的字符串 21--hex-string “HEX-STRING”: 要查找的字符,先编码成16进制格式 123 22 23################ connlimit 连接限制,根据每个客户端IP作并发连接数量限制。 24--connlimit-upto n 连接数小于等于n时匹配 25--connlimit-above n 连接数大于n时匹配 26 27################ limit 报文速率限制 28 29################ state 追踪本机上的请求和响应之间的数据报文的状态。 30 状态有五种:INVALID, ESTABLISHED, NEW, RELATED,UNTRACKED 31--state state 32NEW 新连接请求 33ESTABLISHED 已建立的连接 34INVALID 无法识别的连接 35RELATED 相关联的连接,当前连接是一个新请求,但附属于某个已存在的连接 36UNTRACKED 未追踪的连接 37 381、对于进入的状态为ESTABLISHED都应该放行; 392、对于出去的状态为ESTABLISHED都应该放行; 403、严格检查进入的状态为NEW的连接; 414、所有状态为INVALIED都应该拒绝;
- 隐式匹配:使用-p 选项指明协议时,无需再同时使用-m 选项指明扩展模块以及不需要手动加载扩展模块;
1-p tcp 2 --sport 匹配报文源端口;可以给出多个端口,但只能是连续的端口范围 3 --dport 匹配报文目标端口;可以给出多个端口,但只能是连续的端口范围 4 --tcp-flags mask comp 匹配报文中的tcp协议的标志位 5 6-p udp 7 --sport 匹配报文源端口;可以给出多个端口,但只能是连续的端口范围 8 --dport 匹配报文目标端口;可以给出多个端口,但只能是连续的端口范围 9 10--icmp-type 11 0/0: echo reply 允许其他主机ping 12 8/0:echo request 允许ping其他主机
动作
ACCEPT:允许数据包通过
DROP:直接丢弃数据包,不给任何回应信息
REJECT:拒绝数据包通过,发送回应信息给客户端
SNAT:源地址转换
1# 用于静态公网IP
2iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth1 -j SNAT --to-source 202.12.10.100
3
4# 用于动态公网IP
5iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE
DNAT:目标地址转换
1iptables -t nat PREROUTING -d 202.12.10.100 -p tcp --dport 80 -j DNAT --to-destination 192.168.10.1
REDIRECT:在本机做端口映射
LOG:在日志中记录信息,然后将数据包传递给下一条规则
规则策略
- 黑名单:没有被拒绝的流量都可以通过。(不推荐)(ACCEPT)
- 白名单:没有被允许的流量都拒绝。(推荐)(DROP)
指定规则思路
1、选择一张表,词表决定了数据报文处理的方式
2、选择一条链,此链决定了数据报文流经哪些位置
3、选择适合的条件,此条件决定了对数据报文做何种条件匹配
4、选择处理数据报文的动作,指定相应的防火墙规则
1iptables [-t 表名] 管理选项 [链名] [条件匹配] [-j 目标动作或跳转]
2
3iptables不指定表名时,默认表示filter表,不指定链名时,默认表示该表内所有链,除非设置规则链的默认策略,否则
4需要指定匹配条件
iptables 链管理方法
1-N, --new-chain chain:新建一个自定义的规则链;
2-X, --delete-chain [chain]:删除用户自定义的引用计数为0的空链;
3-F, --flush [chain]:清空指定的规则链上的规则;
4-E, --rename-chain old-chain new-chain:重命名链;
5-Z, --zero [chain [rulenum]]:置零计数器;
6 注意:每个规则都有两个计数器
7 packets:被本规则所匹配到的所有报文的个数;
8 bytes:被本规则所匹配到的所有报文的大小之和;
9-P, --policy chain target 制定链表的策略(ACCEPT|DROP|REJECT) 12345678
iptables 规则管理
1-A, --append chain rule-specification:追加新规则于指定链的尾部;
2-I, --insert chain [rulenum] rule-specification:插入新规则于指定链的指定位置,默认为首部;
3-R, --replace chain rulenum rule-specification:替换指定的规则为新的规则;
4-D, --delete chain rulenum:根据规则编号删除规则;
5-D, --delete chain rule-specification:根据规则本身删除规则; 12345
iptables 规则显示
1-L, --list [chain]:列出规则;
2-v, --verbose:详细信息;
3-vv 更详细的信息
4-n, --numeric:数字格式显示主机地址和端口号;
5-x, --exact:显示计数器的精确值,而非圆整后的数据;
6--line-numbers:列出规则时,显示其在链上的相应的编号;
7-S, --list-rules [chain]:显示指定链的所有规则;
安装 iptables-services
CentOS7 系统中默认存在 iptables 命令,此命令仅为简单查询及操作命令,不包含配置文件,安装 iptables.services 后,将直接生成配置文件,便于配置保存。包含 ipv4 及 ipv6
1# 关闭firewalld
2[root@localhost ~]# systemctl stop firewalld
3
4# 安装iptables-services
5[root@localhost ~]# yum -y install iptables-services
6
7# 启动服务
8[root@localhost ~]# systemctl start iptables.service
9[root@localhost ~]# systemctl status iptables.service
10● iptables.service - IPv4 firewall with iptables
11 Loaded: loaded (/usr/lib/systemd/system/iptables.service; enabled; vendor preset: disabled)
12 Active: active (exited) since Thu 2021-04-29 15:45
13
14# 设置开机自启动
15[root@localhost ~]# systemctl enable iptables.service
16
17# 查看配置文件
18[root@localhost ~]# rpm -ql iptables-services
19/etc/sysconfig/ip6tables
20/etc/sysconfig/iptables # 配置文件在这里
21/usr/lib/systemd/system/ip6tables.service
22/usr/lib/systemd/system/iptables.service
23/usr/libexec/initscripts/legacy-actions/ip6tables
24/usr/libexec/initscripts/legacy-actions/ip6tables/panic
25/usr/libexec/initscripts/legacy-actions/ip6tables/save
26/usr/libexec/initscripts/legacy-actions/iptables
27/usr/libexec/initscripts/legacy-actions/iptables/panic
28/usr/libexec/initscripts/legacy-actions/iptables/save
29/usr/libexec/iptables
30/usr/libexec/iptables/ip6tables.init
31/usr/libexec/iptables/iptables.init
32
33# 保存规则
34[root@localhost ~]# iptables-save > /etc/sysconfig/iptables
35
36# 重载
37[root@localhost ~]# iptables-restore < /etc/sysconfig/iptables
38
39# 基本配置
40[root@localhost ~]# iptables -F
41
42# 查询
43[root@localhost ~]# iptables -nL
44
45# 重启iptables 临时设置的规则如果没有保存到配置文件中,iptables下次启动则会丢失当前的规则,会从/etc/sysconfig/iptables配置文件中加载规则
46[root@localhost ~]# systemctl restart iptables
iptables 默认规则
1[root@localhost ~]# cat /etc/sysconfig/iptables
2# Generated by iptables-save v1.4.21 on Thu Apr 29 16:14:43 2021
3*filter
4:INPUT ACCEPT [0:0]
5:FORWARD ACCEPT [0:0]
6:OUTPUT ACCEPT [60:6160]
7-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
8-A INPUT -p icmp -j ACCEPT
9-A INPUT -i lo -j ACCEPT
10-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
11-A INPUT -j REJECT --reject-with icmp-host-prohibited
12-A FORWARD -j REJECT --reject-with icmp-host-prohibited
13COMMIT
14# Completed on Thu Apr 29 16:14:43 2021
15
iptables 标准流程
1# ACCEPT
2[root@localhost ~]# iptables -F
3[root@localhost ~]# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
4[root@localhost ~]# iptables -A INPUT -i lo -j ACCEPT
5[root@localhost ~]# iptables -A INPUT -s 192.168.2.0/24 -j ACCEPT #允许内网任何访问
6[root@localhost ~]# iptables -A INPUT -p tcp --syn --dport 80 -j ACCEPT
7[root@localhost ~]# iptables -A INPUT -p tcp --syn --dport 22 -j ACCEPT
8[root@localhost ~]# iptables -A INPUT -p tcp --syn --dport 20:21 -j ACCEPT
9[root@localhost ~]# iptables -A INPUT -j REJECT
10[root@localhost ~]# modprobe nf_conntrack_ftp
11[root@localhost ~]# iptables-save > /etc/sysconfig/iptables
12[root@localhost ~]# vim /etc/sysconfig/iptables-config
13IPTABLES_MODULES="nf_conntrack_ftp"
iptables 基本操作
1# 删除现有规则
2iptables -F
3
4# 设置链的默认规则(危险,请勿滥用)
5iptables -P INPUT DROP
6iptables -P FORWARD DROP
7iptables -P OUTPUT DROP
8
9# 白名单(DROP)
10[root@localhost ~]# iptables -t filter -F
11[root@localhost ~]# iptables -P INPUT DROP
12[root@localhost ~]# iptables -t filter -I INPUT -p tcp --dport=22 -j ACCEPT [root@localhost ~]# iptables -t filter -I INPUT -p tcp --dport=80 -j ACCEPT
13
14# 黑名单(ACCEPT)
15[root@localhost ~]# iptables -P INPUT ACCEPT
16[root@localhost ~]# iptables -F
17[root@localhost ~]# iptables -t filter -A INPUT -s 192.168.2.20/24 -p tcp --dport 80 -j DROP
18
19# 添加规则
20[root@localhost ~]# iptables -t filter -A INPUT -p tcp --dport=80 -j ACCEPT
21[root@localhost ~]# iptables -t filter -I INPUT -p tcp --dport=80 -j ACCEPT
22[root@localhost ~]# iptables -t filter -I INPUT -s 192.168.31.244 -p tcp --dport=80 -j DROP
23
24# 删除规则
25[root@localhost ~]# iptables -t filter -D INPUT -p tcp --dport=80 -j ACCEPT
26
27# 通过lo访问本机数据
28[root@localhost ~]# iptables -I INPUT -d 127.0.0.1 -p tcp --dport=9000 -i lo -j ACCEPT
案例
案例一
1[root@localhost ~]# yum -y install httpd vsftpd sshd
2[root@localhost ~]# systemctl start httpd vsftpd sshd
3
4[root@localhost ~]# iptables -t filter -F
5[root@localhost ~]# iptables -I INPUT -p tcp --dport 80 -j ACCEPT
6[root@localhost ~]# iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT
7[root@localhost ~]# iptables -I INPUT -p tcp --dport 22 -j ACCEPT
8[root@localhost ~]# iptables -A INPUT -j REJECT
9
10#在存问题
11
12本机无法访问本机 例如:ping 127.0.0.1
13解决方法
14[root@localhost ~]# iptables -I INPUT -i lo -j ACCEPT
15
16本机无法访问其它主机
17例如:ssh remote_host
18解决方法
19[root@localhost ~]# iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
20
21FTP无法访问
22解决方法1: (被动模式)
23[root@localhost ~]# iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT
24[root@localhost ~]# vim /etc/vsftpd/vsftpd.conf
25pasv_min_port=50000
26pasv_max_port=60000
27[root@localhost ~]# iptables -I INPUT -p tcp --dport 50000:60000 -j ACCEPT
28
29解决方法2:使用连接追踪模块
30[root@localhost ~]# iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
31[root@localhost ~]# iptables -I INPUT -p tcp --dport 20:21 -j ACCEPT
32[root@localhost ~]# modprobe nf_conntrack_ftp #临时方法,添加连接追踪模块
33
34[root@localhost ~]# vim /etc/sysconfig/iptables-config #iptables的配置文件
35IPTABLES_MODULES="nf_conntrack_ftp"
36#启动服务时加载
37#针对数据端口连接时,将三次握手第一次状态由NEW识别为RELATED
案例二:扩展匹配
1#-m icmp
2[root@localhost ~]# iptables -F
3[root@localhost ~]# iptables -t filter -I INPUT -p icmp -m icmp --icmp-type echo-reply -j ACCEPT #允许ping回应
4[root@localhost ~]# iptables -A INPUT -j REJECT
5
6#-m iprange
7[root@localhost ~]# iptables -t filter -I INPUT -m iprange --src-range 192.168.2.10- 192.168.2.100 -j REJECT
8
9#-m multiport
10[root@localhost ~]# iptables -t filter -I INPUT -p tcp -m multiport --dports 20,21,22,25,80,110 -j ACCEPT
11
12#-m tos 根据ip协议头部 type of service进行过滤
13[root@localhost ~]# iptables -F
14[root@localhost ~]# tcpdump -i eth0 -nn port 22 -vvv
15
16#抓取远程主机访问本机的ssh数据包,观察TOS值
17[root@localhost ~]# tcpdump -i eth0 -nn port 22 -vvv #抓取远程从本机rsync或scp复制文件,观察TOS值
18#ssh: tos 0x0 0x10
19#scp: tos 0x0 0x8
20#rsync: tos 0x0 0x8
21[root@localhost ~]# iptables -t filter -A INPUT -p tcp --dport 22 -m tos --tos 0x10 -j ACCEPT
22[root@localhost ~]# iptables -t filter -A INPUT -j REJECT
23
24#-m tcp 按TCP控制位进行匹配
25Flags:SYN ACK FIN RST URG PSH ALL NONE
26[root@localhost ~]# iptables -t filter -A INPUT -p tcp -m tcp --tcp-flags SYN,ACK,FIN,RST SYN --dport 80 -j ACCEPT
27[root@localhost ~]# iptables -t filter -A INPUT -p tcp --syn --dport 80 -j ACCEPT #--tcp-flags SYN,ACK,FIN,RST SYN 检查四个标记位,只有SYN标记位才匹配,即只允许三次握手中的第一次 握手,等价于--syn
28
29#-m comment 对规则进行备注说明
30[root@localhost ~]# iptables -A INPUT -s 192.168.2.250 -m comment --comment "cloud host" -j REJECT
31
32#-m mark 使用mangle表的标记方法,配合mangle表使用
33[root@localhost ~]# iptables -t filter -A INPUT -m mark 2 -j REJECT
案例三:扩展动作
1#-j LOG 记录至日志中
2[root@localhost ~]# grep 'kern.*' /etc/rsyslog.conf
3kern.* /var/log/kernel.log
4[root@localhost ~]# systemctl restart rsyslog
5[root@localhost ~]# iptables -j LOG -h
6[root@localhost ~]# iptables -t filter -A INPUT -p tcp --syn --dport 22 -j LOG --log- prefix " localhost_ssh "
7[root@localhost ~]# iptables -t filter -A INPUT -p tcp --syn --dport 22 -j ACCEPT
8[root@localhost ~]# iptables -t filter -A INPUT -j REJECT
9
10#-j REJECT
11当访问一个未开启的TCP端口时,应该返回一个带有RST标记的数据包
12当访问一个未开启的UDP端口,结果返回port xxx unreachable 当访问一个开启的TCP端口,但被防火墙REJECT,结果返回port xxx unreachable
13[root@localhost ~]# iptables -j REJECT -h
14[root@localhost ~]# iptables -t filter -A INPUT -p tcp --dport 22 -j REJECT --reject- with tcp-reset //返回一个自定义消息类型
15
16#-j MARK 进行标记,可在LVS调度器中应用
17[root@localhost ~]# iptables -t mangle -L
18[root@localhost ~]# iptables -j MARK -h
19[root@localhost ~]# iptables -t mangle -A PREROUTING -s 192.168.2.110 -j MARK --set- mark 1
20[root@localhost ~]# iptables -t mangle -A PREROUTING -s 192.168.2.25 -j MARK --set- mark 2
21[root@localhost ~]# iptables -t filter -A INPUT -m mark --mark 1 -j ACCEPT //按照标记匹 配
22[root@localhost ~]# iptables -t filter -A INPUT -m mark --mark 2 -j REJECT
SNAT
1#开启路由转发功能
2[root@localhost ~]# cat /etc/sysctl.conf
3net.ipv4.ip_forward = 1
4[root@localhost ~]# sysctl -p
5net.ipv4.ip_forward = 1
6
7# SNAT规则
8[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ens37 -j SNAT --to-source 192.168.3.1
9或
10[root@localhost ~]# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o ens37 -j MASQUERADE
DNAT
1#开启路由转发功能
2[root@localhost ~]# cat /etc/sysctl.conf
3net.ipv4.ip_forward = 1
4[root@localhost ~]# sysctl -p
5net.ipv4.ip_forward = 1
6
7# 开启DNAT功能
8[root@localhost ~]# iptables -t nat -A PREROUTING -d 192.168.3.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.2