比特币节点不会连你的端口:坏端口黑名单回避了什么 图 1
比特币节点不会连你的端口:坏端口黑名单回避了什么 · 图 1

把 bitcoind 配好端口转发后,有人的节点还是收不到什么主动入站连接;也有人只是跑了一会儿节点,日志里看不出异常,问题却始终在连接数上。有一个容易漏查的角落:比特币核心在自动挑选外连对端时会主动绕开一份”坏端口”清单,这份清单写在源码树 doc/p2p-bad-ports.md,而它的另一面是——挂在清单端口上的节点,也很难被别的节点主动连上。

清单从哪来、管什么

源码里挑对端的逻辑在 src/net.cpp:每次从地址库抽候选时,只要 IPv4 或 IPv6 地址的端口命中 IsBadPort,这个候选就被跳过——除非此前已经试了 50 个地址都不合格,才放弃这条纪律。src/netbase.cppIsBadPort 实现里那句注释写着”改这张表时记得同步 doc/p2p-bad-ports.md”,两份内容是同一条纪律的镜像。

文档解释这张表的动机:节点的外连目标来自 P2P 网络中继的未核实数据,恶意或被污染的条目可能把节点引向根本不该公开访问的服务端口——文档举例 22(ssh):对一个只做身份认证的服务发起来自”比特币节点”的连接,可能被偏执的管理员视为可疑动作。反过来,连向通常公开且不需认证的服务(文档举 80/http)几乎不会被当成攻击。清单里从 1(tcpmux)、7(echo)、22(ssh)、23(telnet)一路列到 5432(PostgreSQL)、5900(VNC)、6667 系(IRC)、27017(MongoDB)等几十个端口,覆盖的主要是管理、数据库、远程桌面与消息服务。文档末尾还注明了这份名单与浏览器(Chromium、Mozilla)端口屏蔽机制的参照关系。

比特币节点不会连你的端口:坏端口黑名单回避了什么 图 2
比特币节点不会连你的端口:坏端口黑名单回避了什么 · 图 2

对你自己的节点意味着什么

第一层影响是入站饥饿:节点把自己监听在哪个端口广播给全网,其他节点抽对端时若看到这个端口在坏端口表上,就会跳过它。也就是说,把 -port-bind 改到清单内的端口,即便公网路由和防火墙全对,主动入站也会接近零。v31.0 的 src/init.cpp 对此有直接兜底:用 -bind-port 绑到坏端口上时,启动日志会打出 BadPortWarning 警告,等于运行时直接告诉你”你选了一个会被全网回避的端口”。

第二层是几个不踩雷的常识。默认主网 P2P 端口 8333 不在清单上,测试网、signet 的对应端口同样安全,默认部署不存在这个问题;清单管的是比特币节点自动外连时的目标选择,与你手工发起的连接无关——-connect= 指定对端不走这条抽卡逻辑,运维里用 -connect 连自家非标准端口的节点不受影响;清单也不限制你把钱包或 RPC 放哪个端口,RPC 端口与这份表完全无关。

排查场景怎么落地

场景一:入站数为零。先 getnetworkinfo 看本地声明的服务端口,若命中清单端口,改回 8333 系标准端口是根治方案;不是端口问题再查监听可达性那套常规流程。场景二:服务器日志里出现”某比特币节点客户端”连过你的 22 端口。大概率是对方节点抽卡抽到了你的地址——因为坏端口回避使这条路径本就罕见,真发生的常见原因是该端口曾注册过比特币节点、或对方版本较旧。你的防火墙记录解决不了比特币网络的中继缓存,能控制的是自己端口暴露面。场景三:想把节点放在 8333 之外的自定义端口。避开清单即可,文档本身就是一份现成的避雷名单;同时注意 0 到 1023 的系统端口在任何网络里都更难被放行。

一个常见误解:清单不是安全功能

需要划清边界:坏端口表保护的不是你的节点,而是网络里的第三方。它的目的是让节点不会因为地址库被污染而跑去敲别人家的 ssh 或数据库端口,给整个协议招黑。它不给你提供任何访问控制,也不意味着连出到清单外端口就一定安全——清单外端口上跑着未公开服务的情况依然存在,只是协议选择不在应用层重复维护一份全球端口用途普查。把节点连接质量当安全信号是危险的误读:入站少只说明可达性或端口选择有毛病,出站列表干净也不说明任何一笔中继交易可信。网络层隐私与安全的正确工具是入站连接限制、身份隔离(例如 Tor 或 I2P)与最小暴露面,而不是改端口碰运气。

风险提示:本文为网络机制说明,涉及防火墙与端口配置的改动请先在测试环境验证;本文不构成投资建议。