刚接手一个网络加固需求的时候,总有那么几个看似简单、动手就翻车的任务。“拒绝所有IP访问445端口,但允许特定IP访问”就是典型代表。445端口在Windows环境里承担着SMB文件共享的职责,也经常被各种利用445端口的恶意程序盯上,很多单位在安全处置时要求全网封堵它,可一旦业务系统需要通过共享目录互通,你就得在“全部拒绝”和“放行指定来源”之间找到一条精确的路线。这个需求在H3C设备上实现,核心不是会不会敲命令,而是ACL规则顺序、接口方向、以及设备默认行为有没有想清楚。这篇文章就把完整思路和实测过程捋一遍,适合正在做网络加固的网络工程师、运维同学,也适合被安全检查折腾到需要快速出方案的朋友参考。
1. 需求拆解:445端口访问控制到底在控什么
1.1 为什么是445端口而不是其他端口
445端口承载的是SMB协议,Windows环境下文件共享、打印机共享、远程管理里很大一部分流量都会走这个端口。对大部分内部业务来说,这个端口确实是刚需,但对外部网络或非信任区域来说,暴露445端口就意味着把攻击面摊开给互联网,历史上多个影响范围很大的恶意程序,主要传播途径就是利用SMB相关漏洞在445端口上横移。
所以安全加固场景里,网络管理员接到的要求往往是“把全网445端口封掉”。但真实业务环境永远比安全策略复杂,总有一两台服务器、一两个固定IP的应用需要继续使用SMB共享。比如备份服务器要定期读写文件服务器的共享目录,或者业务系统之间需要通过SMB交换文件。这就是“拒绝所有IP访问445端口,但允许特定IP访问”这个需求最典型的生产背景。
单纯在每台Windows主机上配置防火墙也能做,但管理分散、策略不统一、主机被攻破后策容易被关闭。放到网络设备上统一管控,就成了更可靠的选择。H3C的交换机、路由器、防火墙都能承担这个任务,但不同型号、不同软件版本的实现方式有差异,配置前要先确认设备能力和当前软件版本上的命令风格。
1.2 控制点选在交换机、路由器还是防火墙
同样是H3C设备,传统交换机/路由器上通常用ACL(访问控制列表)配合包过滤功能来实现端口控制,而带安全业务处理能力的防火墙设备往往建议直接使用安全策略(Security Policy),两种方式都能达到目的,但管理逻辑不同。我整理了这份对比,可以帮你快速判断该用哪种方案:
| 控制方式 | 适用设备 | 控制粒度 | 管理便利度 | 说明 |
|---|---|---|---|---|
| ACL + packet-filter | 交换机、路由器、部分防火墙 | 五元组、端口 | 中,规则全靠手工维护 | 适合规则少、变更不频繁的场景 |
| 安全策略 | 防火墙(Comware V7及以后版本) | 源、目的、服务、时间段、用户等 | 高,规则可读性好 | 适合经常调整IP、存在复杂业务分组的场景 |
| 主机防火墙 | Windows/Linux服务器 | 进程、端口、远程地址 | 低,需要逐台配置 | 只适合最后一层兜底,不适合集中管控 |
我的习惯是,凡是设备支持安全策略,就优先用安全策略;老设备或者只有ACL能力的设备,才用ACL加包过滤的方案。这个需求难度不大,ACL方案更容易讲清楚原理,下面的配置示例也以ACL为例,最后再补充安全策略的替代写法。
1.3 把需求翻译成控制语义
“拒绝所有IP访问445端口,但允许特定IP访问”这句话写成人话是:对所有访问目的端口445的TCP流量,先检查来源IP,如果来源IP在白名单内就放行,其他来源一律丢弃。
需要注意的是这里有个隐含条件:“特定IP允许访问”。这个放行动作必须在“拒绝所有”之前完成判断,否则白名单IP也会被“所有”这个范围覆盖掉。很多配置失败都栽在这个地方,我见过最典型的错误就是先写了一条deny tcp any destination-port eq 445,后面再写permit tcp source 10.10.10.50 0 destination-port eq 445,这种做法从语义上就错了,因为ACL规则按顺序匹配,先命中deny规则后直接丢弃,后面的permit规则根本没有机会执行。
2. ACL规则设计的先后顺序:为什么permit必须放在前面
2.1 一个数据包在ACL里究竟经历了什么
ACL本质上是一份按顺序执行的规则表。数据包到达接口后,设备会解析出它的源IP、目的IP、源端口、目的端口和协议类型,然后把这份信息从ACL的第一条规则开始逐条比对。一旦某条规则匹配成功,设备就执行这条规则定义的动作(permit放行或deny丢弃),后面的规则不再参与判断。
这个机制和现实生活中“安检通道”很相似:进入通道时先查证件,如果第一个检查口就判定你合规并放行,就不会再把你带到后面的检查口核验一整套材料;反之,如果在第一个检查口就被判定不合规,你连走到下一个检查口的机会都没有。ACL的匹配逻辑就这么直接,规则顺序直接决定了白名单IP的命运。
在H3C的Comware系统里,ACL规则还受rule-id排序影响。默认情况下,设备按照“配置顺序”匹配规则,也就是rule-id数值小的规则排在前面,先被检查。所以配置两条规则时,必须让“允许特定IP访问445”的rule-id小于“拒绝所有IP访问445”的rule-id,顺序上就是permit在前、deny在后。
2.2 一个可以直接抄的配置示例
假设现在有一台备份服务器,源地址是10.10.10.50,需要访问文件服务器10.10.20.20的445端口,其他任何来源访问445都被拒绝。在H3C设备上,标准的配置流程是这样的:
# 进入系统视图 system-view # 创建高级ACL,规则号建议编成3999,方便识别 acl advanced 3999 description Deny_445_Allow_BackupServer # 第一条规则:放行10.10.10.50对445端口的访问 # 注意rule-id要小,必须排在前面 rule 5 permit tcp source 10.10.10.50 0 destination-port eq 445 # 第二条规则:拒绝所有来源对445端口的访问 rule 10 deny tcp destination-port eq 445 # 退出ACL quit配置完成后,把ACL应用到对应的接口上。比如这台设备的GigabitEthernet1/0/1连接着文件服务器所在的VLAN,流量进入该接口的方向是inbound,则:
interface GigabitEthernet1/0/1 packet-filter 3999 inbound quit save force这里的source 10.10.10.50 0中,后面的0是通配符通配掩码(wildcard mask),表示完全匹配这个IP地址,不接受任何掩码变化。destination-port eq 445匹配的目的端口是TCP的445。如果白名单IP有多个,就多写几条permit规则,但一定要保证所有permit规则的rule-id都排在deny规则前面。
2.3 rule-id和匹配顺序:这里的水比想象中深
ACL配置顺序这个点,容易出问题的地方在于手动指定rule-id。工龄长一点的网工可能习惯给规则分配特殊编号,比如给deny规则分配rule-id 5,给permit规则分配rule-id 10。从编号习惯上看没问题,但在这个场景里就彻底错了——deny的rule-id更小会排在前面,白名单IP照样被拒。
还有一部分H3C设备支持把ACL的匹配顺序改成深度优先模式(match-order auto),在这种模式下,规则排列不再严格按照rule-id顺序,而是按照规则的“具体程度”排序,匹配条件更多的规则排在前面。对于“允许特定IP访问445端口”和“拒绝所有IP访问445端口”这两条规则来说,permit规则多了一个source条件,深度更浅一点?其实不一定。为了避免混淆,我建议这个需求一律保持默认的“配置顺序”模式,并且把rule-id规划成5、10、15这样有间隔的方式,方便后期在中间插入新规则又不打乱现有顺序。
记住一句话:“先允许特定,再拒绝所有”是ACL配置的铁律。即使你后面写一百条permit规则,只要任何一条先命中的规则带了deny动作,白名单就是一张废纸。
3. 接口方向和应用位置:把ACL放到正确的地方
3.1 inbound还是outbound,判断思路一次讲清
ACL定义完成后,如果不绑定到接口上,只是一份躺在设备里的静态表格,不会对任何流量产生影响。绑定接口时最先遇到的就是方向问题:到底该用inbound还是outbound。
判断方法很简单:站在设备接口的角度看流量走向。数据包从某个方向进入设备,这个方向的入方向就是inbound;数据包从设备发往某个方向,这个方向的出方向就是outbound。拿前文的场景举例,备份服务器10.10.10.50要访问文件服务器10.10.20.20,如果中间设备是核心交换机,备份服务器接入在GigabitEthernet1/0/1,文件服务器在GigabitEthernet1/0/5,我们在1/0/1接口上做控制,那备份服务器的流量从这个接口进入设备,应该绑定inbound方向;如果在1/0/5接口上做控制,那流量从设备出去到达文件服务器,应该绑定outbound方向。
有一种常见做法是在连接服务器的接口上配置ACL inbound,把所有来源的445流量挡在服务器之前。这样做的好处是无论中间经过多少跳、源地址有没有被NAT,只要流量最终进入服务器所在接口,都会被检查到,逻辑最直观,也最容易被后续排错的人理解。
3.2 不同设备形态下的应用方式
在三层交换机和路由器上,ACL包过滤可以绑定在物理接口或三层VLAN接口上。下面是一个物理接口绑定的完整示例:
interface GigabitEthernet1/0/5 description Link_to_File_Server packet-filter 3999 inbound quit save force如果你的控制对象是VLAN间的互访流量,比如VLAN 10访问VLAN 20,在三层交换机上ACL需要绑定在VLAN虚接口(interface Vlan-interface)上,因为VLAN间的路由发生在三层接口上,绑定在物理二层接口上对VLAN间流量不生效,这是一个很容易被忽略的细节。
H3C的防火墙设备如果使用Comware V7及以后的系统,更推荐的安全做法是在security-policy里配置策略规则,而不是沿用ACL绑定接口的老办法。安全策略的规则同样按顺序匹配,逻辑和ACL一致,但可读性和后续可维护性明显更强。用安全策略来表达这个需求,示意图大致如下:
security-policy ip rule name permit_backup_smb source-address 10.10.10.50 32 destination-address 10.10.20.20 32 service tcp destination-port 445 action pass rule name deny_all_smb destination-address any service tcp destination-port 445 action drop注意安全策略规则也是从上往下匹配,permit规则要放在deny规则前面,这个思路和ACL完全一致。防火墙设备上两种方式都能实现,但建议优先走安全策略,因为后面扩展IP组、服务组、时间段会方便很多。
3.3 NAT场景下的源地址判断
如果设备同时承担NAT(地址转换)任务,源IP的判断就会多一个陷阱。ACL中写source 10.10.10.50时,指的是设备在做ACL匹配时看到的报文源地址。如果白名单IP出现在NAT转换之前,源地址还是内网真实IP,ACL写内网IP就行;但如果流量已经过了一次NAT,设备在接口上看到的是转换后的公网地址,你还写内网IP就会发现规则永远匹配不上。
遇到NAT和ACL同时存在的场景,先花两分钟画一条数据路径:从白名单IP出发,经过哪些设备、在哪个接口进、在哪个接口出、NAT在哪个位置发生。只要把这条路径画清楚,inbound还是outbound、源IP写什么,答案就都出来了。经验之谈:不要把ACL绑定在NAT后的接口上还使用NAT前的源IP,这种错误排错时非常隐蔽,乍一看配置正确,实际规则却从未命中。
4. 验证与排错:配置完成后哪些检查不能省
4.1 三条display命令快速确认状态
配置保存之后,第一件事不是急着拿真实业务测试,而是先看配置是否完整生效。在H3C设备上,三条命令足够完成初步确认:
# 查看ACL规则内容、规则命中计数 display acl 3999 # 查看接口上的包过滤绑定情况 display packet-filter interface # 查看设备日志,确认是否有deny日志产生 display logbufferdisplay acl 3999输出里,每条规则后面会有一个Global Count或者类似的命中次数统计。如果配置完成且已经产生测试流量,permit规则和deny规则都会有对应计数增长。如果规则计数全是0,说明流量根本没经过这条ACL,要么绑定接口错了,要么方向反了,要么流量走了别的路径。
display packet-filter interface的输出则直观地告诉你,哪个接口绑了哪个ACL,方向是inbound还是outbound。很多配置错误在这一步就能看出来——不是ACL本身写错了,而是根本没有绑到正确的接口上。
4.2 用真实流量做黑白名单双向验证
配置类的验证不能只看配置文件“存在”,必须用流量证明规则生效。实际操作时,我一般准备两台测试机,一台使用白名单IP,另一台使用普通IP,分别对目标服务器的445端口做连通性测试。
测试工具可以用系统自带命令。Windows上可以用powershell Test-NetConnection 10.10.20.20 -Port 445,Linux上可以用nc或bash的内置能力:
# 用nc测试端口连通性,如果输出open表示445端口可达 nc -vz -w 3 10.10.20.20 445 # bash内置方式:3秒超时测试TCP端口 timeout 3 bash -c "echo > /dev/tcp/10.10.20.20/445" && echo "open" || echo "closed"从白名单IP测试,应该得到open;从普通IP测试,应该得到closed或超时。如果两侧测试结果不一致,对照下表的排查方向逐个检查:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 白名单IP也不通 | permit规则被deny规则盖住;IP掩码写错;ACL绑定方向错误 | 检查rule-id顺序;确认source通配掩码;用display acl查看命中计数 |
| 普通IP也能通 | ACL没有覆盖这条路径;deny规则没有生效;流量被NAT绕过 | 检查接口绑定;确认为什么流量没进这条链路;检查是否有其他放行策略在前面 |
| 两个方向都不通 | ACL没绑定到接口;规则动作和预期相反 | 检查packet-filter方向;确认没有多个接口串接导致流量走了备用链路 |
| 管理地址也不通 | ACL把设备管理流量也拦了 | 检查是否在管理VLAN接口也绑定了ACL;检查管理源IP是否被deny规则覆盖 |
这个双向测试是检验ACL配置是否真正满足“拒绝所有IP访问445端口,但允许特定IP访问”最有力的证据,宁可多花十分钟,也不要直接上了生产才发现规则无效。
4.3 我亲眼见过的几个“配置正确但功能无效”的案例
有一个比较常见的案例是关于通配掩码的。需求方给出的白名单是192.168.10.0/24网段,配置人员在ACL里写成了source 192.168.10.0 255.255.255.0。这在H3C设备上是非法的匹配方式——ACL里的source掩码是通配符掩码,0.0.0.255才表示最后8位任意,直接写255.255.255.0这种子网掩码格式会导致匹配范围完全错乱。正确写法应该是source 192.168.10.0 0.0.0.255。
另一个案例是在交换机上把ACL同时绑定在了上行口和下行口。客户端流量进来时先被上行口的deny规则拦了,而下行口上明明还有一条permit规则在等着放行,但已经轮不到它执行了。这提醒我们,整个转发路径上只需要在一个关键点做一次控制,不要贪多,多个接口绑定同一份ACL反而容易造成“前面拦了后面放不放都无所谓”的局面。
还有个容易被忽略的情况是:某些业务服务器除了监听445,还会动态协商高端口或依赖139端口。只封掉445并不能覆盖完整风险面,如果安全要求是彻底限制SMB访问,139和动态端口也要纳入考虑范围。当然,如果需求严格限定为“仅445”,那就按需求来,但测试时不要拿一个依赖高端口或139的客户端来验证“全堵住了”,否则得出的结论会有偏差。
5. 变体场景:从“单IP白名单”到更复杂的业务化策略
5.1 多个白名单IP和整个网段放行的写法
现实中“特定IP”往往不止一台。比如文件服务器需要让运维网段和备份服务器都能访问,这时可以把ACL写成这样:
acl advanced 3999 rule 5 permit tcp source 10.10.10.50 0 destination-port eq 445 rule 10 permit tcp source 10.10.30.0 0.0.0.255 destination-port eq 445 rule 15 deny tcp destination-port eq 445注意10.10.30.0 0.0.0.255这种写法,前一段是网段地址,后一段是通配符掩码,两个0和255的组合表示匹配10.10.30.0到10.10.30.255整个C段。凡是允许规则,都要放在deny规则之前。如果白名单经常变动,用安全策略加地址组会更省心,直接在地址组里增删IP,规则本身不用动。
5.2 只限制访问指定服务器的445端口
有时需求不是“全网所有445都拒绝”,而是“只有某台服务器A的445要拒绝所有外来访问,但服务器B的445大家还能用”。这种情况下ACL要把目的地址也限定进去:
rule 5 permit tcp source 10.10.10.50 0 destination 10.10.20.20 0 destination-port eq 445 rule 10 deny tcp destination 10.10.20.20 0 destination-port eq 445注意加了destination参数后,ACL只会针对发往10.10.20.20的445流量做检查,其他目的地址的445流量不受影响。这个写法比全局deny更精准,也更容易被业务部门接受。
5.3 按时间段生效怎么实现
如果业务系统的SMB访问只在固定时间发生,可以用时间段对象让ACL只在指定时间生效。Comware系统里时间段配置大致是:
# 定义名为work的时间段,工作日9点到18点有效 time-range work 09:00 to 18:00 working-day acl advanced 3999 rule 5 permit tcp source 10.10.10.50 0 destination-port eq 445 time-range work rule 10 deny tcp destination-port eq 445加上time-range参数之后,permit规则只在工作日9点到18点之间生效,其他时间走后面的deny规则全部拒绝。这种按时间开放的做法在运维窗口、非办公时间安全收紧的场景里很实用,但要注意设备时间同步必须准确,否则时间段判断会出偏差。
5.4 安全策略的受众:以后要频繁变IP就用这个
如果这个需求会长期存在,而且白名单IP一个月改好几次,我发现最合适的方案不是ACL,而是防火墙上的安全策略加地址组。地址组里维护IP,安全策略里只引用地址组名称,以后增加IP只需要在地址组里加一条,不需要动规则顺序,也不存在rule-id排序的坑。
安全策略本质上也是从上到下匹配,但是每条策略可以定义多个源地址、多个目的地址、多个服务。前面也提到,配置时保持permit策略在前、deny策略在后即可。如果公司后续有“只允许某个部门IP段访问”“只允许指定VLAN访问”这类需求,安全策略的表达力远比ACL强,迁移成本和排错成本都要低得多。
6. 部署前必做的检查与我的踩坑复盘
6.1 把管理面先兜住,别把自己关在门外
ACL应用到接口上时,如果有人把管理员的网段也放进了“拒绝所有445”的deny范围,那影响其实并不直接——因为设备管理一般走SSH的22端口,不会受445规则影响。但有一种情况确实会波及:如果管理PC需要通过SMB映射网络驱动器来上传配置文件、刷设备版本,或者设备日志采集依赖共享目录,那么管理源IP同样会被这条deny规则拦住。
更稳妥的做法是把网管网段的IP也加进permit规则,或者在ACL里额外写一条允许管理网段访问设备的规则。配置顺序上,管理网段的permit规则同样要放在deny所有445的前面。别等设备日志中心连续掉线三天,才想起来是加固策略误伤了管理流量。
6.2 回退方案要在变更前准备好,而不是出问题时再想
任何ACL变更都意味着可能影响现网流量。我的习惯是:变更前先执行一遍display cu | include acl|packet-filter,把当前ACL和接口绑定情况留底;准备好反向命令,也就是undo packet-filter interface GigabitEthernet1/0/5 inbound或者undo acl advanced 3999这样的回退命令。
在正式环境做变更前,先找一台非核心接口的设备测试。你千万别小看这一步,ACL规则在你脑子里的顺序和实际上机后的行为之间,隔着版本差异和匹配模式差异,只在文档里推演是永远不够的。真实环境验证通过后,再快速应用到所有目标接口,而且尽量选择业务低峰时段操作。
6.3 给ACL写描述,给deny规则加日志
配置完成后,给整条ACL加一个明确描述,内容写上需求编号或业务背景,比如description Deny_445_Allow_BackupServer。这样做的好处是三个月后有人来检查,甚至是你自己回来看,都能一眼判断这条ACL的用途,而不是对着一堆数字猜半天。在deny规则上加上logging或类似的关键字(不同版本支持程度略有差异),可以让被拒绝的流量在设备日志里留下痕迹。安全加固不仅要“做”,还要“可审计”,日志记录就是审计的依据。
6.4 我个人的部署习惯:先验证再收尾
这类端口控制需求我在不同设备上做过很多次,沉淀下来的习惯很简单:先写permit,再写deny;先绑接口,再测双向;先看命中计数,再看日志;最后再来一轮完整的黑白名单连通性测试。这套流程看起来朴素,但能挡住绝大多数因为顺序错误、方向错误、掩码错误引发的故障。
有一次我在一台较老的交换机上配置同样的需求,ACL规则、接口绑定都检查了好几遍,但普通IP还是能访问445端口。最后查出来,是接文件服务器的端口上存在两条物理链路,一条走核心交换机,一条走一个旁路设备,流量自动走了没绑ACL的路径,ACL再正确也拦不到它。所以做端口加固时,脑子里一定要有整个网络拓扑的完整概念,确认所有可能到达目标服务器的流量入口都被检查到,而不是只盯着一个接口。
说了这么多,其实每条经验都是从实际项目里磨出来的。ACL本身不复杂,麻烦的是它对你的网络理解提出了要求:规则顺序要清楚、流量方向要清楚、设备角色要清楚。把这三件事想明白了,“拒绝所有IP访问445端口,但允许特定IP访问”就只是一份五分钟能写完的配置而已。