安全运维 | iptable使用详解

2022-12-11 10:57:31 浏览数 (1)

声明:本人坚决反对利用文章内容进行恶意攻击行为,一切错误行为必将受到惩罚,绿色网络需要靠我们共同维护,推荐大家在了解技术原理的前提下,更好的维护个人信息安全、企业安全、国家安全。

iptables的前身叫ipfirewall(内核1.x时代),这是一个作者从freeBSD上移植过来的,能够工作在内核当中的,对数据包进行检测的一款简易访问控制工具。但是ipfirewall工作功能极其有限(它需要将所有的规则都放进内核当中,这样规则才能够运行起来,而放进内核,这个做法一般是极其困难的)。当内核发展到2.x系列的时候,软件更名为ipchains,它可以定义多条规则,将他们串起来,共同发挥作用,而现在,它叫做iptables,可以将规则组成一个列表,实现绝对详细的访问控制功能。

他们都是工作在用户空间中,定义规则的工具,本身并不算是防火墙。它们定义的规则,可以让在内核空间当中的netfilter来读取,并且实现让防火墙工作。而放入内核的地方必须要是特定的位置,必须是tcp/ip的协议栈经过的地方。而这个tcp/ip协议栈必须经过的地方,可以实现读取规则的地方就叫做 netfilter.(网络过滤器)。

为什么已经在进出的口设置了关卡之后还要在内部设置关卡呢?由于数据包尚未进行路由决策,还不知道数据要走向哪里,所以在进出口是没办法实现数据过滤的。所以要在内核空间里设置转发的关卡,进入用户空间的关卡,从用户空间出去的关卡。

这五个位置被称为五个钩子函数(hookfunctions),也叫五个规则链。这是NetFilter规定的五个规则链,任何一个数据包,只要经过本机,必将经过这五个链中的其中一个链。

  • PREROUTING (路由前)
  • INPUT (数据包流入口)
  • FORWARD (转发关卡)
  • OUTPUT(数据包出口)
  • POSTROUTING(路由后)

1

iptable常用策略

iptable策略一般分为两种,一种叫“通”策略,一种叫“堵”策略,通策略,默认门是关着的,必须要定义谁能进。堵策略则是,大门是敞开的,但是你必须有身份认证,否则不能进。当我们定义策略的时候,要分别定义多条功能,其中:定义数据包中允许或者不允许的策略,filter过滤的功能,而定义地址转换的功能的则是nat选项。为了让这些功能交替工作,制定出了“表”这个定义,来定义、区分各种不同的工作功能和处理方式。

使用最多的3个功能如下所示:

filter :定义允许或者不允许的,只能做在3个链上:INPUT ,FORWARD ,OUTPUT

nat:定义地址转换的,只能做在3个链上:PREROUTING ,OUTPUT ,POSTROUTING

mangle:修改报文原数据,是5个链都可以做:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING

2

环境安装

代码语言:javascript复制
安装iptables管理命令
$ yum -y install iptables-services

加载防火墙的内核模块
$ modprobe ip_tables
$ modprobe iptable_filter
$ modprobe iptable_nat
$ modprobe ip_conntrack
$ modprobe ip_conntrack_ftp
$ modprobe ip_nat_ftp
$ modprobe ipt_state
$ lsmod |egrep 'filter|nat|ipt'  # 查看已经加载的模块

启动iptables
$ systemctl stop firewalld && systemctl disable firewalld
$ systemctl start iptables && systemctl enable iptables

3

基础命令

(1)iptable帮助信息

代码语言:javascript复制
-t, --table table:对指定的表 table 进行操作, table 必须是 raw, nat,filter,mangle 中的一个。如果不指定此选项,默认的是 filter 表。
 
# 通用匹配:源地址目标地址的匹配
-p:指定要匹配的数据包协议类型;
-s, --source [!] address[/mask] :把指定的一个/一组地址作为源地址,按此规则进行过滤。当后面没有 mask 时,address 是一个地址,比如:192.168.1.1;当 mask 指定时,可以表示一组范围内的地址,比如:192.168.1.0/255.255.255.0。
-d, --destination [!] address[/mask] :地址格式同上,但这里是指定地址为目的地址,按此进行过滤。
-i, --in-interface [!] <网络接口name> :指定数据包的来自来自网络接口,比如最常见的 eth0 。注意:它只对 INPUT,FORWARD,PREROUTING 这三个链起作用。如果没有指定此选项, 说明可以来自任何一个网络接口。同前面类似,"!" 表示取反。
-o, --out-interface [!] <网络接口name> :指定数据包出去的网络接口。只对 OUTPUT,FORWARD,POSTROUTING 三个链起作用。
 
# 查看管理命令
-L, --list [chain] 列出链 chain 上面的所有规则,如果没有指定链,列出表上所有链的所有规则。
 
# 规则管理命令
-A, --append chain rule-specification 在指定链 chain 的末尾插入指定的规则,也就是说,这条规则会被放到最后,最后才会被执行。规则是由后面的匹配来指定。
-I, --insert chain [rulenum] rule-specification 在链 chain 中的指定位置插入一条或多条规则。如果指定的规则号是1,则在链的头部插入。这也是默认的情况,如果没有指定规则号。
-D, --delete chain rule-specification -D, --delete chain rulenum 在指定的链 chain 中删除一个或多个指定规则。
-R num:Replays替换/修改第几条规则
 
# 链管理命令(这都是立即生效的)
-P, --policy chain target :为指定的链 chain 设置策略 target。注意,只有内置的链才允许有策略,用户自定义的是不允许的。
-F, --flush [chain] 清空指定链 chain 上面的所有规则。如果没有指定链,清空该表上所有链的所有规则。
-N, --new-chain chain 用指定的名字创建一个新的链。
-X, --delete-chain [chain] :删除指定的链,这个链必须没有被其它任何规则引用,而且这条上必须没有任何规则。如果没有指定链名,则会删除该表中所有非内置的链。
-E, --rename-chain old-chain new-chain :用指定的新名字去重命名指定的链。这并不会对链内部造成任何影响。
-Z, --zero [chain] :把指定链,或者表中的所有链上的所有计数器清零。
 
-j, --jump target <指定目标> :即满足某条件时该执行什么样的动作。target 可以是内置的目标,比如 ACCEPT,也可以是用户自定义的链。
-h:显示帮助信息;

(2)查看iptables规则

代码语言:javascript复制
$ iptables -L    # 查看iptables规则
$ iptables -L -vn   # 查看iptables规则(详细信息)

$ iptables -L -t nat                  # 列出 nat 上面的所有规则 -t 参数指定,必须是 raw, nat,filter,mangle 中的一个
$ iptables -L -t nat  --line-numbers  # 规则带编号
$ iptables -L INPUT

(3)清空iptables规则

代码语言:javascript复制
$ iptables -F   # 清除所有规则,不会处理默认的规则
$ iptables -X   # 删除用户自定义的链
$ iptables -Z   # 链的计数器清零(数据包计数器与数据包字节计数器)

(4)添加iptables规则

代码语言:javascript复制
$ iptables -t   # 指定表(default: `filter')
$ iptables -A   # 把规则添加到指定的链上,默认添加到最后一行
$ iptables -I   # 插入规则,默认插入到第一行(封IP)
$ iptables -D   # 删除链上的规则

(5)删除某条规则

代码语言:javascript复制
$ iptables -nL --line-numbers   # 查看规则号码
$ iptables -D INPUT 1           # 删除指定链上的指定序号

(6)保存iptables规则

代码语言:javascript复制
$ iptables-save > 1.txt  #将防火墙规则保存到文件中
$ iptables-save  #将防火墙规则保存到配置文件中,防止重启后失效
$ iptables-restore < 1.txt #从配置文件里载入防火墙配置

注意:你所定义的所有内容,当你重启的时候都会失效,要想我们能够生效,需要使用一个命令将它保存起来
1.service iptables save 
它会保存在/etc/sysconfig/iptables这个文件中
2.iptables-save 命令
iptables-save > /etc/sysconfig/iptables

3.iptables-restore 命令
开机的时候,它会自动加载/etc/sysconfig/iptabels
如果开机不能加载或者没有加载,而你想让一个自己写的配置文件(假设为iptables.2)手动生效的话:
iptables-restore < /etc/sysconfig/iptables.2
则完成了将iptables中定义的规则手动生效

4

黑/白名单配置

(1)允许本地回环地址可以正常使用

代码语言:javascript复制
$ iptables -A INPUT -i lo -j ACCEPT
$ iptables -A OUTPUT -o lo -j ACCEPT
# 本地圆环地址就是那个127.0.0.1,是本机上使用的,它进与出都设置为允许

(2)设置默认规则

代码语言:javascript复制
$ iptables -P INPUT DROP # 配置默认的不让进
$ iptables -P FORWARD DROP # 默认的不允许转发
$ iptables -P OUTPUT ACCEPT # 默认的可以出去

(3)配置白名单

代码语言:javascript复制
$ iptables -A INPUT -p all -s 192.168.1.0/24 -j ACCEPT  # 允许内网机器可以访问
$ iptables -A INPUT -p all -s 192.168.140.0/24 -j ACCEPT  # 允许内网机器可以访问
$ iptables -A INPUT -p tcp -s 183.121.3.7 --dport 3380 -j ACCEPT # 允许183.121.3.7访问本机的3380端

(4)配置黑名单

代码语言:javascript复制
$ iptables -I INPUT -p tcp -s 192.168.1.253 -i ens33 -j DROP
$ iptables -A INPUT -p tcp ! -s 192.168.1.1 -i ens33 -j DROP
$ iptables -A INPUT -p tcp ! -s 192.168.1.0/24 -i ens33 -j DROP

选项解释:
-s # 指定源地址或网段(192.168.1.0/24)。! 取反;
-d # 指定目的地址(nat表prerouting);
-i # 进入的网络接口(ens33,ens37);
-o # 出去的网络接口(ens33,ens37);

(5)访问端口

代码语言:javascript复制
$ iptables -I INPUT -p tcp -m multiport --dport 21,22,23,24 -j DROP
$ iptables -I INPUT -p tcp --dport 3306:8809 -j ACCEPT    # 3306端口-8809端口
$ iptables -I INPUT -p tcp --dport 18:80 -j DROP
$ iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT   # 允许本地回环接口(即运行本机访问本机)
$ iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许已建立的或相关连的通行
$ iptables -A OUTPUT -j ACCEPT         # 允许所有本机向外的访问
$ iptables -A INPUT -p tcp --dport 22 -j ACCEPT    # 允许访问22端口
$ iptables -A INPUT -p tcp --dport 80 -j ACCEPT    # 允许访问80端口
$ iptables -A INPUT -p tcp --dport 21 -j ACCEPT    # 允许ftp服务的21端口
$ iptables -A INPUT -p tcp --dport 20 -j ACCEPT    # 允许FTP服务的20端口
$ iptables -A INPUT -j reject      # 禁止其他未允许的规则访问
$ iptables -A FORWARD -j REJECT     # 禁止其他未允许的规则访问

5

DNAT/SNAT映射配置

在传统的标准的TCP/IP通信过程中,所有的路由器仅仅是充当一个中间人的角色,也就是通常所说的存储转发,路由器并不会对转发的数据包进行修改,更为确切的说,除了将源MAC地址换成自己的MAC地址以外,路由器不会对转发的数据包做任何修改。NAT (Network Address Translation,网络地址转换)恰恰是出于某种特殊需要而对数据包的源ip地址、目标ip地址、源端口、目标端口进行改写的操作。利用iptables的内置表NAT可以实现上述功能

iptables NAT的三个链:PREROUTING,POSTROUTING,OUTPUT

PREROUTING:可以在这里定义进行目标地址NAT的规则,因为路由器进行路由时只检查数据包的目标ip地址,所以为了使数据包得以正确路由,我们必须在路由之前就进行目的NAT

POSTROUTING:可以在这里定义进行源地址NAT的规则,系统在决定了数据包的路由以后在执行该链中的规则

OUTPUT:定义对本地产生的数据包的目的NAT规则

NAT处理的动作选项

代码语言:javascript复制
SNAT:源地址转换,改变数据包的源地址,常接选项--to-source
DNAT:目标址转换,改变数据包的目标地址,常接选项--to-destination
MASQUERADE:地址伪装,适用于ADSL等动态拨号上网的IP伪装
REDIRECT:端口映射,通常用实现透明代理和对外开放内网某些服务,常接选项--to-ports

三个链支持的处理动作

代码语言:javascript复制
PRERROUTING:DNAT,REDIRECT  对目标地址进行修改,支持-o选项(路由之前)
POSTROUTING:SNAT,MASQUERADE  对源地址进行修改,支持-i选项(路由之后)
OUTPUT:DNAT,REDIRECT     处理来自NAT主机本身生成的出站数据包(本机)    

注意:要实现NAT,首先要打开核心转发功能

代码语言:javascript复制
[root@localhost ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

如果永久生效的话,编辑/etc/sysctl.conf文件,修改成net.ipv4.ip_forward = 1,然后执行sysctl -p可以立即生效

(1)SNAT:隐藏内网主机ip地址,也可以实现共享公网ip上网

源地址是192.168.1.0/24转化成172.16.8.9

代码语言:javascript复制
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 172.16.8.9

(2)DNAT:可以通过公网ip访问局域网内的服务

访问172.16.8.9的80端口时,会映射到192.168.1.9的8080端口

代码语言:javascript复制
# iptables -t nat -A PREROUTING -d 172.16.8.9 -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.9:8080

(3)MASQUERADE:ADSL拨号上网,可以认为是SNAT的一种特殊情况(转换地址是动态的)

代码语言:javascript复制
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

4.REDIRECT:在本机上进行端口映射,可以认为是DNAT的一种特殊情况(目标地址是本机)

访问本机21端口时,会被映射到2121端口

代码语言:javascript复制
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 21 -j REDIRECT --to-ports 2121

6

场景应用

代码语言:javascript复制
$ iptables -L -F -A -D   # list flush append delete
# 场景一
$ iptables -I INPUT -p tcp --dport 80 -j ACCEPT # 允许 tcp 80 端口
$ iptables -I INPUT -p tcp --dport 10:22 -j ACCEPT # 允许 tcp 10-22 端口
$ iptables -I INPUT -p icmp -j ACCEPT # 允许 icmp
$ iptables -A INPUT -j REJECT # 添加一条规则, 不允许所有
 
# 优化场景一
$ iptables -I INPUT -i lo -j ACCEPT # 允许本机访问
$ iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许访问外网
$ iptables -I INPUT -p tcp --dport 80 -s 10.10.188.233 -j ACCEPT # 只允许固定ip访问80
 
# 场景二
$ vi /etc/vsftpd/vsftpd.conf # 使用 vsftpd 开启 ftp 主动模式
port_enable=yes
connect_from_port_20=YES
$ iptables -I INPUT -p tcp --dport 21 -j ACCEPT
 
$ vi /etc/vsftpd/vsftpd.conf # 建议使用 ftp 被动模式
pasv_min_port=50000
pasv_max_port=60000
$ iptables -I INPUT -p tcp --dport 21 -j ACCEPT
$ iptables -I INPUT -p tcp --dport 50000:60000 -j ACCEPT
 
# 还可以使用 iptables 模块追踪来自动开发对应的端口
 
# 场景三
$ iptables -I INPUT -i lo -j ACCEPT # 允许本机访问
$ iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许访问外网
$ iptables -I INPUT -s 10.10.155.0/24 -j ACCEPT # 允许内网访问
$ iptables -I INPUT -p tcp -m multiport --dports 80,1723 -j ACCEPT # 允许端口, 80 -> http, 1723 -> vpn
$ iptables -A INPUT -j REJECT # 添加一条规则, 不允许所有
 
$ iptables-save # 保存设置到配置文件
 
# 场景四
$ iptables -t nat -L # 查看 nat 配置
 
$ iptables -t nat -A POST_ROUTING -s 10.10.177.0/24 -j SNAT --to 10.10.188.232 # SNAT
$ vi /etc/sysconfig/network # 配置网关
 
$ iptables -t nat -A POST_ROUTING -d 10.10.188.232 -p tcp --dport 80 -j DNAT --to 10.10.177.232:80 # DNAT
 
#场景五
$ iptables -I INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT # 限制并发连接访问数
$ iptables -I INPUT -m limit --limit 3/hour --limit-burst 10 -j ACCEPT # limit模块; --limit-burst 默认为5

7

注意事项

1) 修改之前导出备份一份; 2)修改时小心,别把自己的IP地址封禁; 3) 可以先在定时任务中添加一条定时清空的规则,等测试没有问题再取消定时任务;

-END-

0 人点赞