一、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