python 控制Windows防火墙(FireWall)

一、说明

最近有朋友问有木有认识做.Net关于Windows防火墙开发的朋友,很是好奇,为啥子需要用.Net开发呢,为啥不用万能的python。然而在认识的同事和朋友中,并没有做.Net开发的(原因未知),就用python尝试一下吧
重点:

  • 管理员权限运行
  • netsh advfirewall firewall 了解一下(手动滑稽)

二、win32com通用

不懂Windows的com组件,只知道python可以用win32com库调用com相关接口,或者加载调用dll库,需要的包:

import pythoncom
import win32com

1. win32com.client.gencache.EnsureDispatch

根据官方声明,调用上述函数会自动生成指定com组件的结构,例如用python运行一下代码:
win32com.client.gencache.EnsureDispatch('HNetCfg.FwMgr', 0)
则会在目录C:\Users\Administrator\AppData\Local\Temp\gen_py\3.6\下生成一个py文件,其中:

class INetFwPolicy2(DispatchBaseClass):
  CLSID = IID('{98325047-C671-4174-8D81-DEFCD3F03186}')
  coclass_clsid = None
      ....
      # 表示该组件的get方法
       _prop_map_get_ = {
      "CurrentProfileTypes": (1, 2, (3, 0), (), "CurrentProfileTypes", None),
      "LocalPolicyModifyState": (15, 2, (3, 0), (), "LocalPolicyModifyState", None),
      # Method 'Rules' returns object of type 'INetFwRules' #Rules保存所有规则,其返回类型为'INetFwRules‘
      "Rules": (7, 2, (9, 0), (), "Rules", '{9C4C6277-5027-441E-AFAE-CA1F542DA009}'),
      # Method 'ServiceRestriction' returns object of type 'INetFwServiceRestriction'
      "ServiceRestriction": (8, 2, (9, 0), (), "ServiceRestriction", '{8267BBE3-F890-491C-B7B6-2DB1EF0E5D2B}'),
  }
  _prop_map_put_ = {
  }
   ...
class INetFwRules(DispatchBaseClass):
  CLSID = IID('{9C4C6277-5027-441E-AFAE-CA1F542DA009}')
  coclass_clsid = None
     ...
  _prop_map_get_ = {
      "Count": (1, 2, (3, 0), (), "Count", None),
  }
  _prop_map_put_ = {
  }
  def __iter__(self):
      "Return a Python iterator for this object"
      try:
          ob = self._oleobj_.InvokeTypes(-4,LCID,2,(13, 10),())
      except pythoncom.error:
          raise TypeError("This object does not support enumeration")
      return win32com.client.util.Iterator(ob, '{AF230D27-BABA-4E42-ACED-F524F22CFCE2}')

注:关于'HNetCfg.FwMgr'的来源--https://www.2cto.com/kf/200904/37096.html

2. 文件说明和接口调用

INetFwPolicy2类为一个com组件,其提供get和set接口,每一项代表一个接口,get接口有:

  • "CurrentProfileTypes": (1, 2, (3, 0), (), "CurrentProfileTypes", None)
  • "LocalPolicyModifyState": (15, 2, (3, 0), (), "LocalPolicyModifyState", None)
  • "Rules": (7, 2, (9, 0), (), "Rules", '{9C4C6277-5027-441E-AFAE-CA1F542DA009}')
  • "ServiceRestriction": (8, 2, (9, 0), (), "ServiceRestriction", '{8267BBE3-F890-491C-B7B6-2DB1EF0E5D2B}')
需要特别注意,元组中最后一项表示该接口返回的类型对应的已注册的com类型,如果为None,如上述的CurrentProfileTypes接口,则可以打印出,一般为数字

通过调用以下代码,来查看一下我们的防火墙规则:

fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
print(fw.CurrentProfileTypes)
rules = fw.Rules
# 此处根据`Rules`的类型{9C4C6277-5027-441E-AFAE-CA1F542DA009}找到INetFwRules
print(rules.Count)
for rule in rules:
   print(rule)# rule的类型查找方法如上,INetFwRules为一个类迭代器,返回类型为{AF230D27-BABA-4E42-ACED-F524F22CFCE2}
   rule = `win32com.client.CastTo(rule, "INetFwRule3")
   print(rule.Name)
  • 根据接口Rules的类型{9C4C6277-5027-441E-AFAE-CA1F542DA009}找到类INetFwRules
  • INetFwRules为一个类迭代器,返回类型为{AF230D27-BABA-4E42-ACED-F524F22CFCE2} INetFwRule即为rule的类型
  • INetFwRule中的getput接口对防火墙规则的一个属性,通过设置属性来获取或设置防火墙
  • INetFwRule中的属性较少,我们可以用rule = win32com.client.CastTo(rule, "INetFwRule3")将其转换为INetFwRule3来查看更多属性
    INetFwRule3属性如下
class INetFwRule(DispatchBaseClass):
  CLSID = IID('{AF230D27-BABA-4E42-ACED-F524F22CFCE2}')
  coclass_clsid = None

  _prop_map_get_ = {
      "Action": (18, 2, (3, 0), (), "Action", None),
      "ApplicationName": (3, 2, (8, 0), (), "ApplicationName", None),
      "Description": (2, 2, (8, 0), (), "Description", None),
      "Direction": (11, 2, (3, 0), (), "Direction", None),
      "EdgeTraversal": (17, 2, (11, 0), (), "EdgeTraversal", None),
      "Enabled": (14, 2, (11, 0), (), "Enabled", None),
      "Grouping": (15, 2, (8, 0), (), "Grouping", None),
      "IcmpTypesAndCodes": (10, 2, (8, 0), (), "IcmpTypesAndCodes", None),
      "InterfaceTypes": (13, 2, (8, 0), (), "InterfaceTypes", None),
      "Interfaces": (12, 2, (12, 0), (), "Interfaces", None),
      "LocalAddresses": (8, 2, (8, 0), (), "LocalAddresses", None),
      "LocalPorts": (6, 2, (8, 0), (), "LocalPorts", None),
      "Name": (1, 2, (8, 0), (), "Name", None),
      "Profiles": (16, 2, (3, 0), (), "Profiles", None),
      "Protocol": (5, 2, (3, 0), (), "Protocol", None),
      "RemoteAddresses": (9, 2, (8, 0), (), "RemoteAddresses", None),
      "RemotePorts": (7, 2, (8, 0), (), "RemotePorts", None),
      "serviceName": (4, 2, (8, 0), (), "serviceName", None),
  }

三、防火墙控制

上述内容中,我们介绍如何使用win32com组件生成py接口类,通过给定的接口查找我们的防火墙规则,以及各个组件属性、调用和返回值。下面将介绍规则属性:

items_name = {
        "Action":'操作',
        "ApplicationName":'程序',
        "Description":'描述',
        "Direction":'进站/出站',
        "EdgeTraversal":'边缘穿越',
        "EdgeTraversalOptions":'边缘穿越选项',
        "Enabled":'已启用',
        "Grouping":'组',
        "IcmpTypesAndCodes":'ICMP设置',
        "InterfaceTypes":'接口类型',
        "Interfaces":'接口',
        "LocalAddresses":'本地地址',
        "LocalAppPackageId":'应用程序包',
        "LocalPorts":'本地端口',
        "LocalUserAuthorizedList":'授权的本地计算机',
        "LocalUserOwner":'本地用户所有者',
        "Name":'名称',
        "Profiles":'配置文件',
        "Protocol":'协议',
        "RemoteAddresses":'远程地址',
        "RemoteMachineAuthorizedList":'授权的远程计算机',
        "RemotePorts":'远程端口',
        "RemoteUserAuthorizedList":'授权的远程用户',
        "SecureFlags":'安全',
        "serviceName":'服务名'}
防火墙规则请参考Windows文档(皮一下),接口文档

四、全量代码

# fw_rules.py

class rule:
    items = {}
    # 中英文转换
    items_name = {
        "Action":'操作',
        "ApplicationName":'程序',
        "Description":'描述',
        "Direction":'进站/出站',
        "EdgeTraversal":'边缘穿越',
        "EdgeTraversalOptions":'边缘穿越选项',
        "Enabled":'已启用',
        "Grouping":'组',
        "IcmpTypesAndCodes":'ICMP设置',
        "InterfaceTypes":'接口类型',
        "Interfaces":'接口',
        "LocalAddresses":'本地地址',
        "LocalAppPackageId":'应用程序包',
        "LocalPorts":'本地端口',
        "LocalUserAuthorizedList":'授权的本地计算机',
        "LocalUserOwner":'本地用户所有者',
        "Name":'名称',
        "Profiles":'配置文件',
        "Protocol":'协议',
        "RemoteAddresses":'远程地址',
        "RemoteMachineAuthorizedList":'授权的远程计算机',
        "RemotePorts":'远程端口',
        "RemoteUserAuthorizedList":'授权的远程用户',
        "SecureFlags":'安全',
        "serviceName":'服务名'}
    items_shell = {
        "Action": 'action',
        "ApplicationName": 'program',
        "Description": 'description',
        "Direction": 'dir',
        "EdgeTraversal": 'edge',
        "EdgeTraversalOptions": '边缘穿越选项',
        "Enabled": 'enable',
        "Grouping": '组',
        "IcmpTypesAndCodes": 'ICMP设置',
        "InterfaceTypes": 'interfacetype',
        "Interfaces": '接口',
        "LocalAddresses": 'localip',
        "LocalAppPackageId": '应用程序包',
        "LocalPorts": 'localport',
        "LocalUserAuthorizedList": '授权的本地计算机',
        "LocalUserOwner": '本地用户所有者',
        "Name": 'name',
        "Profiles": 'profile',
        "Protocol": 'protocol',
        "RemoteAddresses": 'remoteip',
        "RemoteMachineAuthorizedList": 'rmtcomputergrp',
        "RemotePorts": 'remoteport',
        "RemoteUserAuthorizedList": 'rmtusrgrp',
        "SecureFlags": 'security',
        "serviceName": 'service'
    }
    def __init__(self,index):
        self.index = index
        for i in self.items_name.keys():
            self.items[i] = ''

    def init_by_app(self, app_in):
        for key in self.items_name.keys():
            self.items[key] = " " + str(eval("app_in."+key))
            print(self.items[key] )

    def init_by_dict(self,dirc_con):
        flag = False
        for item_key in self.items_name.keys():
            if self.items_name[item_key] in dirc_con.keys():
                flag = True
                self.items[item_key] = dirc_con[self.items_name[item_key]]

        if not flag:
            for key in dirc_con.keys():
                self.items[key] = dirc_con[key]

    def create_rule(self):
        app = win32com.client.Dispatch('HNetCfg.FwRule')
        res = []
        # 注意赋值顺序
        app.Action = int(self.items["Action"])
        app.Description = self.items["Description"]
        app.Direction = int(self.items["Direction"])
        app.EdgeTraversal = self.items["EdgeTraversal"]
        app.EdgeTraversalOptions = self.items["EdgeTraversalOptions"]
        app.Enabled = self.items["Enabled"]
        app.Grouping = self.items["Grouping"]
        ## app.IcmpTypesAndCodes = self.items["IcmpTypesAndCodes"]
        app.InterfaceTypes = self.items["InterfaceTypes"]
        ## app.Interfaces = self.items["Interfaces"]
        app.LocalAddresses = self.items["LocalAddresses"]
        app.LocalAppPackageId = self.items["LocalAppPackageId"]
        ## app.LocalPorts = str(self.items["LocalPorts"]),
        ## app.LocalUserAuthorizedList = self.items["LocalUserAuthorizedList"]
        app.LocalUserOwner = self.items["LocalUserOwner"]
        app.Name = self.items["Name"]
        app.Profiles = self.items["Profiles"]
        app.Protocol = self.items["Protocol"]
        app.RemoteAddresses = self.items["RemoteAddresses"]
        ## app.RemoteMachineAuthorizedList = self.items["RemoteMachineAuthorizedList"]
        app.RemotePorts = self.items["RemotePorts"]
        app.LocalPorts = self.items['LocalPorts']
        ## app.RemoteUserAuthorizedList = ''
        app.SecureFlags = self.items["SecureFlags"]
        # app.serviceName = "null"
        # app.ApplicationName = "null"
        return app

    def __str__(self):
        result = "="*10 + '\n序号 : ' + str(self.index) + '\n'
        for key in self.items_name.keys():
            result += self.items_name[key] + " : " + str(self.items[key]) +"\n"
        return result

def add_rule(dict_value):
    fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
    apps = fw.Rules
    print(apps.Count)
    # app = win32com.client.Dispatch('HNetCfg.FwRule3')
    rule_obj = rule(-1)
    rule_obj.init_by_dict(dict_value)
    app = rule_obj.create_rule()
    apps.Add(app)

def del_rule(dict_value):

    fw = win32com.client.gencache.EnsureDispatch('HNetCfg.FwPolicy2', 0)
    apps = fw.Rules
    print("before :", apps.Count)
    rule_obj = rule(-1)
    rule_obj.init_by_dict(dict_value)
    for app in apps:
        print(rule_obj.items['Name'] , str(app.Name))
        print(rule_obj.items['LocalPorts'] , str(app.LocalPorts))
        print(rule_obj.items['RemoteAddresses'] , str(app.RemoteAddresses))
        if rule_obj.items['Name'] == str(app.Name) and rule_obj.items['LocalPorts'] == str(app.LocalPorts) and rule_obj.items['RemoteAddresses'] == str(app.RemoteAddresses):
            # 只能根据Name删除,大概是个傻子哟
            apps.Remove(str(app.Name))
            # break
    print("after :", apps.Count)

if __name__ == '__main__':
    my_dict = {
    '序号' : '2',
    '操作' : '0',
    '程序' : '',
    '描述' : '',
    '进站/出站' : '1',
    '边缘穿越' : 'False',
    '边缘穿越选项' : '0',
    '已启用' : 'True',
    '组' : '',
    'ICMP设置' : '',
    '接口类型' : 'All',
    '接口' : 'None',
    '本地地址' : '*',
    '应用程序包' : '',
    '本地端口' : '9876',
    '授权的本地计算机' : '',
    '本地用户所有者' : '',
    '名称' : 'test_cmd',
    '配置文件' : '2',
    '协议' : '6',
    '远程地址' : '114.115.250.41/255.255.255.255',
    '授权的远程计算机' : '',
    '远程端口' : '*',
    '授权的远程用户' : '',
    '安全' : '0',
    '服务名' : ''
    }
    add_rule(my_dict)
    del_rule(my_dict)

原创不易,不喜勿喷
https://www.jianshu.com/p/78e70e8e363d

你可能感兴趣的:(python 控制Windows防火墙(FireWall))