iptables防火墙

iptables防火墙

基于Netfilter模块,linux系统内核自带功能,rhel8之前使用iptables工具管理,之后改为使用firewalld工具

基本原理

netfilter的hook function(钩子函数):

  • prerouting
  • input
  • output
  • forward
  • postrouting

链(内置):

  • PREROUTING
  • INPUT
  • OUTPUT
  • FORWARD
  • POSTROUTING

表:

  • filter:过滤、防火墙
  • nat:地址转换,用于修改源ip、目标ip、端口
  • mangle:拆解报文,做修改,并重新封装
  • raw:关闭nat表上启用的连接追踪机制
  • security
每个表可用链:

规则匹配优先级顺序,以下为准

  1. raw: PREROUTING、OUTPUT
  2. mangle: PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
  3. nat: PREROUTING、INPUT、OUTPUT、POSTROUTING
  4. filter:INPUT、FORWARD、OUTPUT

报文流向

image

规则:

组成部分:

  • 匹配条件:
    • 基本匹配条件。
    • 扩展匹配条件,由模块定义
  • 处理动作:
    • 基本处理动作
    • 扩展处理动作,模块定义
    • 自定义

iptables链: 内置和自定义

内置,对应于hook function
自定义,用于内置链的扩展和补充,实现更灵活管理

规则定义注意:

  • 同类规则(访问同意应用),匹配范围小的放上面
  • 不同类的规则(访问不应用),匹配到报文频率较大的放在上面
  • 将那些可由同一条规则描述的多个规则合并起来
  • 设置默认策略

iptables命令:

高度模块化,由诸多扩展模块实现其他检查条件或处理动作的定义
模块目录:

/usr/lib64/xtables/

其中ipv6是libip6_,ipv4是libt_ 、libxt

iptables-service包:

rhel8单独提供的服务包,可以systemd管理

  • iptables-save,保存规则
  • iptables-restore,重载
  • iptables-apply,安全更新规则
  • iptables-restore-translate,格式转换为nfttables规则(nfttables下一篇将)

iptables-restore

iptables-restore [选项]

-n 		不清除原有规则。文件重载会把iptables已有的内容清
-t 		仅分析生成规则集,不提交

iptables命令

iptables [-t table] comm chain [扩展匹配条件 options] [-j target target-options]

-t table		raw,mangle,nat,filter(默认)

comm部分详解:

链管理:
    -N	新建一条自定义规则链
    -X	删除一条自定义链(内部没有规则定义)
    -P 	设置默认策略,对filter表,策略支持:
      ACCEPT	接收
      DROP	丢弃
      REJECT	拒绝
    -E	重命名自定义链,引用计数不为0的自定义链不能被重命名,也不可被删除(也就是内部无规则定义)
规则管理:
    -A 	追加,默认filter
    -I 	插入,不指明位置默认第一条
    -D 	删除。
      指明规则序号
      指明规则本身
    -R 	替换指定链上的规则
    -F 	清空指定规则链
    -Z	清零,比如流量计数
      iptables每条规则都有两个计数器
      1.匹配到的报文的个数
      2.匹配到的所有报文大小之和
查看:
    -L	列出指定链的所有规则,默认filter
    ***以下补充参数都要写在L前面,或单独-
      -n 	以数字格式显示地址和端口号
      -v 	显示详细信息,v越多越详细
      -x 	显示计数器结果的精确值(非四舍五入结果)
      --line-numbers	显示规则序号
      --modprobe=command

chain部分:

  • PREROUTING
  • INPUT
  • FORWARD
  • OUTPUT
  • POSTROUTING

匹配条件:

基本匹配条件:

无需加载模块,自行提供的。
“!”是取反意思

[!] -s ip/mask 	指定源地址。s为本机
[!] -d ip/mask 	目标地址,d为远程主机
[!] -p 协议		支持tcp、udp、udplite、icmp、icmpv6、esp、ah、sctp、mh。all为支持所有
[!] -i 网卡		数据流入接口,用于PREROUTING、INPUT、FORWARD
[!] -o 网卡 	数据流出接口,应用于FORWARD、OUTPUT、POSTROUTING链
扩展匹配条件:

要加载模块

  • 隐式扩展:不用手动加载模块,用的是协议模块,不用在-p 之前使用“-m ”
  • 显式扩展:必须使用-m 选项指明模块
隐式扩展

tcp:

--sport 端口[:port]		匹配报文源端口,支持范围
[!] --dport 端口[:port]		目标端口,支持范围
[!] --tcp-flags mask comp 	表示匹配三次握手的内容是否符合
  mask 为要检查的内容
  comp 以这个定义的为准
如:
  --tcp-flags SYN,ACK,FIN,RST SYN #表示检查tcp握手的标志位SYN,ACK,FIN,RST四个,其中SYN必须为1,其他必须为0
  --tcp-flags ALL ALL
  --tcp-flags ALL NONE
[!] --syn 	用于匹配tcp第一次握手,作用同上

udp:

[!] --sport 端口[:端口]
[!] --dport 端口[:端口]

icmp:
注意:如果需要允许icmp,需要防火墙和内核都是配置,两者都受限制

#1为禁用所有,0为默认允许
icmp_echo_ignore_all = 0

icmp-typev {type[/code]或typename}	#可百度icmp-type查看类型和代码含义
    echo-request:8	#ping的请求是8
    echo-reply:0/0	#ping的返回结果是0/0
显式扩展:

multiport

以离散或连续的方式,定义多个端口匹配条件,最多15个,支持tcp,udp,udplite,dccp,sctp

[!] --sports 端口[,端口 or ,端口:端口]
[!] --dports 端口[,端口 or ,端口:端口]

例:

iptables -A INPUT -d 192.168.65.7 -p tcp -m multiport --dports 22,80,3306,... -j ACCEPT

iprange:

以连续地址的方式来指明多ip地址匹配条件

[!] --src-range 192.168.0.1-192.168.0.100
[!] --det-range 192.168.0.1-192.168.0.100

time:

设置访问时间段

--timestart 10:00[:00]
--timestop 10:10[:00]
[!] --weekdays [1-7]
[!] --monthdays day
--kerneltz 		使用内核配置的时区,而非硬件时钟

例:

#允许2.2.规定的ip,在周一至周五,10点到16点之间(用时区时间),访问1.1.的23端口
iptables -I INPUT -d 1.1.1.10 -p tcp --dport 23 -m iprange --src-range 2.2.2.10-2.2.2.30 -m time --timestart 10:00 --timestop 16:00 --weekdays 1,2,3,4,5 --kerneltz -j ACCEPT

string:

数据包内容的字符串检查,只对明文协议有用,加密无效

--algo {bm|kmp}		必须项。基于哪种字符匹配算法
[!] --string "字符"		过滤的字符串
[!] --hex-string "字符"		支持16进制字符
--from 起始位		字符匹配从哪位开始
--to 结束位

例:

#数据中字符串有gay的字符,拒绝出站,用bm算法
iptables -I OUTOUT -m string --alge bm --string "gay" -j REJECT	

connlimit:

单ip并发连接数限制

--connlimit-upto 5	0	5个以内允许连接。如果策略是drop,那么为白名单
--connlimit-above 20    大于20拒绝。如果策略是drop,那么小于该数为白名单

例:

#2.2.2连接1.1.1的23端口,数量超过2个以上就拒接
iptables -I INPUT -d 1.1.1.10 -p tcp --dport 23 -s 2.2.2.20 -m connlimit --connlimit-upto 2 -j REJECT

limit:

令牌桶限制。令牌桶为每个进程,内核申请调用后,发数据,每一次发送都要拿一个令牌才能发,令牌可以做每秒内次数限制(1s3次),如果进程只用了一个令牌,它可以把令牌攒起来(令牌桶中),limit可限制桶中只能攒多少、每秒发多少令牌

注:可用hping3(网络攻击)工具来测试发包

--limit 速率[/second/minute/hour/day]		限制每s/m/h发包速率
--limit-burst 10	可最多收集10个令牌

例:

#访问1.1.主机80端口的tcp入站请求,限制每秒收100个,令牌桶最大攒5个,多出来的匹配策略组
iptables -I INPUT -d 1.1.1.10 -p tcp --dport 80 --syn -m limit --limit 100/second --limit-burst 5 -j ACCEPT

state:

传输层、网络层的连接追踪。默认两层是没有访问记忆的,所以在内核中开启一段内存,用于记录请求的tcp、udp访问过程、信息,断开连接后,该记录存放一定时间后清零。
清零之前再次访问直接进来,清零后重新通过。而内核中的内存空间,访问量大时会被占满,所以3种解决:

  1. 关闭连接追踪
  2. 开辟的内存空间调大
  3. 改超时时间长短
[!] --state 状态
  状态:
    NEW		新记录
    ESTABLISHED		记录后开始连接并未删除
    UNTRACKED		raw关闭nat表的追踪功能
    RELATED		新记录,用的新端口或协议,但与之前的new记录有关联,记录以后,再次连接都叫established
    INVALID 	无法识别、不合法的连接

依赖内核模块:

nf_conntrack
nf_conntrack_ipv4

加载模块:

#手动
modprobe nf_conntrack_ftp

#配置文件加载
vim /etc/sysconfig/iptables-config
IPTABLES_MODULES="nf_conntrack_ftp"

查看追踪信息:

  • 已追踪的连接记录位置:/proc/net/nf_conntrack
  • 调整记录的数量最大值:/proc/sys/net/nf_conntrack_max
  • 超时时长:/proc/sys/net/netfilter/*timeout*

例:
实现安全入网,木马程序禁止出站的功能,或可让别人established、new状态进来,除了established出站,其他拒绝

#入站

iptables -I INPUT -p tcp -m multiport --dports 22,23,80,443 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -j DROP

#出站
iptables -A OUTPUT -s 1.1.1.1 -m state --state ESTABLISHED -j ACCEPT

target(处理动作):

简单动作:
  • ACCEPT
  • DROP,丢弃包,也是无底洞,使用丢弃时
扩展动作:

在特殊表中,有特殊的动作,在下面nat表中继续描述

REJECT

拒绝包

--reject-with 拒绝类型
类型:
  icmp-net-unreachable	网络不可达
  icmp-host-unreachable	主机不可达
  icmp-port-unreachable	默认。端口不可用
  icmp-proto-unreachable	协议
  icmp-net-prohibited		网络被禁止
  icmp-host-prohibited	主机被禁止
  icmp-admin-prohibited	管理被禁止
LOG

客户端访问记录日志,默认存于/var/log/messages/
注:使用时应放在第一条规则,一般不开,写日志可能影响性能

--log-level		日志级别
--log-prefix	日志文件名前缀

例:

iptables -I INPUT -d 1.1.1.10 -p tcp --dport 22 -m state --state NEW -j LOG --log-prefix "is ssh access: "
RETURN

在调用过程中返回主链,在自定义链中使用,需要做高级规则时可使用,docker、k8s、istio中常见

自定义链做为target

调用自定义链的过程相当于程序中if语句的过程

例:
#新建自定义链
iptables -N in_ping_rule
iptables -A in_ping_rule -s 2.2.2.2 -p tcp --dport 22 -j REJECT 	#自定义链中加入规则
iptables -I INPUT 2 -s 2.2.2.2 -p tcp -j in_ping_rule		#INPUT引用,第2条,当源地址2.2.为tcp时,处理交给in_ping_rule自定义链匹配

#删除自定义链
iptables -D INPUT 2		#删除引用
iptables -F in_ping_rule	#清空自定义链内容
iptables -X in_ping_rule	#删除链

规则保存和载入:

#保存iptables规则到文件,文件路径可自选,非固定
iptables-save > /etc/sysconfig/iptables-2021.v1

#重载文件,把文件中的命令加载到iptables
iptables-restore < /etc/sysconfig/iptables-2021.v1

规则优化思路:

使用自定义链管理特定应用的相关规则,模块化管理规则

  1. 优先放行双方向状态为ESTABLISHED的报文
  2. 服务于不同类型的功能的规则,匹配到报文可能性更大的放前面
  3. 服务于同一类型的功能的规则,匹配条件较为严格的放前面
  4. 设置默认策略(白名单机制)。不建议“iptables -P ”设置默认策略,建议最后一条写全部拒绝

案例

filter表

例1:实现拒绝所有人访问
#方法1:有小风险,如果-F了,凉凉,只能主机改
iptables -P INPUT DROP
iptables -P OUPUT DROP

#方法2:不改默认策略,只设置网卡不能入站,风险较上面小
iptables -I INPUT -i 网卡 -j REJECT
iptables -I OUTPUT -o 网卡 -j REJECT	
例2:我ping别人,别人ping不通我
iptables -I OUPUT 2 -d 192.168.65.7 -p icmp --icmp-type 8 -j ACCEPT		#允许8 类型代码访问外部
iptables -I INPUT 2 -d 192.168.65.7 -p icmp --icmp-type 0/0 -j ACCEPT	#允许0/0 类型代码返回主机

forward表

例:允许客户机访问服务器

在内网环境中,使用1台linux主机当防火墙,所有内网主机通过防火墙主机访问外网
一般内核转发功能没有开通,网关的两个网卡,同一主机内可以互ping,但不能ping另外主机

节点 ip
客户机 1.1.1.10/24
网关 1.1.1.1/24、2.2.2.1/16
web服务器 2.2.2.20/16
1)网关开启内核转发
echo  “”net.ipv4.ip_forward=1" > /etc/sysctl.conf 
2)添加两台机器的路由

场景1:两台主机的网关不指向本次实验网关机

#客户机添加
route add -net 2.2.2.0/16 gw 1.1.1.1

#web服务器添加
route add -net 1.1.1.10/24 gw 2.2.2.1

场景2:两台主机的网关指向本次实验网关机

#网关添加
route add -net 1.1.1.0/24 gw 1.1.1.1
route add -net 2.2.2.0/16 gw 2.2.2.1
3)允许访问web服务
#网关添加
iptables -A FORWARD -j REJECT
iptables -I FORWARD -d 2.2.0.0/16 -p tcp --sport 80 -j ACCEPT		#只允许通过80端口访问外网
iptables -I FORWARD -s 1.1.1.0/24 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -I FORWARD -d 2.2.2.20 -m state --state RELATED -j ACCEPT 
#以上三条条开放内网访问外网

nat表

特殊动作

  • SNAT,转换源地址,改变数据包的源地址
  • MASQUERADE,IP伪装,只适用于ADSL等动态拨号上网的IP伪装,如果主机IP是静态分配的,就用snat
  • DNAT,目的地址转换,改变数据包的目的地址
  • REDIRECT,端口重定向,只用在本地的端口映射,可将本地80转到8080上

环境

节点 ip
内网 1.1.1.10
网关 1.1.1.1、 2.2.2.1
外网 2.2.2.20
例1:snat模式,内ip-->网关ip-->外

2.2.2.20上抓包,显示结果已经变化

#1.1.1.0/24网段访问外网时,源ip都改用1.1.1.1
iptables -t nat -A PREROUTING -s 1.1.1.0/24 -j SNAT --to-source 2.2.2.1
例2:MASQUERADE模式
iptables -t nat -I POSTROUTING -s 1.1.1.0/24 -j MASQUERADE
例3:DNAT模式
#访问网关的80时转到1.1.1.10:8080
iptables -t nat -I PREROUTING -d 2.2.2.1/24 -p tcp --dport 80 -j DNAT --to-destination 1.1.1.10:8080
例4:REDIRECT模式
#访问 1.1.1.10:80,转为访问本地8080
iptables -A PREROUTING -t nat -d 1.1.1.10 -p tcp --dport 80 -j REDIRECT --to-ports 8080

生产环境案例

*filter
:INPUT ACCEPT [85890:4530430]
:FORWARD ACCEPT [76814:55698470]
:OUTPUT ACCEPT [166620:238017546]
-A FORWARD -s 172.16.0.100/32 -j ACCEPT 
-A FORWARD -s 172.16.0.200/32 -j ACCEPT 
-A FORWARD -s 172.16.0.67/32 -j ACCEPT
#-A FORWARD -s 172.16.0.0/16 -j ACCEPT
#-A FORWARD -s 172.18.0.0/16 -j ACCEPT
#-A FORWARD -s 172.18.0.0/16 -j REJECT
#-A FORWARD -s 172.16.0.68/32 -j ACCEPT 
#-A FORWARD -s 172.16.0.69/32 -j ACCEPT 
#-A FORWARD -s 172.16.0.6/32 -j ACCEPT 
-A FORWARD -s 172.17.200.200/32 -j ACCEPT 
-A FORWARD -s 172.17.136.136/32 -j ACCEPT 
-A FORWARD -s 172.17.0.100/32 -j ACCEPT 
-A FORWARD -s 172.18.100.1/32 -j ACCEPT 
-A FORWARD -s 172.18.0.100/32 -j ACCEPT 
-A FORWARD -s 172.18.200.2/32 -j ACCEPT 
-A FORWARD -s 172.18.200.3/32 -j ACCEPT 
-A FORWARD -s 172.18.211.211/32 -j ACCEPT 
-A FORWARD -s 172.18.212.212/32 -j ACCEPT 
-A FORWARD -m iprange --src-range 172.16.0.100-172.16.0.110 -j ACCEPT 
-A FORWARD -m iprange --src-range 172.17.0.100-172.17.0.110 -j ACCEPT 
-A FORWARD -m iprange --src-range 172.18.0.100-172.18.0.110 -j ACCEPT 
-A FORWARD -m iprange --src-range 172.17.100.6-172.17.100.16 -j ACCEPT 
-A FORWARD -m iprange --src-range 172.18.100.61-172.18.100.70 -j ACCEPT 
-A FORWARD -s 172.16.0.0/16 -m string --string "verycd.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.16.0.0/16 -m string --string "tudou.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.16.0.0/16 -m string --string "youku.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.16.0.0/16 -m string --string "iqiyi.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.16.0.0/16 -m string --string "pptv.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.16.0.0/16 -m string --string "letv.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.16.0.0/16 -m string --string "xunlei.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.18.0.0/16 -m string --string "verycd.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.18.0.0/16 -m string --string "tudou.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.18.0.0/16 -m string --string "youku.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.18.0.0/16 -m string --string "iqiyi.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.18.0.0/16 -m string --string "pptv.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.18.0.0/16 -m string --string "letv.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -s 172.18.0.0/16 -m string --string "xunlei.com" --algo kmp --to 65535 -j REJECT --reject-with icmp-port-unreachable
#-A FORWARD -s 172.18.0.0/16 -j REJECT
#-A FORWARD -s 172.16.0.0/16 -j REJECT
#-A FORWARD -i ppp0 -m string --string ".exe" --algo bm --to 65535 -j REJECT --reject-with icmp-port-unreachable 
-A FORWARD -s 172.18.0.0/16 -m time --timestart 08:50:00 --timestop 18:00:00 --weekdays Mon,Wed,Fri  --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmp-port-unreachable 
-A FORWARD -s 172.17.0.0/16 -m time --timestart 08:50:00 --timestop 18:00:00 --weekdays Mon,Wed,Fri  --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmp-port-unreachable 
-A FORWARD -s 172.16.0.0/16 -m time --timestart 08:50:00 --timestop 12:30:00 --weekdays Tue,Thu,Sat  --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmp-port-unreachable 
-A FORWARD -s 172.16.0.0/16 -m time --timestart 13:50:00 --timestop 18:00:00 --weekdays Tue,Thu,Sat  --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmp-port-unreachable 
#-A FORWARD -s 172.17.0.0/16 -m time --timestart 08:50:00 --timestop 12:30:00 --weekdays Mon,Wed,Fri --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmp-port-unreachable 
#-A FORWARD -s 172.17.0.0/16 -m time --timestart 13:30:00 --timestop 18:10:00 --weekdays Mon,Wed,Fri --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmp-port-unreachable 
#-A FORWARD -s 172.18.0.0/16 -m time --timestart 08:50:00 --timestop 18:10:00 --weekdays Mon,Wed,Fri --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmp-port-unreachable 
#-A FORWARD -s 172.18.0.0/16 -m time --timestart 08:50:00 --timestop 18:10:00 --weekdays Tue,Thu --datestop 2038-01-19T11:14:07 -j REJECT --reject-with icmpport-unreachable 
COMMIT
*nat
:PREROUTING ACCEPT [1429833:65427211]
:POSTROUTING ACCEPT [850518:35452195]
:OUTPUT ACCEPT [120198:9146655]
-A POSTROUTING -s 172.16.0.100/32 -j MASQUERADE
-A POSTROUTING -s 172.18.0.100/32 -j MASQUERADE
#-A POSTROUTING -s 172.16.0.200/32 -j MASQUERADE
-A POSTROUTING -s 172.16.0.69/32 -j MASQUERADE
-A POSTROUTING -s 172.17.200.200/32 -j MASQUERADE
-A POSTROUTING -s 172.17.136.136/32 -j MASQUERADE
-A POSTROUTING -s 172.17.0.100/32 -j MASQUERADE
#-A POSTROUTING -s 172.18.0.0/16 -j MASQUERADE
#-A POSTROUTING -s 172.16.0.6/32 -j MASQUERADE
-A POSTROUTING -m iprange --src-range 172.16.0.100-172.16.0.110 -j MASQUERADE 
-A POSTROUTING -m iprange --src-range 172.17.0.100-172.17.0.110 -j MASQUERADE 
-A POSTROUTING -m iprange --src-range 172.18.0.100-172.18.0.110 -j MASQUERADE 
-A POSTROUTING -s 172.16.0.0/16 -p tcp -m multiport --dports 80,443,53,22,6666 -j MASQUERADE 
-A POSTROUTING -s 172.16.0.0/16 -p udp -m multiport --dports 22 -j MASQUERADE 
-A POSTROUTING -s 172.17.0.0/16 -p tcp -m multiport --dports 80,443,53,22,6666 -j MASQUERADE 
-A POSTROUTING -s 172.17.0.0/16 -p udp -m multiport --dports 22 -j MASQUERADE 
-A POSTROUTING -s 172.18.0.0/16 -p tcp -m multiport --dports 80,443,53,22,6666,1206,5938,1949 -j MASQUERADE 
-A POSTROUTING -s 172.18.0.0/16 -p udp -m multiport --dports 22,1206,5938,1949 -j MASQUERADE 
COMMIT
posted @ 2023-11-26 20:06  suyanhj  阅读(153)  评论(0)    收藏  举报