zoukankan      html  css  js  c++  java
  • firewalld 极速上手指南

    从CentOS6迁移到7系列,变化有点多,其中防火墙就从iptables变成了默认Firewalld服务。firewalld网上资料很多,但没有说得太明白的。一番摸索后,总结了这篇文章,用于快速上手。

    1.概览

    CentOS7.2.1511 默认防火墙如下图:
    这里升级到最新的,相对于默认的这里增加了几个配置,是firewalld更灵活。

    2.区域(zone)

    firewalld是centos7的一大特性,最大的好处有两个:
    (1)支持动态更新,不用重启服务;
    (2)引入了防火墙的“zone”概念,简单来说就是为用户预先准备了几套防火墙策略模板,然可根据不同场景选择相应的策略,类似于我们常见windows下网络连接时候选择的工作区(工作网络,家庭网络,公共网络)。
    关于第二点的特性实现就使用到了一个区域(zone)的概念。对应到上图中的是1号位置
    通过下面命令查看所有的区域
    下表给出了所有区域解释
     

    3.过滤规则

    target:区域放行策略,类似iptables中的target,例如public区域设置target:default,该区域的规则为白名单模式。如果target:ACCEPT,则该区域的网络接口全放行(为什么这里是说的网络接口?下面interface项详细解释)。设置target使用下面命令:
     
    这里有两个问题:
    1.第一次命令失败,提示必须要加上参数--permanent
        在firewalld-cmd执行的命令中,如果是规则相关的,加上--permanent参数不会立即生效,只会被记录到配置文件。如果要生效需要调用firewall-cmd --reload重载;如果不加--permanent则是立即生效,但如果--reload会被清掉。
        此外,在firewall-cmd命令中有些命令需要必须加--permanent参数,比如这里的--set-target。下面执行--reload
    icmp-block-inversion:这个是一个禁ping的参数,默认关闭
    interfaces:该区域绑定的网络接口。firewalld的优势就是分了不同的区域,通过这个参数可以为不同的网络接口指定规则。图中ens192网卡被指定到了public区域,所有这个网卡上的请求都应用这个区域的规则。
    使用命令 firewall-cmd --change-interface=ens192 --zone=public 修改网卡绑定区域
    关于这个有两点注意:
    1.网路接口可以不被指定在任何区域,在这种情况下,没有被指定区域的网络接口使用默认zone。下面两条命令获取/设置默认zone
    2.interfaces的优先级别没有source高。优先级为:source>interface>firewalld.conf
    firewalld是封装的iptables,所以看iptables规则更直接。例如有以下配置,网络接口在public中,trusted区域中放行10.10.10.10源,其他区域默认不修改:
    public (active)
      target: default
      icmp-block-inversion: no
      interfaces: ens192
      sources:
    ...
    
    trusted (active)
      target: ACCEPT
      icmp-block-inversion: no
      interfaces:
      sources: 10.10.10.10/32
    ...
    通过iptables查看source区域在前面,所以优先级比interface高。
     
    sources:根据源ip放行
    services:根据服务进行放行,默认的里面有ssh和dhcpv6-client两个服务。ssh就是22端口。
    如果需要自定义一个服务规则,怎么做呢?
    在/etc/firewalld/services下面添加自定义配置test.xml,如
    <?xml version="1.0" encoding="utf-8"?>
    <service>
      <short>Test Port</short>
      <port protocol="tcp" port="5000"/>
    </service>
    然后就能通过--add-service以服务名test添加规则
     
    ports:根据端口放行
    protocols:协议类型,默认为空
    masquerade:地址隐藏,默认是no,如果设置成yes,使用lo本地地址访问时候,会被转换成物理ip
    forward-ports:
    source-ports:
    icmp-blocks:
    rich rules:复杂规则。使用复杂规则能很统一的控制规则。一条完整的规则如下,规则中source,destination, port项都是可以根据需要缺省的
    rule family="ipv4" source address="0.0.0.0" destination address="192.168.136.190" port port="3306" protocol="tcp" accept
    添加规则使用命令:firewall-cmd --add-rich-rule='...'
    同样使用--permanent参数为指定永久规则
     

    4.firewalld配置

    firewalld的配置在/etc/firewall下
    在zones目录下,存放有所有区域的配置。进入到zones目录下,没有看到所有文件?
    原因是firewalld在这个目录下没有找到配置的时候,会使用/usr/lib/firewalld/zones下配置。该目录下是服务默认配置,在/etc下不能找到相关配置则使用/usr/lib下的

    5.接口封装

    如果在接口中使用firewalld服务,调用shell命令的方式效率低。平均添加一条rich-rule需要0.7s的时间(8c,12G,CentOS7)。
    这里推荐一种方式是,直接去操作/etc/firewalld/zone下的 xml 配置文件,最后使用 --reload 加载规则。这种方式下,写文件的时间可以忽略,所有的时间都耗费在 reload上。总共时间测试下来在2s以内。
    示例文件:
    <?xml version="1.0" encoding="utf-8"?>
    <zone>
      <short>Public</short>
      <description>Nothing</description>
      <service name="ssh"/>
      <rule family="ipv4">
        <source address="10.10.10.10"/>
        <destination address="10.10.10.10"/>
        <port protocol="tcp" port="1000"/>
        <accept/>
      </rule>
    </zone>
     
    import xml.etree.cElementTree as ET
    tree = ET.ElementTree(file="/etc/firewalld/zones/public.xml")
    root = tree.getroot()
     
    # 获取rich rule规则
    for each_rule in root.findall('rule'):
        # 打印地址协议
        print 'family:' + str(each_rule.attrib)
        # 打印源地址
        source_obj = each_rule.find('source')
        if source_obj is not None:
            print 'source:' + str(source_obj.attrib)
        # 打印目的地址
        destination_obj = each_rule.find('destination')
        if destination_obj is not None:
            print 'destination:' + str(destination_obj.attrib)
        # 打印端口
        port_obj = each_rule.find('port')
        if port_obj is not None:
            print 'port:' + str(port_obj.attrib)
     
    # 删除rich rule规则,删除参数为rich rule字符串,记为 remove_str
    # decode_obj(element) 将xml结构解析成字符串,返回值为字符串,注意字符串赋值顺序,语法细节参考添加规则
    for each_rule in root:
        if decode_obj(each_rule) == remove_str:
            root.remove(each_rule)
     
    # 剩下的修改功能、查找功能可以参照上面实现,这里主要说明的是xml库的使用方法

    这里再针对xml库说明下,从<zone>开始,每一层都是一个节点,然后形成的一棵树。每个节点是 ET.Element(tag, attrib={}),比如这里short, description, service , rule都是tag, family是attrib

    需要访问节点的 tag 和 attrib,直接xmlobj.tag,xmlobj.attrib方式访问

    获取子节点使用xmlobj.getchildren(),或者是获取指定tag的节点xmlobj.findall(tag)

     
     
  • 相关阅读:
    磁盘阵列监控
    Docker-PS命令解析
    .NET编程周记第3期-2020年1月19日
    Microsoft Ignite The Tour Beijing 记录: Learn Connect Explore
    使用TryGetComponent取代GetComponent以避免Editor中的内存分配
    向.Net/Unity 程序员推荐一个十分因吹斯听的网站:sharplab.io
    Unity AR Foundation 和 CoreML: 实现手部的检测和追踪
    如何使用Android Studio在安卓平台对Unity开发的应用进行性能检查?
    Unity的Mesh压缩:为什么我的内存没有变化?
    Unity User Group深圳站——Timeline & Cinemachine分享
  • 原文地址:https://www.cnblogs.com/newguy/p/8809663.html
Copyright © 2011-2022 走看看