在这里插入图片描述

前言

上篇文章我们聊了零信任网络的基本概念,提到了零信任的四大核心能力。

今天重点聊聊其中一个最关键的能力:SPA(Single Packet Authorization,单包授权),它是零信任实现"网络隐身"的核心技术。


一、传统服务器的"门户大开"问题

在说SPA之前,先看看传统服务器是怎么暴露在互联网上的。

传统VPN/服务器的端口状态

当你部署一台VPN服务器或者任何需要远程访问的服务时,标准流程是这样的:

# 开放SSH端口
sudo ufw allow 22/tcp

# 开放VPN端口
sudo ufw allow 1194/udp

结果是什么?

端口22和1194在公网上是"开放"的

任何人都可以用扫描器(比如nmap)扫到这个端口:

$ nmap -sS -p 22,1194 target.server.com

Starting Nmap 7.94
Nmap scan report for target.server.com
PORT     STATE    SERVICE
22/tcp   open     ssh
1194/udp open     openvpn

对攻击者来说,这是一个明确的攻击入口。

他可以:

  • 对22端口进行暴力破解
  • 寻找SSH服务的漏洞
  • 使用msfconsole尝试各种exploit

这就是典型的"靶子站在那儿等子弹"。

为什么端口必须开放?

这不是VPN/SSH的错,而是TCP/IP协议的设计:

TCP三次握手:
1. 客户端发送SYN包(我想连接)
2. 服务器响应SYN-ACK包(好的,请)
3. 客户端发送ACK包(确认)

在第2步服务器响应SYN-ACK之前,服务器必须有一个端口在监听。这个端口对外部世界是可见的。

你必须先"开门",才能验证来访者是谁。


二、SPA是怎么工作的?

SPA的核心思想

SPA的中文是"单包授权"。

顾名思义:只需要一个数据包,就能完成身份验证和授权。

但更准确的理解是:在TCP三次握手之前完成身份验证。

SPA vs 传统端口敲门(Port Knocking)

很多人容易把SPA和早期的"端口敲门"技术混淆,实际上两者有本质区别:

对比项 传统端口敲门 SPA(单包授权)
原理 按顺序请求一系列端口(7001→8002→9003) 一个加密签名的UDP包
安全性 基于端口序列,容易被嗅探/重放 HMAC签名,不可伪造
抗干扰 网络乱序、丢包会导致失败 单包无状态,不受乱序影响
速度 多个端口依次敲门,速度慢 一次验证,即开即用
本质 还是"敲门",只是更隐蔽 真正的身份认证

简单说:端口敲门是"摩斯密码式的暗语",SPA是"加密的身份证"。

SPA的工作流程

传统VPN的流程:

1. 端口开放(公网可见)
2. TCP连接建立
3. 用户认证
4. 授权访问

SPA的流程:

1. 单包敲门(携带身份信息)
2. 服务端验证身份
3. 验证通过后,端口才开放
4. TCP连接建立
5. 访问资源

用"黑话"来说

SPA实现了**“先验证,后连接”**。

在SPA模式下,服务器在验证通过之前:

  • 端口对外部不可见
  • nmap扫描返回"filtered"或"closed"
  • 连TCP SYN包都不会响应

攻击者扫到的不是一个"打开的门",而是一个"黑洞"。


三、SPA的技术原理

核心机制:先监听,后开门

SPA的核心思想是**“端口平时不存在,需要时再创建”**。

实现原理:

  • SPA服务端进程(如fwknopd)不监听任何Socket端口
  • 而是通过底层抓包技术(如libpcap)监听网卡上的所有UDP数据包
  • 一旦验证通过,立刻通过动态修改防火墙规则(如iptables/nftables)为客户端源IP开启短暂放行窗口(通常30秒)
  • 验证失败或超时后,规则自动失效,端口恢复"隐身"状态

这就是为什么验证前nmap扫到的是"filtered"(黑洞),验证后端口瞬间变成"open"。

为什么SPA用UDP?

SPA通常基于UDP协议实现,原因在于:

  • TCP是面向连接的:发送TCP包必然触发三次握手,会在服务器留下半开连接(Half-open connection)
  • UDP是无状态的:发送完即焚,不会在服务器留下任何连接痕迹
  • 服务器对未验证的UDP请求完全不响应,实现真正的"黑洞"效果

单包的结构

一个SPA包通常包含:

字段 说明
客户端版本 协议版本号
时间戳 防止过期包攻击(时间窗口内有效)
随机数 Nonce/UUID,防止完全一致的包重放
认证字段 HMAC签名(完整性保护,防篡改)
访问令牌 可选,包含目标端口、访问权限等信息

认证过程

客户端                              服务端
   |                                   |
   |  1. 生成SPA包(包含身份信息)      |
   |  2. 用共享密钥或公钥签名          |
   |---------------------------------->|
   |                                   |  3. libpcap抓包,解析SPA包
   |                                   |  4. 验证HMAC签名
   |                                   |  5. 检查时间戳(5分钟内)
   |                                   |  6. 检查随机数(防重放)
   |                                   |  7. 验证通过
   |                                   |
   |         [fwknopd动态写入iptables] |
   |         [为源IP开放临时放行窗口]   |
   |<==================================>|
   |         正常TCP连接建立            |

防重放攻击

SPA包里包含时间戳和随机数。

服务端会:

  1. 检查时间戳是否在合理范围内(比如5分钟内)
  2. 记录已使用的随机数,拒绝重复使用

这防止了攻击者"录音重放"式的攻击。


四、SPA的"网络隐身"效果

对比测试

我们来做个对比测试:

测试一:传统SSH服务器(端口开放)

$ nmap -sS -p 22 target.server.com
PORT   STATE    SERVICE
22/tcp open     ssh

测试二:启用SPA的服务器(端口隐藏)

$ nmap -sS -p 22 target.server.com
PORT   STATE    SERVICE
22/tcp filtered ssh

注意state从open变成了filtered

filtered vs closed 的本质区别

  • closed:服务器返回了RST包,端口确实开放但拒绝了连接
  • filtered:服务器完全不响应,nmap无法判断端口状态
    • nmap发送了探针,但没收到任何回包
    • 这正是SPA要实现的"黑洞"效果

filtered意味着:服务器对请求完全不回应,攻击者甚至无法确定这是"墙"还是"没人"。

更进一步,如果攻击者使用UDP扫描,SPA服务器同样不会回复ICMP Port Unreachable报文。这种"极度安静"的特性才是SPA最迷人的地方——服务器对未授权请求完全"视而不见"。

攻击者的视角

对于使用SPA的服务:

  • 用nmap扫描:只能看到"filtered",不知道端口是否真的开放
  • 用masscan扫描:同样扫不到有效信息
  • 暴力破解:连门都找不到,怎么破?

攻击成功的关键是"先找到攻击面"。SPA把攻击面降到了零。


五、市面上常见的SPA实现

1. Protocol:WireGuard

WireGuard是一个现代VPN协议,它不是严格的SPA实现,但借鉴了类似的"密钥验证"思想:

# WireGuard的配置示例
[Peer]
PublicKey = <Server Public Key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.0.0.0/24

重要区分

  • WireGuard的端口(51820/udp)始终是开放的,nmap可以扫描到
  • 但没有对应私钥,攻击者无法建立连接
  • 这叫"连接隐身",而非SPA的"网络隐身"

如果想实现真正的端口隐藏(nmap扫不到),需要配合防火墙规则或专门的SPA工具。

2. Protocol:Cloudflare Access(基于边缘代理的零信任)

Cloudflare Access严格来说是Identity-Aware Proxy(IAP),运行在L7(应用层),而非L3/L4的SPA:

  • 用户访问时,先到Cloudflare边缘节点
  • 边缘节点拦截并验证身份(Cookie/Token)
  • 验证通过后,通过Cloudflare Tunnel转发到源站
  • 用户直接访问的是Cloudflare IP,而非源站真实IP

这也是一种"网络隐身"——源站IP完全被隐藏,但实现方式与SPA不同。

3. Protocol:Twingate

Twingate是一个商业零信任网络方案:

  • 使用类似SPA的连接机制
  • 客户端先与协调服务器建立隧道
  • 实际流量通过DST-NAT转发

4. 开源实现:fwknop

fwknop是一个实现了SPA的开源工具:

# 服务器端iptables规则(默认丢弃所有)
-A INPUT -m state --state ESTABLISHED -j ACCEPT
-A INPUT -j DROP

# 当收到有效的SPA包后,自动开放端口
# 开放时间窗口:30秒

六、SPA的局限性

SPA不是银弹,它有自己的局限性:

局限性一:客户端需要预配置

用户不能"即开即用",需要预先配置:

  • 共享密钥或证书
  • 客户端软件

这增加了部署复杂度。

局限性二:网络质量要求高

SPA包必须可靠传输。如果SPA包丢了,连接根本建立不起来。

局限性三:不能完全替代细粒度授权

SPA验证的是"你有没有权限敲门",但后续的细粒度身份认证(如你是哪个用户、你属于哪个组)和权限控制(你能访问哪些资源)还需要IAM等其他机制配合。

局限性四:不能防DDoS

攻击者可以发送大量SPA包让服务端资源耗尽。SPA解决的是"认证前暴露"的问题,但DDoS是另一层面的攻击。

局限性五:NAT环境下的源IP匹配问题

如果客户端处于复杂NAT环境下(例如公司内网出口IP会动态变化),SPA包中的源IP可能与后续TCP连接的源IP不一致,导致防火墙放行规则匹配失败。

解决方案:现代SPA工具通常会解析UDP报文头部的实际公网来源IP,并动态绑定该IP,从而确保即便在NAT后也能精准开放权限。虽然理论上也可以使用端口号作为放行依据,但为了安全性,通常优先推荐IP绑定方式——因为在多用户共用出口IP的环境下,仅靠端口号可能存在极小的"搭便车"风险。

局限性六:MTU和分片问题

如果SPA包包含了复杂的证书信息导致包过大(超过MTU),可能在传输路径中被分片或丢弃,导致验证失败。

解决方案:设计精简的SPA协议头,或确保SPA包小于典型MTU(1400字节)。


七、SPA + 零信任:完整的防护体系

SPA是零信任的重要一环。值得一提的是,SPA是SDP(Software Defined Perimeter,软件定义边界)架构的核心技术,SDP被称为"黑云(Black Cloud)“,其核心逻辑就是SPA实现的"先认证,后连接”。

但零信任还需要其他能力配合:

┌─────────────────────────────────────────┐
│              零信任防护体系              │
├─────────────────────────────────────────┤
│  SPA        →  网络隐身,攻击面归零     │
│  身份认证    →  确认"你是谁"            │
│  设备评估    →  确认"你的设备安全吗"    │
│  最小权限    →  确认"你只能访问需要的"  │
│  持续监控    →  监控异常行为            │
└─────────────────────────────────────────┘

八、实战:使用fwknop搭建SPA防护

环境

  • 服务器:Ubuntu 22.04
  • 客户端:macOS / Ubuntu

服务端安装配置

# 1. 安装fwknop
sudo apt update
sudo apt install fwknop-server

# 2. 生成密钥对
fwknop-keygen -a

# 输出类似:
# KEY_BASE64: abcdefghijklmnopqrstuvwxyz1234567890ABCDE=
# HMAC_KEY_BASE64: 1234567890abcdefghijklmnopqrstuvwxyzABCD=

# 3. 配置/etc/fwknop/access.conf
SOURCE: ANY
REQUIRE_USERNAME: username
KEY: abcdefghijklmnopqrstuvwxyz1234567890ABCDE=
HMAC_KEY: 1234567890abcdefghijklmnopqrstuvwxyzABCD=

# 4. 启动服务
sudo systemctl start fwknopd
sudo systemctl enable fwknopd

客户端配置

# 1. 安装客户端
sudo apt install fwknop-client

# 2. 配置~/.fwknoprc
[default]
ACCESS_PORT                    = 62201
SPA_SERVER                     = your.server.com
KEY_BASE64                     = abcdefghijklmnopqrstuvwxyz1234567890ABCDE=
HMAC_KEY_BASE64                = 1234567890abcdefghijklmnopqrstuvwxyzABCD=

# 3. 访问服务器
fwknop -n your.server.com -s

效果验证

# 在访问之前,端口是隐藏的
$ nmap -sS -p 62201 your.server.com
PORT      STATE    SERVICE
62201/tcp filtered

# 执行SPA敲门后
$ fwknop -n your.server.com -s
$ nmap -sS -p 62201 your.server.com
PORT      STATE    SERVICE
62201/tcp open

总结

SPA(单包授权)是零信任网络实现"网络隐身"的核心技术。

它的核心价值:

  1. 缩小攻击面:端口在验证通过前对外部不可见
  2. 防扫描:nmap等工具扫不到有效信息
  3. 防暴力破解:攻击者连门都找不到

金句:SPA让服务器从"防御姿态"转变为"隐身状态"——你无法攻击一个你根本看不见的目标。

但SPA只是零信任的一环。完整的零信任还需要:

  • 强身份认证
  • 设备安全评估
  • 最小权限控制
  • 持续行为监控

下篇文章,我们聊聊零信任的完整架构设计:IAM + 微隔离 + SPA 如何协同工作。


如果觉得有帮助,欢迎点赞、收藏!你们公司有没有使用SPA技术?评论区聊聊。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐