[TOC]

防火墙分类

按照硬件组成部分划分: ​ 硬件防火墙:在硬件级别实现部分功能的防火墙;另一个部分功能基于软件实现; ​ 软件防火墙:应用软件处理逻辑运行于通用硬件平台之上的防火墙; 按照服务范围划分: ​ 主机防火墙:服务范围为当前主机; ​ 网络防火墙:服务范围为防火墙被的局域网;

netfilter

netfilter是位于内核空间的一个防火墙框架,通过iptables这样一个规则管理工具,向框架中添加规则,从而实现防火墙功能。

iptables

Firewall:防火墙的意思,只是一个隔离工具;Packets Filter Firewall,主要实现经过该网络的数据包的过滤功能;工作于主机或网络的边缘,对经由的报文根据预先定义的规则(匹配条件)进行检测,对于能够被规则匹配到的报文实行某预定义的处理机制的一套组件;

netfilter:防火墙框架,framework;位于内核空间;
iptables:命令行工具程序,位于用户空间;规则管理工具;

传说中的四表五链

要处理这些数据包总要一种规则,然而这些表和链就组成了一个规则。来看一张完整图:

<img loading=\" loading="lazy" src="13-Linux%E4%B9%8B%E9%98%B2%E7%81%AB%E5%A2%99iptables/complete.png">

表:
filter表--过滤数据包
nat表--用于网络地址转换(IP、端口)
mangle表--修改数据包的服务类型、TTL、并且可以配置路由实现QOS
raw表--决定数据包是否被状态跟踪机制处理

链:
INPUT链--进来的数据包应用此规则链中的策略
OUTPUT链--外出的数据包应用此规则链中的策略
FORWARD链--转发数据包时应用此规则链中的策略
PREROUTING链--对数据包作路由选择前应用此链中的规则(所有的数据包进来的时侯都先由这个链处理)
POSTROUTING链--对数据包作路由选择后应用此链中的规则(所有的数据包出来的时侯最后都由这个链处理)

上图十分清晰的表明数据包的流向。

由于四表中我们常用的就只有filter和nat,所以再来一张鸟哥版精简图:

simple

iptables的命令组成

匹配条件: ​ 网络层首部:Source IP, Destination IP, … ​ 传输层首部:Source Port, Destination Port, TCP Flags(SYN,ACK,FIN,URG,RST,PSH), … ​ 扩展检查机制: 处理动作:target ​ ACCEPT,DROP,REJECT,…

iptables 语法

iptables 不是固定的一种使用格式,而是有好多种。来看看帮助文档的写法吧。

# man iptables
    iptables [-t table] {-A|-C|-D} chain rule-specification
    iptables [-t table] -I chain [rulenum] rule-specification
    iptables [-t table] -R chain rulenum rule-specification
    iptables [-t table] -D chain rulenum
    iptables [-t table] -S [chain [rulenum]]
    iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
    iptables [-t table] -N chain
    iptables [-t table] -X [chain]
    iptables [-t table] -P chain target
    iptables [-t table] -E old-chain-name new-chain-name
其中:
    rule-specification = [matches...] [target]
    match = -m matchname [per-match-options]
    target = -j targetname [per-target-options]

总结起来大概就是这样

iptables [-t TABLE] COMMAND CHAIN [num] 匹配条件 -j 处理动作
iptables [-t table] COMMAND chain  criteria [-m matchname [per-match-options]]  [-j targetname [per-target-options]]

-t table:指明要管理的表; 默认为filter;

命令参数

命令参数这么多,那我们就来详细分析下命令吧。命令选项有长有断,后面只列举短的

  --append  -A chain		#增加链
  --check   -C chain		#检查链规则
  --delete  -D chain		#删除链规则
  --delete  -D chain rulenum	#删除制定数链规则
    --insert  -I chain [rulenum]	#插入指定链的规则到指定位置
  --replace -R chain rulenum	#替换链规则
  --list    -L [chain [rulenum]]	#列出链规则
  --list-rules -S [chain [rulenum]]		#打印链规则
  --flush   -F [chain]		#清空链规则
  --zero    -Z [chain [rulenum]]	#清零链规则
  --new     -N chain		#创建自定义链
  --delete-chain -X [chain]		#删除自定义链
  --policy  -P chain target		#修改链策略
  --rename-chain -E old-chain new-chain		#重命名链

这些命令可分为三类:链管理,规则管理和查看。

链管理

-P:iptables [-t table] -P chain target,定义链的默认策略;其target一般可使用ACCEPT或DROP;
-N:iptables [-t table] -N chain,自定义规则链;仅在默认链通过某规则进行调用方可生效;因此,每个自定义链都有其引用记数;
-X:iptables [-t table] -X [chain],删除自定义的空的引用计数为0的链;
-F:iptables [-t table] -F [chain [rulenum]] [options...],清空指定的链,或删除指定链上的规则 ;
-E:iptables [-t table] -E old-chain-name new-chain-name,重命名自定义的引用计数为0的链;
-Z:iptables [-t table] -Z  [chain [rulenum]] [options...]

规则管理

-A:append, iptables [-t table] -A chain rule-specification,追加规则到指定的链尾部;
-I:insert, iptables [-t table] -I chain [rulenum] rule-specification,插入规则到指定的链中的指定位置,默认为链首;
-D:delete,iptables [-t table] -D chain rule-specification或iptables [-t table] -D chain rulenum,删除指定的链上的指定规则;
-R:replace,iptables [-t table] -R chain rulenum rule-specification,将指定的链上的指定规则替换为新的规则;   

规则查看

-L:list, iptables [-t table] -L [chain [rulenum]] [options...]
    -n:数字格式;
    -v:verbose,详细格式信息;
        -vv, -vvv 
    --line-numbers:显示链上的规则的编号;
    -x:exactly,显示计数器的精确值; 

计数器

每条规则以及链的默认策略分别有各自的两个计数器: (1) 匹配到的报文的个数:pkts (2) 匹配到的所有报文的大小之积:bytes

counter

匹配条件

[-m matchname [per-match-options]]

匹配条件包括基本匹配条件和扩展匹配条件,扩展匹配条件又分显示和隐式

匹配条件:
    基本匹配条件
    扩展匹配条件
        隐式扩展
        显式扩展

基本匹配条件

[!] -s, --source address[/mask][,...]:检查报文中的源IP地址是否符合此处指定的地址或地址范围;
[!] -d, --destination address[/mask][,...]:检查报文中的目标IP地址是否符合此处指定的地址或地址范围;
[!] -p, --protocol protocol:检查报文中传输层的协议类型,支持tcp, udp,  udplite, icmp,  icmpv6,esp,  ah, sctp, mh,或者 "all";
[!] -i, --in-interface name:检查报文进入本机时的接口是否符合本处指定的接口;INPUT, FORWARD  and  PREROUTING ;
[!] -o, --out-interface name:检查报文即将离开本机时经由的接口是否符合本处指定的接口;FORWARD, OUTPUT and POSTROUTING;
 -m, --match match:显式指明要使用的扩展模块;
 -j, --jump target:跳转目标;
 
 注:[!] :表示取反

扩展匹配条件

隐式扩展

隐式扩展:不用-m选项明确给出要使用的扩展机制的扩展;此处主要指使用-p, {tcp|udp|icmp}给定协议后可直接对给定的协议所进行的扩展;

-p tcp:可直接使用tcp协议对应的扩展选项;
    [!] --source-port,--sport port[:port]:匹配报文中的传输层的源端口;可给出多个连接的端口;
    [!] --destination-port,--dport port[:port]:匹配报文中的传输层的目标端口;可给出多个连接的端口;
    [!] --tcp-flags mask comp
        SYN,ACK,FIN,RST,URG,PSH;
        
        mask:要检查的标志位列表,以逗号分隔,例如SYN,ACK,FIN,RST 
        comp:mask给定的众标志位中,其值必须为1的标志位列表,余下的必须为0;
        
            --tcp-flags SYN,ACK,FIN,RST SYN 
            
    [!] --syn:相当于--tcp-flags SYN,ACK,FIN,RST SYN 
    
-p udp:可直接使用udp协议对应的扩展选项;
    [!] --source-port,--sport port[:port]:匹配报文中的传输层的源端口;可给出多个连接的端口;
    [!] --destination-port,--dport port[:port]:匹配报文中的传输层的目标端口;可给出多个连接的端口;
    
-p icmp:可直接使用cimp协议对应的扩展选项;
    [!] --icmp-type {type[/code]|typename}
        --icmp-type  0/0:匹配对ping请求的响应报文
        --icmp-type 8/0:匹配ping请求报文

显示扩展

显式扩展:必须使用-m选项给出matchname的扩展,而且有些扩展都还存在专用选项;

1、multiport
    以离散或连续的方式定义的多端口匹配条件; Up  to 15 ports can be specified. 
    
    [!] --source-ports,--sports port[,port|,port:port]...:指定多个源端口;
    [!] --destination-ports,--dports port[,port|,port:port]...:指定多个目标端口;
    [!] --ports port[,port|,port:port]...:匹配此处指定的源或目标端口;
    
2、iprange
    以连续的ip地址范围指明多地址匹配条件;
    
    [!] --src-range from[-to]
    [!] --dst-range from[-to]
    
3、string
    对报文中的应用层数据做字符串匹配检测;
    
    [!] --string pattern
    [!] --hex-string pattern
    --algo {bm|kmp}:字符串匹配检查算法;
    --from offset
    --to offset
    
4、time
    根据报文到达的时间与指定的时间范围进行匹配度检测;
    
     --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
     --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
     
     --timestart hh:mm[:ss]
     --timestop hh:mm[:ss]
     
     [!] --monthdays day[,day...]
     [!] --weekdays day[,day...]
     
5、connlimit 
    根据每客户端IP做并发连接数限制,即限制单IP可同时发起连接请求;
    
    --connlimit-upto n:连接数小于等于阈值;
    --connlimit-above n:连接数超出阈值;
    
    ~]# iptables -I INPUT -d 10.1.0.6 -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
    
6、limit 
    基于收发报文的速率进行匹配;
        
    --limit rate[/second|/minute|/hour|/day]
    --limit-burst number
    
# iptables -A INPUT -d 10.1.0.6 -p icmp --icmp-type 8 -m limit --limit-burst 3 --limit 20/minute -j ACCEPT
     
7、state 
    状态检测:连接追踪机制(conntrack)
        
        NEW:新连接
        ESTABLISHED:已建立的连接
        RELATED:相关联的连接
        INVALID:无法识别的连接
        UNTRACKED:未被追踪连接;
        
    相关的内核模块:
        nf_conntrack
        nf_conntrack_ipv4
        nf_conntrack_ftp  手动装载
        
        追踪到的连接:/proc/net/nf_conntrack文件中;
        能追踪的最大连接数量定义在:/proc/sys/net/nf_conntrack_max  建议调整至足够大;
        不同的协议的连接追踪时长: /proc/sys/net/netfilter/
     
    [!] --state state
    
    如何开放被动模式的ftp服务:
      (1) 装载追踪ftp协议的模块;
      	# modprobe nf_conntrack_ftp

      (2) 放行入站命令连接
      	# iptables -A INPUT -d SERVER_IP -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT

      (3) 放行入站数据连接
      	# iptables -A INPUT -d SERVER_IP -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT

      (4) 放行出站的ESTABLISHED连接
      	# iptabls -A OUTPUT -s SERVER_IP -m state --state ESTABLISHED -j ACCEPT

处理动作(跳转目标)

-j tagetname [per-target-options]

简单target:
    ACCEPT,DROP
    
扩展target:
    REJECT:
        --reject-with type
             icmp-net-unreachable, 
             icmp-host-unreachable, 
             icmp-port-unreachable, 
             icmp-proto-unreach‐able, 
             icmp-net-prohibited, 
             icmp-host-prohibited, 
             icmp-admin-prohibited,
             默认为:icmp-port-unreachable;
    LOG:
        Turn  on  kernel  logging of matching packets.
        
        --log-level level
        --log-prefix prefix:日志信息的前导信息;

保存和载入规则

CentOS 7:

保存:iptables-save > /PATH/TO/SOME_RULE_FILE 
重载:iptables-restore < /PATH/FROM/SOME_RULE_FILE
    -n, --noflush:不清除原有规则
    -t, --test:仅分析生成规则集,但不予提交;
    
    注意:重载文件中的规则,会清除已有规则;

CentOS 6:

保存:service  iptables  save
    保存规则于/etc/sysconfig/iptables,保存操作会清除文件中原有的内容;
重载:server iptables restart 
    默认重载/etc/sysconfig/iptables文件中的规则
    
脚本配置文件:/etc/sysconfig/iptables-config
    用于指明要装载的模块;

规则添加是考量原则

(1) 报文流经的位置:用于判断将规则添加至哪个链; (2) 实现的功能:用于判断将规则添加至哪个表; (3) 报文的方向:用于判断哪个为“源”,哪个为“目标”; (4) 匹配条件:用于编写能够正确匹配目标报文的规则;

优化规则思路

(1) 优先放行双方向状态为ESTABLISHED的报文; (2) 服务于不同类别的功能的规则,匹配到报文可能性更大的放前面; (3) 服务于同一类别的功能的规则,匹配条件较为严格的放前面; (4) 设置默认策略:白名单机制

​ (a) 可使用iptables -P设定默认策略;不建议 ​ (b) 建议在规则链的最后定义规则做为默认策略;

看完了吗?试试吧!

练习:基于状态放行telnet, ftp, ssh, http, samba, icmp等服务;
    (1) 对本机的ping请求每分钟不得超出20个;
    (2) 每客户端对本机的ssh的并发连接数不得超过3个;
    (3) 本机的telnet服务仅允许工作时间内访问;

网络防火墙

网络防火墙主要是在两个地方做:

(1) 网关; (2) filter表的FORWARD链;

要注意的问题:
    (1) 请求-响应报文均会经由FORWARD链,要注意规则的方向性;
    (2) 如果要启用conntrack机制,建议将双方向的状态为ESTABLISHED的报文直接报文;
    
NAT: Network Address Translation
    请求报文:由管理员定义;
    响应报文:由NAT的conntrack机制自动实现; 
    
    请求报文:
        改源地址:SNAT
        改目标地址:DNAT
        
iptables/netfilter:
    NAT定义在nat表;
        PREROUTING,INPUT,OUTPUT,POSTROUTING
        
        SNAT:POSTROUTING
        DNAT:PREROUTING
        PAT:
        
target:
    SNAT:
        This  target  is only valid in the nat table, in the POSTROUTING and INPUT chains, and user-defined chains which are only called from those chains.
        
        --to-source [ipaddr[-ipaddr]]
        
    DNAT:
        This target is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains  which  are only  called from those chains.
        
        --to-destination [ipaddr[-ipaddr]][:port[-port]]
        
     MASQUERADE
        This target is only valid in the nat table, in the POSTROUTING chain.  It  should  only  be  used  with  dynamically assigned  IP (dialup) connections: if you have a static IP address, you should use the SNAT target.
        
        SNAT场景中应用于POSTROUTING链上的规则实现源地址转换,但外网地址不固定时,使用此target;
        
    REDIRECT
        This  target  is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains which are only called from those chains.
        
        --to-ports port[-port]