一、iptables
防火墙,实现网络报文的隔离作用,一般有两种:主机防火墙和网络防火墙。
linux的防火墙功能,主要靠内核态的netfilter模块实现,而iptables只是处于用户态的一个编写防火墙规则的工具而已。netfilter根据iptables制定的规则进行数据包的过滤
linux内核,在网络数据报文所必经的5个点各设置了一个勾子函数,对数据包进行拦截,然后进行过滤。
Linux防火墙是通过netfiler这个内核框架实现,netfiler用于管理网络数据包。不仅具有网络地址转换(NAT)的功能,也具备数据包内容修改、以及数据包过滤等防火墙功能。
利用运作于用户空间的应用软件,如iptables/firewalld/ebtables等来控制netfilter。Netfilter在内核协议栈中指定了五个处理数据包的钩子(hook),分别是PRE_ROUTING、INPUT、OUTPUT、FORWARD与POST_ROUTING,通过iptables/firewalld/ebtables等用户层工具向这些hook点注入一些数据包处理函数,这样当数据包经过相应的hook时,处理函数就被调用,从而实现包过滤功能。
这些用户层工具中,iptables工作在IP层,只能过滤IP数据包;ebtables工作在数据链路层,只能过滤以太网帧(比如更改源或目的MAC地址)
1、5链
所谓链,就是在网络数据报文所必经的5个点各设置了一个勾子函数,对数据报文进行处理。
-
PREROUTING,路由前,网卡接收到数据包之后
-
INPUT,到达本机的数据包,路由后
-
FORWARD,转发,目的地不是本机的数据包,一般作为路由器使用时才需要
-
UTPUT,从本机发出去的数据包,路由前
-
POSTROUTING,路由后,从接口发出去之前
对于linux主机,一个报文:
-
流入:FREROUTING----->INPUT
-
流出:OUTPUT---->POSTROUTING
-
转发:PREROUTING----->FORWARD---->POSTROUTING
2、4表
每个勾子函数所能做的事不尽相同,将能实现相同功能的链组织起来,形成一张表。
一张表就是一个功能,这个功能在哪些位置可以实现。
表 |
链 |
功能 |
内核模块 |
filter |
INPUT FORWARD OUTPUT |
负载过滤功能,也就是防火墙主要功能 |
iptable_filter |
nat |
PREFOUTING(DNAT) INPUT OUTPUT POSTROUTING(SNAT) |
负责网络地址转换 |
iptable_nat |
mangle |
REROUTING INPUT OUTPUT FORWARD POSTROUTING |
修改报文 |
iptable_mangle |
raw |
PREROUTING OUTPUT |
取消连接追踪 |
iptable_raw |
2.1、filter
实现数据包的过滤,也就是主机防火墙的功能
对应3个链:INPUT,FORWARD,OUTPUT
iptables -t filter -L
2.2、nat
网络地址转换,该模块以Connection Tracking(连接追踪)模块为基础,仅对每个连接的第一个报文进行匹配和处理,然后交由Connection Tracking模块将处理结果应用到该连接之后的所有报文。
nat仅对报文头的地址信息进行修改,而不修改报文内容,按所修改的部分,nat可分为源NAT(SNAT)和目的NAT(DNAT)两类,前者修改第一个报文的源地址部分,而后者则修改第一个报文的目的地址部分。
对应4个链:PREFOUTING(DNAT),INPUT,OUTPUT,POSTROUTING(SNAT)
iptables -t nat -L
2.3、mangle
对报文内容进行修改,实现数据报文的解封装,然后修改报文,最后重新封装
mangle表主要用于修改数据包的TOS(Type Of Service,服务类型)、TTL(Time To Live,生存周期)指以及为数据包设置Mark标记,以实现Qos(Quality Of Service,服务质量)调整以及策略路由等应用。
对应5个链:PREROUTING,INPUT,OUTPUT,FORWARD,POSTROUTING
iptables -t mangle -L
2.4、raw
所谓连接跟踪,跟踪并且记录每个连接的状态,比如:NEW,ESTABLISHED,RELATED,INVALID等状态,Neftiler为了实现基于数据连接状态侦测的状态防火墙功能和NAT地址转换功能才开发出了连接跟踪这套机制
因为raw表优先级最高,从而可以对收到的数据包在连接跟踪前进行处理。一但用户使用了RAW表,在某个链上,RAW表处理完后,将跳过NAT表和 ip_conntrack处理,即不再做地址转换和数据包的链接跟踪处理了.
RAW表可以应用在那些不需要做nat的情况下,以提高性能。如大量访问的web服务器,可以让80端口不再让iptables做数据包的链接跟踪处理,以提高用户的访问速度。
对应2个链:PREROUTING,OUTPUT
链可以在不同的表中被复用,同一个链在不同表中的规则是隔离的。
iptables -t raw -L
2.5、表的优先级
每个链上的不同表,也是有顺序的
表顺序:raw---->mangle---->nat---->filter
-
PREROUTING:raw---->mangle---->nat
-
INPUT:mangle---->filter
-
FORWARD:mangle---->filter
-
OUTPUT:raw---->mangle---->nat---->filter
-
POSTROUTING:mangle---->nat
3、查看规则
注意:
-
以表为单位进行查看
#查看filter表的INPUT链上的规则
iptables -t filter -L INPUT
#默认就是查看filter表的INPUT链,所以可以省略
iptables -L -n -v --line-numbers
-
-L,列出规则
-
-n,不做IP反解
-
-v,显示更详细的信息,可以加多个v,显示的更多
-
--line-numbers,显示规则编号
iptables -L -n --line-numbers
-
--line-numbers,表示查看规则的序列号
#查看nat表的规则
iptables -L -n -t nat
#查看所有规则,包括默认规则
iptables -S
4、清空规则
iptables -F|-X|-Z
-
-F,清除filter表中预设的所有规则
-
-X,清除filter表中自定义的链
-
-Z,清空计数器,默认,iptables会记录所过滤过的包的个数和大小
注意:
-
默认规则不会被清除
5、保存规则
iptables的规则保存路径:/etc/sysconfig/iptables
5.1、centos6
#保存规则,实际在做iptables-save > /etc/sysconfig/iptables
service iptables save
#启动iptables服务,实际在做iptables-restore < /etc/sysconfig/iptables
service iptables restart
注意:
-
iptables实际并没有启动守护进程,只是在运行脚本,保存或恢复规则
5.2、centos7
方法一:
/usr/libexec/iptables/iptables.init save
方法二:
iptables-save > /etc/sysconfig/iptables
6、设置规则
6.1、语法
iptables -t <表名,filter表可省略> <匹配的规则:-s -d -p等> \
-j <target目标:ACCEPT|DROP|QUEUE|RETURN|SNAT|DNAT>
链管理:
-
-F,清空规则
-
-N,新建自定义链
-
-X,删除自定义链
-
-Z,清0计数器
-
-P,为指定链设置默认策略
-
-E,重命名自定义链
规则管理:
-
-A,追加新规则至末尾
-
-I,插入新规则至指定位置
-
-D,删除规则
-
-R,替换指定规则
基本条件:
-
-s,指定源地址
-
-d,指定目的地址
-
-p,指定协议:tcp/udp/icmp
-
!,表示取反
-
-i,从哪个接口进来,用于IPNU、FORWARD、PREROUTING链
-
-o,从哪个接口出去,用于FORWARD、OUTPUT、POSTROUTING链
目标:
-
ACCEPT,接受
-
DROP,丢弃
-
REJECT,拒绝
-
RETURN,返回调用链,一般用在自定义链
-
REDIRECT,端口重定向
-
LOG,记录日志
-
MARK,防火墙标记
-
SNAT,源地址转换
-
DNAT,目标地址转换
-
MASQUERADE,地址伪装
-
NOTRACK,不跟踪,用于RAW表
-
自定义链,指定将报文转发至自定义链进行过滤
注意:
-
规则按从上往下顺序进行匹配,匹配到就不再往下匹配
-
如果所有规则都没有匹配上,使用默认规则
-
默认规则只能是DROP或ACCEPT,不能为REJECT
6.2、默认规则
#将FORWARD链的filter表的默认规则改成drop
#默认就是filter表
iptables -t filter -P FORWARD DROP
#将OUTPU链的nat表的默认规则改成DROP
iptabes -t nat -P OUTPUT DROP
6.3、追加
iptables -t filter -A INPUT -s 172.25.254.10/32 -j REJECT
-
-A,表示在filter表的INPUT链的最后面新增一条规则
#不允许ping
#在filter表最后追加一条策略
#默认就是filter表,所以不用指定表
iptables -t filter -A INPUT -p icmp -j DROP
#拒绝172.25.254.10这个IP来访问本要贩80,23端口
iptables -t filter -A INPUT -s 172.25.254.10/32 -p tcp --dport 80 \
-j REJECT
6.4、插入
iptables -t filter -I INPUT 2 -s 172.25.254.10/32 -j REJECT
-
-I,表示将这条规则插入到filter表的INPUT链的规则序号为2的位置
6.5、替换
iptables -t filter -R INPUT 1 -p tcp --dport 80 -j REJECT
-
-R,替换INPUT链的1号规则
6.6、删除
#删除filter表INPUT链中的第一条规则
iptables -t filter -D INPUT 1
6.7、自定义链
自定义的链,最终要应用到默认链上,才能起作用
例:
#在filter表,自定义一个链叫test
iptables -t filter -N test
#在自定义链的filter表定义规则
iptables -t filter -A test -s 172.25.254.11 -j REJECT
#访问22端口数据包,先转到test链进行过滤
#如果在test链没有匹配到规则,再回到INPUT链,从当前规则向下匹配
iptables -t filter -A INPUT -p tcp --dport 22 -j test
7、扩展模块
iptables有一些扩展模块,可以调用
#所有以.so结尾的文件,就是扩展模块
rpm -ql iptables
#查看扩展帮助
man iptables-extensions
显式扩展规则
-
使用-m,使用扩展模块
-
-m modules-name<string state connlimte time> options <模块的option>
隐式的扩展规则
-
不需要-m选项,使用扩展模块
-
比如:-p tcp --dport,就是使用的tcp扩展模块,指定目标端口
7.1、multiport
#需要使用扩展规则,-m,指定使用multiport模块
#如果要指定一个端口范围,使用冒号,如:80:1000,表示80端口到1000端口
iptables -t filter -A INPUT -s 172.25.254.10/32 -p tcp -m multiport \
--dport 80,23 -j REJECT
7.2、connlimit
TCP模块
TCP三次握手:
-
客户端发送请求:SYN=1,ACK=0
-
服务端回应:SYN=1,ACK=1
-
客户端确认:ACK=1,SYN=0
从第4次开始,客户端开始发送数据
PSH=1,ACK=1
断开连接
FIN=1
格式:
tcp --tcp-flags list1 list2
-
list1,表示要对哪些字段进行检查
-
list2,表示指定list1中,哪些字段必须为1
list1:SYN,ACK,PSH,FIN,RST,URG
list2:
-
SYN,表示TCP握手第一次
-
SYN,ACK,表示TCP握手第二次
-
ACK,表示第三次握手
#隐示扩展:tcp-flags
#只允许2次的syn为1的连接
iptables -t filter -A INPUT -p tcp --tcp-flags \
SYN,ACK,PSH,FIN,RST,URG \
SYN -m connlimit --connlimit-above 2 -j REJECT
#和上面一个意思,只不过用--syn代替
iptables -t filter -A INPUT -p tcp --syn -m connlimit \
--connlimit-above 2 -j REJECT
#针对本地的23号端口,一个IP只能作两次syn连接,第3次就拒绝了
#使用connlimit模块,根据客户端IP,限制客户端的并发连接数
iptables -t filter -A INPUT -p tcp --syn --dport 23 -m connlimit \
--connlimit-above 2 -j REJECT
7.3、iprange
#拒绝172.25.254.100到200这个网段的IP访问SSH
#使用iprange模块
iptables -t filter -A INPUT -m iprange -p tcp --dport 22 \
--src-range 172.25.254.100-172.25.254.200 -j REJECT
7.4、time
#18:00到22:00之间,不允许telnet
#使用time模块
iptables -t filter -A INPUT -p tcp --syn --dport 23 -m time \
--timestart 18:00 --timestop 22:00 -j REJECT
7.5、state
根据连接追踪机制检查连接的状态
-
一个连接建立之后,即:客户端发送请求报文,服务器也响应了一个报文。在一定时间内(如:6秒内),此连接信息会在内存中保存下来。在过期前,同样的连接请求到达,会刷新时间,只要此信息有效,此时就处于已连接状态;超时,则删除此连接信息。
-
默认,内核为了不让这种信息把内存占完,对连接追踪功能所能容纳的最大连接数有所限制。
#默认最大连接数65535
cat /proc/sys/net/nf_conntrack_max
#记录的连接
cat /proc/net/nf_conntrack
可追踪的连接状态:
-
NEW,新发出的请求,连接记录不存在此连接信息,所以,识别为第一次发出的请求
-
ESTABLISHED,已建立的连接,记录失效之前所处状态
-
RELATED,相关的连接,比如:FTP连接,分命令连接和数据连接两部分,在建立数据连接之前,要先通过命令连接发送命令,这种关系就叫RELATED
-
INVALIED,无法识别的连接
放行FTP被动模式:
#加载FTP追踪模块
modprobe nf_conntrack_ftp
#放行请求报文
#命令连接:NEW,ESTABLISHED
iptables -I INPUT -d 192.168.0.200 -p tcp --dport 21 \
-m state --state NEW,ESTABLISHED \
-j ACCEPT
#数据连接:RELATED,ESTABLISHED
#被动模式,服务器数据连接端口不固定,所以全开
iptables -I INPUT -m state --state RELATED,ESTABLISHED \
-j ACCEPT
#放行响应报文:ESTABLISHED
#响应报文,只要是ESTABLISHED就放行
#注意,前提,OUTPUT链,默认规则为拒绝。
iptables -I OUTPUT -m state --state ESTABLISHED \
-j ACCEPT
8、NAT
#也就是将linx主机作为一个路由器来使用
#需要开启内核转发功能
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p
8.1、SNAT
#如果收到一个包的目的IP不是172.25.254.0/24(路由器本地接口IP网段),将做SNAT,并且指定将源IP转换成转发出口的IP:10.0.0.10
#适用于出口IP固定
iptables -t nat -A POSTROUTING ! -d 172.25.254.0/24 -j SNAT \
--to-source 10.0.0.10
#将目的IP为10.0.0.10的数据包,转发至后端172.25.254.10这个主机
iptables -t nat -A PREROUTING -d 10.0.0.10 -j DNAT \
--to-destination 172.25.254.10
#将目的IP为10.0.0.10,且端口为80的访问数据包,转发到后端的172.25.254.10:8080
#不仅做IP转换,还做端口转换
iptables -t nat -A PREROUTING -d 10.0.0.10 -p tcp \
--dport 80 -j DNAT --to-destination 172.25.254.10:8080
8.2、伪装
也是做SNAT,只不过会自动将源IP转换成出口的IP,比如:ADSL,出口IP不是固定
#将目的地址不是本地接口IP的数据,做SNAT,将数据包的源IP转换成eth1口的IP
#如果只有一个出口,不带-o选项也可以
iptables -t nat -A POSTROUTING ! -d 172.25.254.0/24 -o eth1 \
-j SNAT MASQUERADE
8.3、端口转发
#将所有的80端口请求转发到8080端口
iptables -t nat -A PREROUTING -p tcp --dport 80 \
-j REDIRECT -to-ports 8080
9、使用mangle表作策略路由
要求:
-
内网192.168.10.0/24网段主机去访问互联网,走电信线路出去;
-
内网其它主机去访问互联网,走联通线路出去
9.1、配置两张路由表
#设置默认路由表,走联通线路
ip route add default via 2.2.2.2 dev eth2
#创建一个新路由表10,走电信线路
ip route add default via 1.1.1.1 dev eth1 table 10
9.2、配置策略路由
#打了标记1的数据包使用路由表10进行路由
ip rule add fwmark 1 table 10
#其实可以通过ip rule,直接指定源IP,就不用下一步的打标记步骤了
ip rule add from 192.168.10.0/24 dev eth0 table 10
ip rule参数:
-
From -- 源地址
-
To -- 目的地址(这里是选择规则时使用,查找路由表时也使用)
-
Tos -- IP包头的TOS(type of sevice)
-
Dev -- 物理接口
-
Fwmark -- iptables标签
采取的动作除了指定路由表外,还可以指定下面的动作:
-
Table 指明所使用的表
-
Nat 透明网关
-
Prohibit 丢弃该包,并发送 COMM.ADM.PROHIITED的ICMP信息
-
Reject 单纯丢弃该包
-
Unreachable丢弃该包, 并发送 NET UNREACHABLE的ICMP信息
9.3、给数据包打标记
#从eth0接口进来,在路由前,给源IP为192.168.10.0/24网段的数据包,打上标记1
iptables -t mangle -A PREROUTING -i eth0 -s 192.168.10.0/24 \
-j MARK --set-mark 1
9.4、补充:Linux路由表
linux总共可以有256(0-255)张路由表,其中:
-
0表系统保留
-
253,254,255系统维护
-
1-252,用户可以自定义使用
255 ,local,本地路由表,存有本地接口地址,广播地址,以及NAT地址。local表由系统自动维护,管理员不能操作此表。
254 ,main,主路由表,传统路由表。ip route若没指定表即操作表254
253 ,default ,默认路由表一般存放默认路由。
10、利用raw表提高性能
在启用了iptables web服务器上,流量高的时候经常会出现下面的错误:
ip_conntrack: table full, dropping packet
这个问题的原因是由于web服务器收到了大量的连接,在启用了iptables的情况下,iptables会把所有的连接都做链接跟踪处理,这样iptables就会有一个链接跟踪表,当这个表满的时候,就会出现上面的错误。
iptables的链接跟踪表最大容量为/proc/sys/net/nf_conntrack_max,链接碰到各种状态的超时后就会从表中删除。
所以解決方法一般有两个:
(1) 加大 nf_conntrack_max 值
vi /etc/sysctl.conf
net.nf_conntrack_max = 393216
net.nf_conntrack_max = 393216
(2)降低 nf_conntrack timeout时间
vi /etc/sysctl.conf
net.netfilter.nf_conntrack_tcp_timeout_established = 300
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
以上办法,虽然可以解决问题,但是nf_conntrack数目大了之后,会消耗CPU去翻查整张表,为了提高性能,可以使用raw表。
#将访问本地的80端口的连接不作追踪
iptables -t raw -A PREROUTING -p tcp --dport 80 -j NOTRACK
#从本地80端口发出去的包也不作追踪
iptables -t raw -A OUTPUT -p tcp --sport 80 -j NOTRACK
#允许转发没有追踪状态的连接
iptables -A FORWARD -m state --state UNTRACKED -j ACCEPT