Linux基础服务之防火墙

数据包在Linux主机中流向

  1. 当一个数据包到达主机时,主机需要判断,此数据包是发往本机还是转发给其他主机的;
  2. 如果是发往本机的,数据包从内核空间发送到用户空间,由相应的程序进行处理;
  3. 如果是转发的,则在内核空间进行处理;
  4. 当本机产生的数据包需要发送时,经由路由判断,发送到相应的网卡;
  5. 最后网卡将数据包发送出去,离开本机。
数据包在Linux主机中的流向

上面的5点就是Linux防火墙发挥作用的地点,在netfilter中由5个链表示,分别是:

  • PREROUTING链:数据包刚刚到达本机
  • INPUT链:数据包发往本机的用户空间
  • FORWARD链:数据包在内核空间转发到另外的网卡
  • OUTPUT链:用户空间即将发送的数据包
  • POSTROUTING链:数据包即将离开本机

iptables位于用户空间,用于管理和操作netfilter,而netfilter位于内核空间,是防火墙真正发挥作用的地方。

链实际上一个hook函数,数据包由这些hook函数进行检查。

netfilter

netfilter包含4个表,分别是:filter、nat、mangle、raw表。netfilter会在内存中的一个区域存放这些表中包含的规则。这四个表,每个表都有相应的链,链上则有相应的规则。

netfile中四个表的优先级
  • INPUT链:保护本机,防止恶意的流量进入本机
  • OUTPUT链:限制本机
  • FORWARD链:保护“后端”机器,forward链可以筛选转发的流量,然后让ip_forward转发。

不同表中出现相同的链时,处理的优先级由高到低依次处理:raw->mangle->natl->filter

filter表处理数据包的过程

当数据包流入时,首先经过路由判断该数据包是流入防火墙本机还是转发到其他机器的。对于流入本机的数据包经过INPUT链,INPUT链所在位置是一个钩子函数,数据经过时将被钩子函数检查一番,检查后如果发现是被明确拒绝或需要丢弃的则直接丢弃,明确通过的则放行,不符合匹配规则的同样丢弃。处理结果通告netfilter,这个数据包的处理结果,即使是拒绝或丢弃了数据包也还是会给出一个通知。

当用户空间产生的数据包要发送出去时,首先经过OUTPUT链并被此处的钩子函数检查一番,检查通过则放行,然后经过路由决策判决从哪个接口出去,并最终从网卡流出。

在发出的数据包中,先经过OUTPUT,再经过路由决策。这样一来,对那些检查不通过的数据包会直接丢弃,而无需再消耗资源去做路由决策。

iptables命令

iptables 书写规则

书写iptables规则,考虑两个部分:

  • 要实现何种功能:即选择对应功能的表
  • 流量的流向:即选择“五链”的位置

iptables的一般命令格式

iptables -t table ①COMMAND chain [规则号number] ②匹配条件 -j 处理动作
  • table:默认为filter,可省略,其他需要显式指定
  • ①COMMAND:大概分为四种类型,分别是增、删、改、查
    • 增加规则或链
      • -A :append,在指定链 chain 的末尾插入指定的规则,也就是说,这条规则会被放到最后,最后才会被执行
      • -I :insert,在链 chain 中的指定位置插入一条或多条规则。默认在链头部插入,规则编号为1
      • -N :--new-chain,用指定的名字创建一个新的链
    • 删除规则或链
      • -D:delete,删除指定链 chain 的一条或多条规则
      • -X:删除用户自定义且未引用的空链
      • -F:清空所有防火墙规则
      • -Z:置零链上的数据包,清空计数
    • 查询规则
      • -L:列出链 chain 上面的所有规则,如果没有指定链,列出表上所有链的所有规则
        • -v:verbose,显示详细信息,v越多显示越详细
        • -n:number,以数字格式显示地址和端口号
        • -x:exactly,显示计数器技术结果的精确值
        • --line-nmubers:显示规则编号
    • 修改
      • -R:replace,替换链中的第rulenum条规则,从1开始计数
  • ②匹配条件
    • 基本匹配
      • [!] -s address[/mask][,…]: 源ip,省略表示所有地址; !表示取反;
      • [!] -d address[/mask][,…]:目标ip,省略表示所有地址;
      • [!] -i IFACE: 报文从哪个网卡流入
      • [!] -o IFACE: 报文从哪个网卡流出
    • 扩展匹配
      • 隐式扩展
        • -p tcp
          • [!] {–sport|–dport} port[:port]:匹配tcp协议的指定端口(port)或端口连续的范围(port:port)
          • [!] [–syn]:匹配syn为1,其它为0的报文;表示仅匹配TCP3次握手的第一次,即建立请求
        • -p udp
          • [!] {–sport|–dport} port[:port] 匹配udp协议的指定端口(port)或端口连续的范围(port:port)
        • -p icmp
          • [!] –icmp-type major[.minor]:major:8,echo request, 请求;0: echo reply, 响应;
          • ping时先请求后响应:ping别人先出去8后进来0;别人ping自己,先进来8后出去0
      • 显式扩展
        • -m iprange:匹配给定指定的IP地址范围
          • [!] --src-range from[-to]:匹配给定的源地址范围
          • [!] --dst-range from[-to]:匹配给定的目标地址范围
        • -m multiport:匹配离散的多个端口(最多15个),并且只有指定了-p tcp或-p udp时该选项才生效
          • [!] --source-ports,--sports port[,port|,port:port]...
          • [!] --destination-ports,--dports port[,port|,port:port]...
          • [!] --ports port[,port|,port:port]... :不区分源和目标,只要是端口就行
        • -m state:匹配状态,结合ip_conntrack追踪会话的状态
          • [!] --state {INVALID|ESTABLISHED|NEW|RELATED( 新连接并和已有连接是相关联的)}
          • 例如:iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT
        • -m string:匹配报文中的字符
          • --algo {kmp|bm}:两种算法,随便指定一种
          • --string "string_pattern"
          • 例如:iptables -A OUTPUT -m string --algo bm --string "taobao.com" -j DROP
        • -m mac:匹配mac地址
          • [!] --mac-source address:MAC地址格式为XX:XX:XX:XX:XX:XX
        • -m limit:使用令牌桶(token bucket)来限制过滤连接请求数
          • --limit RATE[/second/minute/hour/day]:允许的平均数量。如每分钟允许10次ping,即6秒一次ping。默认为3/hour
          • --limit-burst:允许第一次涌进的并发数量。第一次涌进超出后就按RATE指定数来给出响应。默认值为5
          • 例如:允许每分钟6次ping,但第一次可以ping 10次。10次之后按照RATE计算,iptables -A INPUT -d ServerIP -p icmp --icmp-type 8 -m limit --limit 6/minute --limit-burst 10 -j ACCEPT
        • -m connlimit:限制每个客户端的连接上限
          • --connlimit-above n:连接数量高于上限n个时就执行TARGET
          • 例如:如最多只允许某ssh客户端建立3个ssh连接,超出就拒绝。两种写法:
          • iptables -A INPUT -d ServerIP -p tcp --dport 22-m connlimit --connlimit-above 3-j DROP
          • iptables -A INPUT -d ServerIP -p tcp --dport 22-m connlimit ! --connlimit-above 3-j ACCEPT
          • 这个模块虽然限制能力不错,但要根据环境计算出网页正常访问时需要建立的连接数,另外还要考虑使用NAT转换地址时连接数会翻倍的问题。
  • 处理动作:表示对匹配到的数据包要做什么处理
    • 丢弃DROP、拒绝REJECT、接受ACCEPT
    • DNAT:目标地址转换
    • SNAT:源地址转换
    • REDIRECT:端口重定向
    • MASQUERADE:地址伪装(其实也是源地址转换)
    • RETURN:用于自定义链,自定义链中匹配完毕后返回到自定义的前一个链中继续向下匹配

数据包状态

iptables的state模块定义了数据包的四种状态:NEW、ESTABLISHED、RELATED、INVALID。state提供的4种状态对于tcp/udp/icmp类型的数据包都是通用的

NEW状态

为了建立一条连接,发送的第一个数据包(如tcp三次握手的第一次SYN数据包)的状态为NEW。如果第一次连接没建立成功,则第二个继续请求的数据包已经不是NEW数据包了。

所以,如果不允许NEW状态的数据包表示不允许主动和对方建立连接,也不允许外界和本机建立连接。

ESTABLISHED状态

无论是tcp数据包、udp数据包还是icmp数据包,只要发送的请求数据包穿过了防火墙,那么接下来双方传输的数据包状态都是ESTABLISHED,也就是说发过去的和返回回来的都是ESTABLISHED状态数据包。

RELATED状态

与当前任何连接都无关,完全是被动或临时建立的连接之间传输的数据包。数据包是因为本机先送出一个数据包而导致另一条连接的产生,那么这个新连接的所有数据包都属于RELATED状态的数据包。

FTP被动模式是典型的RELATED状态。在ftp服务器上的21号端口上开启了命令通道(也就是命令连接)后,以后无论是被动模式的随机数据端口还是主动模式的固定20数据端口,可以肯定的是数据通道的建立是由命令通道指定要开启的,所以这个数据通道中传输的数据包都是RELATED状态的。

INVALID状态

恶意的数据包。只要不是ESTABLISHED、NEW、RELATED状态的数据包,那么就一定是INVALID状态。对于INVALID数据包最应该放在链中的第一条,以防止恶意的循环攻击。

网关式防火墙的NEW、ESTABLISHED和RELATED状态

网关式的防火墙挡在客户端和服务器端中间,用于过滤或改变数据包。

关于它的状态变化,可以总结为"墙头草":

①.客户端送到防火墙的数据包是什么状态,防火墙的state模块就设置为什么状态,转发给服务器的数据包就是什么状态;

②.服务端发给防火墙的数据包是什么状态,防火墙的state模块就设置为什么状态,转发出去的数据包就是什么状态。

也就是说,防火墙并不改变数据包状态的性质。

虽说数据包的状态只有防火墙才有资格判断,但是这样归纳却不妨碍理解。

例如,TCP三次握手的第一次,客户端发送一个SYN数据包给服务器要建立连接,这个SYN数据包传到防火墙上,防火墙的state模块也会将自己的状态设置为SYN_SENT,并认为这个数据包是NEW状态的数据包,然后转发给服务器,转发过程的数据包的状态也是NEW。当服务器收到SYN后应答一个SYN+ACK数据包,当SYN+ACK数据包到达防火墙时,防火墙也和服务器一样将自己设置为SYN_RECV状态,并认为这个数据包已经是ESTABLISHED的数据包了,然后将这个数据包以ESTABLISHED的状态转发给客户端。

RELATED状态也是一样的,只要双方的连接是"另起炉灶"的数据包,客户端和服务端之间的防火墙会随着数据包的流向而做一支"墙头草"。

其实这些状态以及转变都会在/proc/net/nf_conntrack文件中记录,只是比较难以被人为追踪到。

追踪状态的工具

netfilter是有状态机制的防火墙,通过conntrack模块跟踪记录每个连接的状态,通过它可制定严密的防火墙规则。ip_conntrack提供追踪功能,后来改称为nf_conntrack,由nf_conntrack模块提供。只要一加载该模块,/proc/net/nf_conntrack文件中就会记录下追踪的连接状态。虽然会追踪TCP/UDP/ICMP的所有连接,但是在此文件中只保存tcp的连接状态。

/proc/net/nf_conntrack文件显示的TCP连接

第二条显示的是ESTABLISHED状态的连接,该连接是192.168.1.104:64472-->192.168.1.115:22,以及返回的连接192.168.1.115:22 --> 192.168.1.104:64472。

也可使用由iptstate包提供的ipstate命令实现显示当前的网络连接状态

iptstate命令实时显示网络连接状态

图中TTL值的设置位置在/proc/sys/net/netfilter/目录下的文件中,TIME_WAIT的默认超时时间为2分钟,即等待TIME_WAIT的时间2分钟后就断开连接,可以将其修改。(TIME_WAIT处于TCP连接4次挥手主动段开方的倒数第二个阶段,也就是收到了被动端FIN=1,并且主动端发送ACK后的状态)

使用nf_conntrack跟踪连接同样会消耗系统资源,监控最大连接数由/proc/sys/net/netfilter/nf_conntrack_mac文件决定,追踪数达到了最大值后,后续的所有连接都将排队被阻塞。

nf_conntrack_max文件决定最大监控连接数

nf_conntrack模块不是一定需要显式装载才会被装载的,有些依赖它的模块被装载时该模块也会被装载。例如iptables命令中包含iptables -t nat时,就会装载该模块自动开启追踪,进而可能导致达到追踪max值而出错

管理规则

iptables编辑的规则都由内核维护在内存中,重启iptables"服务"会使内存中的规则列表全部被清空。iptables"服务"启动时默认加载的脚本配置文件/etc/sysconfig/iptables

保存规则

方法一:直接保存到/etc/sysconfig/iptables中:

service iptables save

方法二:可自定义保存位置

iptables-save >/etc/sysconfig/iptables
iptables-save >/etc/sycofnig/iptables.20190103

恢复规则

iptables-restore </etc/sysconfig/iptables
iptables-restore </etc/sysconfig/iptables.20190103

管理规则的方法:

管理规则更好的方法是写成脚本。将这些规则全部写入到一个shell脚本中,并对多次重复的地址使用变量,例如服务器的地址或网段,内网的网段。

使用脚本的优点有:

1.管理的便捷。写成脚本可以直接修改该文件,要重新生效时只需执行一次该脚本文件即可。但是要注意脚本的第一条命令最好是iptables -F,这样每次运行脚本都会先清空已有规则再加载脚本中的其他规则。

2.可以在脚本中使用变量。这样以后某台服务器地址改变了只需修改该服务器地址对应的变量值即可。

3.容易阅读,因为可以加注释,并通过注释来对规则进行分类,未来修改就变得相对容易的多。

4.备份规则变得更容易。备份后,即使硬盘坏了导致现有的规则丢失了也可以简单的拷贝一个脚本过去运行即可,而不用再一条一条命令的敲。

5.也可以实现开机加载规则。只需在/etc/rc.d/rc.local中加上一条执行该脚本的命令即可。

6.可以将其加入任务计划。

自定义链

自定义链是被主链引用的。引用位置由"-j"指定自定义链名称,表示跳转到自定义链并匹配其内规则列表。在自定义链中的最后一条加上一条返回主链的规则,表示匹配完自定义后继续回到主链进行匹配。数据包匹配到了跳转到自定义链这个位置开始进入自定义链匹配,如果自定义链都没被匹配而是被最后的RETURN规则匹配,则回到主链再次匹配。

创建自定义链

iptables -N mychain

主链跳转到自定义链

iptables -A INPUT -d 192.168.1.115 -j mychain

自定义链返回主链

iptables -A mychain -d 192.168.100.8 -j RETURN

删除自定义链,需要先清空自定义链,去除被引用记录,然后使用-X删除空的自定义链。

iptables -F mychain
iptables -D INPUT 1
iptables -X mychain

一个 iptables 脚本

#!/bin/bash

IPT=/usr/sbin/iptables

IP_TRUSTED=192.168.1.0/255.255.255.0
LOCAL_ADDR=192.168.1.110

WEB=80
SSH=22
MYSQL=3306
VNC=5901

modprobe ipt_MASQUERADE
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp

# DELETE Any Existing Chains In Filter Table
$IPT -F -t filter
$IPT -X -t filter
$IPT -Z -t filter

# Setting Default Policies,just accept output,drop any other
$IPT -P INPUT DROP
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD DROP

# Setting SSH just trusted ip can connect it
$IPT -t filter -A INPUT -s $IP_TRUSTED -p tcp -m multiport -dport=$SSH,$VNC -j ACCEPT

#This server can ping other host
$IPT -t filter -A INPUT -p icmp --icmp-type=0 -j ACCEPT
#Just trusted ip can ping this server
$IPT -t filter -A INPUT -s $IP_TRUSTED -p icmp -j ACCEPT

# Setting INPUT,this server can connect other server via tcp 
$IPT -t filter -A INPUT -m state --state=ESTABLISHED,RELATED -j ACCEPT
$IPT -t filter -A INPUT -p tcp -m multiport -sport=20,21,22,80,3306 -j ACCEPT

# Setting INPUT,this server can connect other server via udp
$IPT -t filter -A INPUT -p udp -m multiport --sport=53,123 -j ACCEPT

# localhost
$IPT -t filter -I INPUT -i lo -j ACCEPT
$IPT -t filter -I OUTPUT -o lo -j ACCEPT

# security
$IPT -A INPUT -d $LOACL_ADDR -p tcp --syn -m connlimit --connlimit-above 15 -j DROP

参考链接

https://www.cnblogs.com/f-ck-need-u/p/7397146.html#auto_id_24

https://www.cnblogs.com/bits/archive/2009/03/01/Linux-bash_iptables.html

https://www.cnblogs.com/chongchong88/p/5570403.html

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券