Harmony os 网络防火墙实战:用 @ohos.net.netFirewall 给应用加一道“网闸”

Harmony os 网络防火墙实战:用 @ohos.net.netFirewall 给应用加一道"网闸"

这段时间一直在翻 HarmonyOS 的 Network Kit 文档,看到一个以前没怎么注意过的小模块:@ohos.net.netFirewall。看完文档的第一反应是------这玩意儿太适合做"桌面级防火墙设置面板"了 ,而且官方已经把增删改查都封装好了,我们只要写 UI 就行。developer.huawei.com

这篇就当是我自己的学习记录,也顺手给以后要接这个能力的同学一点参考:怎么用 ArkTS 操作系统级网络防火墙


一、这个模块到底能干嘛?

先把官方提供的能力翻成"人话":

  • 查 / 改防火墙总开关和默认策略
    • getNetFirewallPolicy(userId)
    • setNetFirewallPolicy(userId, policy)
    • 能看到当前防火墙是不是开着、默认入站是放行还是拒绝、默认出站是放行还是拒绝。developer.huawei.com+1
  • 对规则做增删改查
    • 新增:addNetFirewallRule(rule): Promise<number>
    • 修改:updateNetFirewallRule(rule)
    • 删除:removeNetFirewallRule(userId, ruleId)
    • 查询单条:getNetFirewallRule(userId, ruleId)
    • 分页查询:getNetFirewallRules(userId, requestParam)(带排序、分页)developer.huawei.com
  • 支持三类规则
    • IP 规则:按 IP / 端口 / 协议控制流量
    • 域名规则:按域名 / 通配符 *.example.com 控制
    • DNS 规则:按 DNS 服务器维度控制

再加几个现实中的限制:

  • 支持设备 :PC / 2in1 / TV(手机上你是看不到这个能力的)。developer.huawei.com
  • 系统能力SystemCapability.Communication.NetManager.NetFirewall
  • 权限
    • 查询类:ohos.permission.GET_NET_FIREWALL
    • 管理类(增删改):ohos.permission.MANAGE_NET_FIREWALL

从能力和权限就能看出来,这玩意儿偏系统管理场景,大概率是给系统应用、桌面管理工具这类用的,普通三方 App 就别太乐观了。


二、先把"总闸"搞清楚:NetFirewallPolicy

整个防火墙的开关和默认策略由 NetFirewallPolicy 控制,结构很简单:developer.huawei.com

  • isOpen: boolean
    • true:防火墙整体开启
    • false:防火墙整体关闭
  • inAction: FirewallRuleAction
  • outAction: FirewallRuleAction
    • 枚举 FirewallRuleAction
      • RULE_ALLOW = 0:允许
      • RULE_DENY = 1:拒绝

典型用途:

  • 家用环境:
    • 入站:默认拒绝(inAction = RULE_DENY
    • 出站:默认允许(outAction = RULE_ALLOW
  • 超狠的管控环境:
    • 入站 / 出站都默认拒绝,然后只放行白名单应用 / IP 段

查询 + 设置防火墙策略的示例

复制代码
import { netFirewall } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

const USER_ID = 100; // 示例多用户 ID,根据系统实际为准

async function toggleFirewall() {
  try {
    const policy = await netFirewall.getNetFirewallPolicy(USER_ID);
    console.info('当前策略:', JSON.stringify(policy));

    // 如果没开,就顺手打开,顺带设个"入站禁、出站放"的策略
    if (!policy.isOpen) {
      const newPolicy: netFirewall.NetFirewallPolicy = {
        isOpen: true,
        inAction: netFirewall.FirewallRuleAction.RULE_DENY,
        outAction: netFirewall.FirewallRuleAction.RULE_ALLOW
      };
      await netFirewall.setNetFirewallPolicy(USER_ID, newPolicy);
      console.info('防火墙已开启并更新策略');
    }
  } catch (err) {
    const be = err as BusinessError;
    console.error(`操作防火墙策略失败:code=${be.code}, msg=${be.message}`);
  }
}

三、真正好玩的在这里:NetFirewallRule 长什么样?

所有具体"怎么拦、拦谁"的逻辑都落在 NetFirewallRule 上。这个结构比较长,我按块拆一下。developer.huawei.com

1. 通用字段(所有类型规则都有)

  • userId: number
    多用户场景下属于哪个用户,必须是系统存在的 userId,否则直接 29400000 把你弹回去。
  • name: string(必填,≤128 字符)
    规则名,建议写人能看懂的那种,比如:"Block WeChat TCP 443"
  • description?: string(≤256 字符)
    扩展说明,给以后排查问题的自己留点线索。
  • direction: NetFirewallRuleDirection
    • RULE_IN = 1:入站
    • RULE_OUT = 2:出站
  • action: FirewallRuleAction
    • RULE_ALLOW / RULE_DENY
  • type: NetFirewallRuleType
    • RULE_IP = 1:按 IP / 端口 / 协议控制
    • RULE_DOMAIN = 2:按域名控制
    • RULE_DNS = 3:按 DNS 服务器控制
  • isEnabled: boolean
    • true:规则生效
    • false:规则存在但不生效(相当于 UI 上的开关)
  • id?: number
    规则 ID,由系统在 add 时生成,后面 update / delete 都要用它。
  • appUid?: number
    针对某个应用 / 服务的 UID 做限制,用这个字段就能玩出"只拦某个 App"的效果。

2. IP 规则专属字段:localIps / remoteIps / ports / protocol

type = RULE_IP 时,这几个字段才有意义:developer.huawei.com+1

  • localIps: NetFirewallIpParams[]
  • remoteIps: NetFirewallIpParams[]
  • protocol?: number
    • 6:TCP
    • 17:UDP
  • localPorts: NetFirewallPortParams[]
  • remotePorts: NetFirewallPortParams[]

NetFirewallIpParams 结构:

  • type: number(必填)
    • 1:单个 IP 或子网(需要 address + mask
    • 2:IP 段(需要 startIp + endIp
  • family?: number
    • 1:IPv4
    • 2:IPv6(文档里写了,实际当前主要还是 IPv4)
  • address?: string
  • mask?: number
  • startIp?: string
  • endIp?: string

数量限制 (否则会报 29400002 / 29400003):developer.huawei.com+1

  • localIps / remoteIps:最多 10 个
  • localPorts / remotePorts:最多 10 个

端口结构 NetFirewallPortParams

  • startPort: number
  • endPort: number
    如果只要一个端口,就让 startPort = endPort

3. 域名规则字段:domains

type = RULE_DOMAIN 时才用得上:developer.huawei.com+1

  • domains: NetFirewallDomainParams[]

NetFirewallDomainParams

  • isWildcard: boolean
    • true:带通配符,比如 *.example.cn
    • false:完整域名,比如 www.example.cn
  • domain: string

同样有数量限制,不然会报:

  • 29400004 / 29400005:域名规则 / 域名数量超限

4. DNS 规则字段:dns

type = RULE_DNS 时有效:developer.huawei.com+1

  • dns: NetFirewallDnsParams
    • primaryDns: string
    • standbyDns?: string

如果你加了两个一模一样的 DNS 规则,会被 29400007 告诉你"重复了"。


四、实战 1:给某个应用拦掉一段出站 IP 段

假设场景:

我想让用户 UID 为 20001 的某个应用,禁止它访问 20.10.1.0/24 的 TCP 443 端口(比如禁它访问某个外网服务)。

可以写一条出站 IP 规则:

复制代码
import { netFirewall } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

const USER_ID = 100;

async function addIpDenyRule() {
  const rule: netFirewall.NetFirewallRule = {
    userId: USER_ID,
    name: 'BlockApp20001_20.10.1.0_443',
    description: '拦截 appUid=20001 访问 20.10.1.0/24:443',
    direction: netFirewall.NetFirewallRuleDirection.RULE_OUT,
    action: netFirewall.FirewallRuleAction.RULE_DENY,
    type: netFirewall.NetFirewallRuleType.RULE_IP,
    isEnabled: true,
    appUid: 20001,
    localIps: [
      // 本地可以不填,表示本机所有地址
    ],
    remoteIps: [
      {
        family: 1,      // IPv4
        type: 1,        // 单 IP/子网
        address: '20.10.1.0',
        mask: 24
      }
    ],
    protocol: 6,        // TCP
    localPorts: [
      // 本地端口不限
    ],
    remotePorts: [
      {
        startPort: 443,
        endPort: 443
      }
    ]
  };

  try {
    const ruleId = await netFirewall.addNetFirewallRule(rule);
    console.info('新增防火墙规则成功,ruleId = ', ruleId);
  } catch (err) {
    const be = err as BusinessError;
    console.error(`新增防火墙规则失败:code=${be.code}, msg=${be.message}`);
  }
}

如果你把 IP / 端口数组写太多,遇到 29400002 / 29400003,十有八九就是你一条规则塞太满了,拆几条就好。


五、实战 2:用域名规则一键拉黑一批网站

再来一个"家长模式"的例子:

我想禁止某个用户访问 www.example.cn 以及所有 *.example.cn

直接搞域名规则:

复制代码
async function addDomainDenyRule() {
  const rule: netFirewall.NetFirewallRule = {
    userId: 100,
    name: 'Block_example_domain',
    description: '拦截 example.cn 全家桶',
    direction: netFirewall.NetFirewallRuleDirection.RULE_OUT,
    action: netFirewall.FirewallRuleAction.RULE_DENY,
    type: netFirewall.NetFirewallRuleType.RULE_DOMAIN,
    isEnabled: true,
    appUid: 0, // 不指定具体应用,默认对用户全局生效
    domains: [
      {
        isWildcard: false,
        domain: 'www.example.cn'
      },
      {
        isWildcard: true,
        domain: '*.example.cn'
      }
    ]
  };

  try {
    const ruleId = await netFirewall.addNetFirewallRule(rule);
    console.info('新增域名规则成功,ruleId = ', ruleId);
  } catch (err) {
    const be = err as BusinessError;
    console.error(`新增域名规则失败:code=${be.code}, msg=${be.message}`);
  }
}

如果你发现加第 N 条域名规则死活不成功,看一下返回错误是不是 29400004 / 29400005,很可能是数量超限了。developer.huawei.com+1


六、实战 3:做一个简单规则管理面板(分页 + 开关)

如果你想做一个"防火墙管理"应用,最基础的就是把所有规则列表拉出来,然后让用户能:

  • 看见每条规则的名字 / 类型 / 方向 / 状态
  • 点进去编辑
  • 点一下按钮启用 / 禁用
  • 删除

1)分页查询规则列表

getNetFirewallRules(userId, requestParam) 就是干这个的:developer.huawei.com

复制代码
async function listRules(page: number, pageSize: number) {
  const req: netFirewall.RequestParam = {
    page,
    pageSize,
    orderField: netFirewall.NetFirewallOrderField.ORDER_BY_RULE_NAME,
    orderType: netFirewall.NetFirewallOrderType.ORDER_ASC
  };

  try {
    const result = await netFirewall.getNetFirewallRules(100, req);
    console.info('分页结果:', JSON.stringify(result));

    const { data, totalPage } = result;
    // data 就是一页的规则列表,直接丢给你的 ArkUI 列表组件即可
    return { rules: data, totalPage };
  } catch (err) {
    const be = err as BusinessError;
    console.error(`获取规则列表失败:code=${be.code}, msg=${be.message}`);
    return { rules: [], totalPage: 0 };
  }
}

FirewallRulePage 结构:

  • page / pageSize / totalPage
  • data: NetFirewallRule[]

UI 上就很常规:分页按钮 + 列表。

2)开关"启用 / 禁用"规则

思路是:

  1. 先用 getNetFirewallRule(userId, ruleId) 把整条规则拉出来

  2. 改一下 isEnabled,再 updateNetFirewallRule(rule)

    async function toggleRuleEnabled(userId: number, ruleId: number, enabled: boolean) {
    try {
    const rule = await netFirewall.getNetFirewallRule(userId, ruleId);
    rule.isEnabled = enabled;
    await netFirewall.updateNetFirewallRule(rule);
    console.info(规则 ${ruleId} 已更新 isEnabled=${enabled});
    } catch (err) {
    const be = err as BusinessError;
    console.error(切换规则状态失败:code=${be.code}, msg=${be.message});
    }
    }

如果更新的时候提示 29400006,说明这条规则已经被别人删掉了,你这边的 ruleId 只是"尸体"。

3)删除规则

复制代码
async function removeRule(userId: number, ruleId: number) {
  try {
    await netFirewall.removeNetFirewallRule(userId, ruleId);
    console.info(`删除规则 ${ruleId} 成功`);
  } catch (err) {
    const be = err as BusinessError;
    console.error(`删除规则失败:code=${be.code}, msg=${be.message}`);
  }
}

七、错误码小抄(踩坑专用)

这个模块的错误码挺有"个性"的,我自己整理了一份"翻译"版:developer.huawei.com+1

  • 201 Permission denied
    • 权限不给面子:
      • 要么你没在配置里声明对应权限
      • 要么你的应用根本不在"能用这个系统能力"的白名单里
  • 401 Parameter error / 2100001 Invalid parameter value
    • 典型情况:
      • userId 不存在
      • page / pageSize 越界
      • mask / startIp / endIp 搞错
  • 2100002 Operation failed. Cannot connect to service
    • 后台服务没起来 / 出问题了,这种一般只能看系统日志。
  • 29400000 The specified user does not exist
    • 多用户 ID 写错了,直接对着系统用户列表改。
  • 29400001 防火墙规则总数超限
    • 说明你太能加了,考虑把一些规则合并一下。
  • 29400002 / 29400003 / 29400004 / 29400005
    • 某一条规则里 IP / 端口 / 域名数量超过上限了,把一个庞然大物拆成几条小规则。
  • 29400006 The specified rule does not exist
    • 更新 / 删除的时候,ruleId 已经失效。
  • 29400007 The dns rule is duplication
    • 同样的 DNS 规则已经存在了,没必要再加一次。

八、适合拿来干什么?

从现在这套能力来看,我自己能想到几个比较顺手的用法:

  1. 系统级"网络安全管家"
    • 做一个类似桌面系统的防火墙配置中心:
      • 总开关 + 默认策略
      • 应用维度 + IP / 域名维度的规则管理
    • 把系统底层能力包装成一个较友好 UI
  2. 企业/校园一体机的"策略下发终端"
    • 企业在后台配置好一堆规则
    • 前端设备上的 App 用 @ohos.net.netFirewall 去同步本地策略
  3. 家长控制 / 自律模式 Demo
    • 用域名规则禁一些类型的网站
    • 再配合时间段控制(例如别的模块控制),可以玩出"晚上 10 点之后全网断联"这类功能

最后

@ohos.net.netFirewall 给人的感觉就是:底层已经帮我们把"拦网"这个脏活累活干完了,我们只需要专心搞好规则建模 + 管理 UI 就行。

以后如果我真的写一个"PC 版网络管家"或者"家长控制模式"的 Demo,大概率就是:

  • UI 层:ArkUI + 状态管理
  • 逻辑层:netFirewall.get* / set* / add* / update* / remove*
  • 结合一点日志 / 拦截记录展示(拦截记录那块接口和分页查规则很像,这里就先不展开了)
相关推荐
吴声子夜歌40 分钟前
Windows——网络相关命令
网络·windows·php
qq_376766241 小时前
机房U位资产管理系统的数据分析能力:如何让数据中心运维效率升级?
网络·人工智能
马剑威(威哥爱编程)1 小时前
【鸿蒙开发实战篇】如何实现高级图片滤镜
华为·harmonyos
Freshman小白1 小时前
《英文科技论文写作与学术报告》网课答案(雨课堂、学堂在线...)
网络·学习·答案
马剑威(威哥爱编程)1 小时前
【鸿蒙开发实战篇】鸿蒙6.0图片编辑实战:PixelMap与Canvas的完美结合
华为·harmonyos
m0_738120721 小时前
渗透测试——Kioptrix5靶机渗透测试详细教程
网络·python·安全·web安全·ssh
勇气要爆发1 小时前
问:HTTP和HTTPS的区别及安全性
网络
AhaPuPu1 小时前
LLM Agent Attack- Indirect Prompt Injection
网络·人工智能·prompt
wadesir1 小时前
提升系统效率的关键(Linux文件系统性能优化入门教程)
linux·网络·性能优化