Salt 之 ipset 模块实战:用执行模块与状态模块管理 iptables IP 集合

发布时间:2026/9/23 14:19:28
Salt 之 ipset 模块实战:用执行模块与状态模块管理 iptables IP 集合 Salt 之 ipset 模块实战用执行模块与状态模块管理 iptables IP 集合【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址: https://gitcode.com/gh_mirrors/sa/salt本文基于当前开源仓库中的 ipset 模块文档doc/ref/modules/all/salt.modules.ipset.rst展开系统讲解 Salt 如何通过执行模块salt.modules.ipset与状态模块salt.states.ipset管理 Linux 内核的 IP 集合ipset用于配合 iptables 防火墙实现高效的 IP/端口/网段批量匹配。读完本文你将掌握 ipset 集合的创建、增删改查、清空等全部命令的调用方式理解底层参数映射与校验逻辑并能在 SLS 状态文件中实现集合与成员的幂等管理。模块定位与加载条件ipset 模块用于操作 Linux 内核提供的 ipset 工具——一种面向 iptables 的高性能集合数据结构可将大量 IP 地址、网段、端口、MAC 地址等组织为命名集合供防火墙规则引用避免逐条编写 iptables 规则。Salt 将该能力封装为统一接口便于通过salt * ipset.xxx批量下发到所有 minion。从源码 salt/modules/ipset.py 可见模块的__virtual__()会检查系统中是否存在ipset二进制文件def __virtual__(): if salt.utils.path.which(ipset): return True return ( False, The ipset execution modules cannot be loaded: ipset binary not in path., )也就是说只有在 minion 上安装了ipset命令如yum install ipset或apt install ipset时模块才会被加载否则返回加载失败原因。状态模块 salt/states/ipset.py 则依赖执行模块是否可用ipset.version in __salt__来决定是否加载。集合类型与地址族映射模块内部维护了两张核心常量表这是理解所有命令参数的基础。支持的集合类型_IPSET_SET_TYPES源码 salt/modules/ipset.py 定义了模块支持的全部 15 种集合类型集合类型说明bitmap:ipIP 位图必须指定 rangebitmap:ip,macIPMAC 位图bitmap:port端口位图hash:ipIP 哈希hash:macMAC 哈希hash:ip,portIP端口哈希hash:ip,port,ipIP端口IP 哈希hash:ip,port,netIP端口网段哈希hash:net网段哈希hash:net,net网段网段哈希hash:net,iface网段网卡接口哈希hash:net,port网段端口哈希hash:net,port,net网段端口网段哈希hash:ip,markIP防火墙标记mark哈希list:set集合的列表可聚合其他集合地址族映射_IPSET_FAMILIES源码 salt/modules/ipset.py 将 family 参数映射为 ipset 命令内部的 inet 族_IPSET_FAMILIES { ipv4: inet, ip4: inet, ipv6: inet6, ip6: inet6, }即family参数既支持完整的ipv4/ipv6也兼容ip4/ip6缩写。默认值为ipv4。执行模块函数全解析以下函数均位于 salt/modules/ipset.py命令通过__salt__[cmd.run]在 minion 本地执行python_shellFalse保证不经过 shell 解释。version——查看 ipset 版本执行ipset --version并解析出版本号salt * ipset.version实现见 salt/modules/ipset.py先运行ipset --version对输出按空白切分后取第二个字段作为版本返回。new_set——创建集合new_set是使用频率最高的函数之一负责创建自定义集合。其签名与典型调用如下自 2014.7.0 版本加入def new_set(nameNone, set_typeNone, familyipv4, commentFalse, **kwargs):CLI 示例源码 salt/modules/ipset.py# 创建一个 list:set 类型的集合 salt * ipset.new_set custom_set list:set # 带注释创建 salt * ipset.new_set custom_set list:set commentTrue # IPv6 salt * ipset.new_set custom_set list:set familyipv6创建过程会依次校验集合名必须指定、集合类型必须指定、类型必须在_IPSET_SET_TYPES中。随后通过_CREATE_OPTIONS_REQUIRED检查该类型必须携带的参数如bitmap:ip必须提供range再按_CREATE_OPTIONS中的选项表拼接ipset create name type [options]命令。各类型创建选项表_CREATE_OPTIONS源码 salt/modules/ipset.py 定义了每种类型可用的创建选项bitmap 系列bitmap:ip、bitmap:ip,mac、bitmap:portrange必填、timeout、counters、comment、skbinfohash 系列hash:ip、hash:net、hash:net,net、hash:net,port、hash:net,port,net、hash:ip,port、hash:ip,port,ip、hash:ip,port,net、hash:net,ifacefamily、hashsize、maxelem、netmask、timeout、counters、comment、skbinfohash:machashsize、maxelem、timeout、counters、comment、skbinfohash:ip,mark额外支持markmasklist:setsize、timeout、counters、comment其中comment、counters、skbinfo属于无值选项_CREATE_OPTIONS_WITHOUT_VALUE见 salt/modules/ipset.py拼接命令时不带值直接追加选项名。必填选项表_CREATE_OPTIONS_REQUIRED源码 salt/modules/ipset.py 中仅 bitmap 系列要求range必填其余 hash/list 系列无必填项_CREATE_OPTIONS_REQUIRED { bitmap:ip: [range], bitmap:ip,mac: [range], bitmap:port: [range], hash:ip: [], # ... 其余 hash/list 类型均为空列表 }此外仅当集合类型支持family选项时才追加family inet|inet6参数commentTrue时追加comment标志。命令成功无输出时返回True。单元测试 tests/pytests/unit/modules/test_ipset.py 验证了缺失名称、缺失类型、非法类型、bitmap 缺range时的错误返回以及成功路径返回True的行为。delete_set——删除集合执行ipset destroy name删除整个集合自 2014.7.0 加入salt * ipset.delete_set custom_set salt * ipset.delete_set custom_set familyipv6实现见 salt/modules/ipset.py未指定名称时返回Error: Set needs to be specified。rename_set——重命名集合salt * ipset.rename_set custom_set new_setnew_set_name salt * ipset.rename_set custom_set new_setnew_set_name familyipv6实现见 salt/modules/ipset.py。重命名前会先通过_find_set_type确认原集合存在、新名称未被占用两个前置校验失败分别返回Error: Set does not exist和Error: New Set already exists再执行ipset rename old new。list_sets——列出所有集合salt * ipset.list_sets实现见 salt/modules/ipset.py。执行ipset list -t将输出按空行切分为多个集合对象每一行按key: value解析成字典返回由多个字典组成的列表每个字典含Name、Type、Header等字段。check_set——检查集合是否存在salt * ipset.check_set name实现见 salt/modules/ipset.py。内部调用_find_set_info执行ipset list -t name集合存在返回True不存在返回False。add——向集合追加条目# 追加单个 IP salt * ipset.add name 192.168.1.26 # 追加 IPMAC 复合条目 salt * ipset.add name 192.168.0.3,AA:BB:CC:DD:EE:FF # 带注释entry 内联写法 salt * ipset.add name 192.168.0.1 comment Hello实现见 salt/modules/ipset.py是校验最丰富的函数之一名称与条目必填集合必须存在_find_set_info返回集合元信息包括Type与Header命令使用ipset add -exist name entry...-exist保证条目已存在时不会报错同时可用于更新条目的注释选项与集合创建能力绑定校验传入timeout时集合 Header 必须包含timeout否则返回Error: Set {name} not created with timeout support传入packets/bytes时集合必须创建于counters支持传入comment时集合必须创建于comment支持传入skbmark/skbprio/skbqueue时集合必须创建于skbinfo支持通过_ADD_OPTIONS选项表见 salt/modules/ipset.py拼接条目附加选项如hash:net系列额外支持nomatch先读取集合现有成员若条目已存在返回Warn: Entry {entry} already exists in set {name}命令成功返回Success失败返回Error: {输出}。单元测试 tests/pytests/unit/modules/test_ipset.py 覆盖了缺失参数、集合不存在、timeout/counters/comment 能力校验、重复条目告警以及成功路径。功能测试 tests/pytests/functional/modules/test_ipset.py 则演示了真实环境下的bitmap:ip集合创建与条目添加。delete——删除集合条目salt * ipset.delete name 192.168.0.3,AA:BB:CC:DD:EE:FF实现见 salt/modules/ipset.py。校验集合存在后执行ipset del name entry成功返回Success。check——检查条目是否在集合中智能匹配check是模块中智能度最高的函数它不只是简单执行ipset test而是读取集合成员后用 Python 的ipaddress库做语义化匹配# 单 IP salt * ipset.check name 192.168.0.1 # IP 范围 salt * ipset.check name 192.168.0.2-192.168.0.19 # 子网 salt * ipset.check name 192.168.0.0/25 # 带注释的条目 salt * ipset.check name 192.168.0.1 comment Hello参数说明源码 salt/modules/ipset.pyname集合名entry单个 IP、IP 范围或子网块支持传列表familyipv4 或 ipv6。匹配逻辑依赖辅助函数链_parse_members→_parse_member→_member_contains→_compare_member_parts见 salt/modules/ipset.py。核心能力包括按集合类型如hash:net拆分子类型ip/net字段尝试解析为ipaddress.IPv4Network/IPv6Network或IPv4Address/IPv6Addressport转为整数IP 范围a-b用summarize_address_range展开为网段列表子网包含关系判断如集合成员为192.168.0.4/31检查192.168.0.4/30时能正确判定包含/被包含关系见 salt/modules/ipset.py。单元测试 tests/pytests/unit/modules/test_ipset.py 对hash:ip与hash:net两种类型分别验证了单 IP、/31网段、范围条目的匹配结果。test——用内核测试条目是否在集合中与check的语义化解析不同test直接调用底层ipset test name entry命令依据退出码判断salt * ipset.test name 192.168.0.2 salt * ipset.test name fd81:fc56:9ac7::/48 # IPv6实现见 salt/modules/ipset.py使用cmd.run_all执行retcode 0返回False否则返回True。单元测试 tests/pytests/unit/modules/test_ipset.py 验证了该退出码判定逻辑。flush——清空集合条目不指定集合时清空所有集合指定时只清空该集合salt * ipset.flush salt * ipset.flush set salt * ipset.flush # IPv6 同理 salt * ipset.flush set实现见 salt/modules/ipset.py执行ipset flush [name]命令无输出成功时返回True。状态模块以声明式 SLS 管理 ipsetsalt.states.ipset源码 salt/states/ipset.py将上述执行模块封装为幂等的声明式状态自 2014.7.0 加入共五个状态函数。所有状态均遵循 Salt 标准返回结构name、changes、result、comment并支持testTrue试运行模式此时返回result: None与“would be...”注释。set_present / set_absent——管理集合本身setname: ipset.set_present: - set_type: bitmap:ip - range: 192.168.0.0/16 - comment: True setname: ipset.set_absent: - set_type: bitmap:ip - range: 192.168.0.0/16 - comment: Trueset_presentsalt/states/ipset.py先check_set判断已存在则直接成功test 模式提示“would be added”否则调用ipset.new_set成功后记录 changes。set_absentsalt/states/ipset.py集合不存在视为成功存在时先ipset.flush清空再ipset.delete_set删除。present / absent——管理集合条目setname_entries: ipset.present: - set_name: setname - entry: 192.168.0.3 - comment: Hello - require: - ipset: baz setname_entries: ipset.present: - set_name: setname - entry: - 192.168.0.3 - 192.168.1.3 - comment: Hello - require: - ipset: baz setname_entries: ipset.absent: - set_name: setname - entry: - 192.168.0.3 - 192.168.1.3 - comment: Hello - require: - ipset: bazpresentsalt/states/ipset.pyname只是状态内部的用户自定义标识并非真实条目entry支持单个值或列表。状态会自动把timeout、comment等 kwargs 拼入条目字符串如timeout 300 comment Hello先ipset.check判断条目是否已存在不存在才调用ipset.add。absentsalt/states/ipset.py逻辑相反条目已不在集合中视为成功存在则调用ipset.delete移除。flush——清空指定集合setname: ipset.flush:实现见 salt/states/ipset.py集合不存在直接失败test 模式提示“would be flushed”否则调用执行模块的ipset.flush。功能测试 tests/pytests/functional/states/test_ipset.py 验证了states.ipset.present在真实 ipset 环境下的添加行为与注释输出格式。典型实战配合 iptables 的完整链路结合执行模块与状态模块一个典型场景——在 minion 上维护“黑名单 IP 集合”并让 iptables 引用它# 1. 创建 hash:net 集合支持网段与超时 salt * ipset.new_set blacklist hash:net familyipv4 timeout86400 commentTrue # 2. 添加条目 salt * ipset.add blacklist 203.0.113.5 salt * ipset.add blacklist 198.51.100.0/24 comment spam net # 3. 校验 salt * ipset.list_sets salt * ipset.check blacklist 198.51.100.0/24 salt * ipset.test blacklist 203.0.113.5 # 4. 清空/删除 salt * ipset.flush blacklist salt * ipset.delete_set blacklist等价的状态声明blacklist: ipset.set_present: - set_type: hash:net - family: ipv4 - timeout: 86400 - comment: True blacklist_entries: ipset.present: - set_name: blacklist - entry: - 203.0.113.5 - 198.51.100.0/24 - comment: spam net - require: - ipset: blacklist随后在 iptables 中引用该集合可配合 Salt 的 iptables 状态模块iptables -A INPUT -m set --match-set blacklist src -j DROP注意事项与适用前提依赖 ipset 二进制模块通过which(ipset)检测未安装时执行模块与状态模块均不加载详见 salt/modules/ipset.py。能力校验是双向的向集合add带 timeout/counters/comment/skbinfo 的条目时集合本身必须在创建时启用了对应能力否则返回明确错误。check与test语义不同test依赖内核精确匹配check由 Python 侧解析 IP 对象支持范围/子网包含关系判断适合状态模块做幂等判断但也依赖集合类型解析正确。条目内联注释check与add均支持在 entry 中携带comment xxx片段见 salt/modules/ipset.py状态模块会自动拼装timeout/comment到条目字符串中。IPv6 支持所有函数均接受familyipv6或ip6最终映射为inet6族。执行环境为 Linux 内核 ipset该模块面向 Linux 系统Windows 下不可用功能测试也通过skip_if_binaries_missing(ipset)跳过。延伸阅读执行模块完整实现salt/modules/ipset.py状态模块完整实现salt/states/ipset.py状态模块文档doc/ref/states/all/salt.states.ipset.rst单元测试tests/pytests/unit/modules/test_ipset.py功能测试tests/pytests/functional/modules/test_ipset.py、tests/pytests/functional/states/test_ipset.py【免费下载链接】saltSoftware to automate the management and configuration of infrastructure and applications at scale.项目地址: https://gitcode.com/gh_mirrors/sa/salt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询