目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

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是否定义强制访问控制规则后加上的

表与链之间的关系

应用防火墙是以表为操作入口,只要在相应的表中的规则链上添加规则即可实现某一功能。

应该知道哪张表包括哪些规则链,在规则链上操作即可。

规则链
filterINPUT、FORWARD、OUTPUT
natPREROUTING、OUTPUT、POSTROUTING、INPUT
manglePREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
rawPREROUTING、OUTPUT
securityINPUT、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

作者:Soulboy