3. 网络层安全加固
Redis 默认监听所有网络接口(0.0.0.0),且早期版本默认无认证。一旦端口 6379 暴露到公网,攻击者可直接写入 SSH 公钥、计划任务或主从复制恶意载荷,实现远程命令执行。网络层加固的目标不是"加一层密码",而是把 Redis 的可达范围从"任何能路由到它的主机"收缩到"仅业务进程所在的可信主机与端口"。本节围绕四个控制点展开:bind 决定监听哪些地址,protected-mode 决定无认证时的兜底拒绝,防火墙决定谁能到达该端口,TLS 决定链路上的数据是否可被窃听或篡改。
一、bind:把监听地址收敛到可信网卡
bind 指令控制 Redis 在哪些本地地址上接受连接。它不是白名单——写 bind 10.0.1.5 表示只在该网卡上监听,其他网卡(包括 127.0.0.1 之外的公网网卡)根本不建立监听套接字,连接请求在 TCP 层就被拒绝。这是最彻底的一层收敛。
常见配置形态与含义:
bind 127.0.0.1 -::1:仅本机可访问,适合单机应用与本地运维。bind 127.0.0.1 10.0.1.5:本机 + 内网业务网卡,应用服务器通过 10.0.1.5 访问,公网网卡不监听。bind 0.0.0.0:监听全部 IPv4 地址,仅在容器或严格受控网络中使用,且必须配合防火墙与认证。
需要注意两点。第一,Redis 6 之前 bind 后若写多个地址,任一地址不可用会导致启动失败;Redis 6+ 改为"尽力绑定",不可用的地址会跳过并记录日志,因此启动后必须核对实际监听结果。第二,修改 bind 后应通过 ss -lntp | grep 6379 或 redis-cli -h <ip> -p 6379 ping 验证:期望的地址返回 PONG,非期望地址应连接超时或被拒绝。
二、protected-mode:无认证时的兜底闸门
protected-mode yes(3.2 起默认开启)的判定逻辑是:当没有配置密码且没有显式 bind 到具体地址(即监听 0.0.0.0 或未配置 bind)时,Redis 只接受来自回环地址的连接,其他来源一律返回错误并拒绝执行命令。它是一道"配置疏忽保护",而不是访问控制手段。
因此存在一个常见误区:以为开了 protected-mode 就安全了。只要同时设置了 requirepass,protected-mode 就不再拦截外部连接——此时安全性完全依赖密码强度与网络边界。正确做法是:bind 收敛 + protected-mode 保持 yes + 认证三者叠加,而不是互相替代。若确需在容器内监听 0.0.0.0,应显式设置 protected-mode no 并同时用防火墙限制来源,且清楚这是有意为之的取舍。
三、防火墙:在主机与网络边界双重收口
bind 解决"本机监听哪些地址",防火墙解决"哪些远端主机能到达这些地址"。两者是不同层次,缺一不可。典型做法是主机防火墙(iptables/nftables/firewalld)只放行应用服务器网段,网络 ACL/安全组再限制一次。
# 仅允许 10.0.1.0/24 访问 6379,其余丢弃
iptables -A INPUT -p tcp --dport 6379 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 6379 -j DROP
# firewalld 等价写法
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" port port="6379" protocol="tcp" accept'
firewall-cmd --reload
验证时不要只看规则是否存在,要实际从允许主机和禁止主机各发起一次连接:允许侧应能完成 PING,禁止侧应表现为超时(DROP)或拒绝(REJECT)。同时检查是否误放行了 0.0.0.0/0,以及云安全组与主机防火墙是否一致——只改一处是排障中最常见的"以为封了其实没封"。
四、TLS:让链路本身不可读、不可改
当 Redis 跨不可信网络(跨可用区、跨机房、混合云)通信时,仅靠 bind 和防火墙无法防止链路上的嗅探与中间人。Redis 6 起原生支持 TLS,需要准备 CA、服务端证书/私钥、客户端证书,并在配置中启用:
tls-port 6379
port 0 # 关闭明文端口
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients yes # 要求客户端证书(双向认证)
tls-protocols "TLSv1.2 TLSv1.3"
客户端连接需带 TLS 参数:redis-cli --tls --cacert ca.crt -h redis.internal -p 6379 ping。若使用主从复制,replicaof 与 tls-replication yes 需一并配置,否则复制链路仍走明文。验证要点:明文端口应无法连接;不带客户端证书的连接应被拒绝;openssl s_client -connect redis.internal:6379 -CAfile ca.crt 能完成握手并显示证书链。
五、组合验证与配置基线
四个控制点应按"由内到外"的顺序验证:先确认监听地址正确,再确认无认证兜底生效,再确认远端可达性符合预期,最后确认链路加密与证书校验。下面给出一份可直接对照的检查表(示例参数,需按实际网段替换)。
| 控制点 | 配置示例 | 验证命令 | 通过判据 |
|---|---|---|---|
| bind | bind 127.0.0.1 10.0.1.5 | ss -lntp | grep 6379 | 仅出现 127.0.0.1 与 10.0.1.5 |
| protected-mode | protected-mode yes | 无密码时从外部连接 | 返回 DENIED 提示 |
| 防火墙 | 仅放行 10.0.1.0/24 | 从允许/禁止主机各连一次 | 允许侧 PONG,禁止侧超时 |
| TLS | tls-port 6379, port 0 | redis-cli --tls --cacert ... | 握手成功且明文端口不可连 |
最后强调一个工程习惯:把上述配置写入版本化的配置文件模板,并在变更后保留 CONFIG GET bind、CONFIG GET protected-mode、CONFIG GET tls-port 的输出作为证据。网络层加固的价值不在于"配了",而在于"能证明只有预期的主机能以预期的方式访问"。