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