ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

安全网关与openresty

安全网关与openresty 网关-相关概念时常能听到邮件网关、API网关、和AP他们和路由器的网关有何区别本文带你了解网关为何物、网关的从何而来以及网关使按什么分类的这几类网关有何不同一、网关的基本概念与类别网关在不同语境下指的东按西天差地别按工作协议层次分网关至少有三类基底形态类型工作层次核心职能典型实现传输网关网络层/传输层数据转发、基础协议转换默认网关路由器、L4 负载均衡、NAT应用网关应用层深度协议解析、语义翻译、服务路由Nginx、API 网关、邮件网关安全网关跨网络层—应用层访问控制、认证、入侵防御、内容过滤下一代防火墙、WAF、SDP 网关再按场景切还有支付网关、IoT 网关、存储网关、信令网关……名字都叫网关解决的问题却几乎不重叠。AP是安全网关且是其中身份认证 访问控制这一子类。不过要说清楚的是AP 是个跨类产品——它的外形是应用网关内核是安全网关。三层身份叠在一起看才完整维度AP 的归属说明工作形态应用网关跑在 HTTP/HTTPS 七层做深度协议解析、路由、Header 注入职能内核安全网关访问控制、身份认证、设备状态校验、审计——正是安全网关的定义项架构角色PEP策略执行点按 NIST SP 800-207决策外包给 PDP自己只负责执行二、本质区别 管“通不通” vs 管“该不该”广义网关默认任务是联通与切换-把流量从A送到B顺带做协议翻译、负载均衡、缓存限流它关心是包怎么走。AP默认任务是裁决-在放行之前先回答“你是谁你的设备健康吗你凭什么访问这个应用”它关心的是身份。有个很能说明问题的对照某类传统链路网关做全流量加密时网关只能看到链路层的 IP 和端口信息无法感知具体业务身份 。这类网关把流量保护得很好却完全不知道访问者是谁——而 AP 恰恰相反身份就是它的全部输入。三、架构上最关键的差异AP不是“一个设备”而是半个组件这是很多人理解错位的地方。按 NIST SP 800-207 的零信任逻辑模型访问决策和执行是分离的 PDP策略决策点 策略引擎 PE 策略管理器 PA负责判PEP策略执行点 负责拦位于主体和资源之间AP 就是 PEP 的一种实现。NIST 明确说 PEP 可以多种形态落地——云网关、反向代理、服务网格 sidecar、主机 agent、传统 appliance 都行。区别在于普通网关决策和执行都在自己身上配置即策略Nginx 的 conf、防火墙的 ACL。AP自己只做执行决策外包给背后的 PDPIdP 设备清单 信任推断 访问控制引擎。控制面和数据面分离AP 通过控制通道接收指令业务流量走数据面。所以 AP 从来不是单兵作战它是一套体系里的门卫背后必须有 IdP、设备信任库、策略引擎在喂信号。这也是为什么买一个 AP 产品不等于实现了零信任。四、还有三个实操层面的差异1. 暴露 vs 隐身普通网关是发布型——把后端服务暴露出去让外面能访问。AP 是隐身型——后端默认不可达DNS 的 CNAME 指向 APAP 是全公司内外网访问企业应用的唯一入口绕过它就没路。2. 信任模型普通网关工作在传统边界模型进来了就信。AP 是零信任每次请求独立评估身份 设备状态 上下文会话中途设备掉补丁也能被踢掉。3. 覆盖范围有限这点是 AP 的短板得说清楚BeyondCorp 原教旨形态的 AP 本质是Web 代理型主要保护浏览器访问的应用对 C/S 架构的原生客户端支持弱。而 SDP 网关走的是另一条路子——用单包授权SPA让服务端口对未授权者完全不响应实现网络层隐身 。所以零信任安全网关这个货架上AP 和 SDP 网关是两种不同机制的产品。五、怎么判断你需要的是哪种要连通性、性能、路由、协议转换​ → 传输/应用网关Nginx、负载均衡、路由器要API 治理鉴权、限流、计费、开发者门户→ API 网关不是 AP要替代 VPN、保护内部后台Grafana/Jenkins/管理台、按身份授权、拿身份级审计​ → AP / ZTNA 类要隐藏暴露面、防扫描探测、保护非 Web 的 C/S 老系统​ → SDP 网关要等保/合规要求的身份级审计与设备合规校验​ → 必须 AP 类普通网关补不上一句话收尾网关是个家族姓AP 是其中的一个学名而且是个只在零信任语境下才有意义的学名。离开 IdP、设备信任、策略引擎谈 AP它就退化成一个带了登录页的反向代理。开源openRestyOpenResty 官方对自己的定义很克制a full-fledged web platform that integrates our enhanced version of the Nginx core, our enhanced version of LuaJIT, many carefully written Lua libraries, and lots of high-quality 3rd-party Nginx modules​ —— 而且特别强调了一句OpenResty is not an Nginx fork. It is a higher-level application and gateway platform using Nginx as a component.这一句就定了性Nginx 在 OpenResty 里是被使用的组件不是被修改的分叉。一、四层组件栈层组件职责宿主​Nginx 核心事件驱动epoll/kqueue、连接管理、master-worker 进程模型、HTTP/TCP 协议栈引擎​LuaJITJIT 即时编译性能接近 C提供协程与FFI直接调 C 函数绕过 Lua C API 栈开销桥梁​ngx_lua / stream_lua把 LuaJIT 虚拟机嵌入 worker 进程劫持 Nginx 各处理阶段开出 Lua 挂载点库​lua-resty-*非阻塞客户端与工具lua-resty-core、lua-cjson、lua-resty-redis / mysql / http、lua-resty-limit-traffic、lua-resty-jwt、lua-resty-lrucache、lua-resty-lock 等配套还有ngx.shared.DICT共享内存跨 worker 共享数据、resty命令行、opm包管理器。物理形态长这样┌─ Nginx Master Process ─────────────────────────────┐ │ ┌─ Worker 1 ─┐ ┌─ Worker 2 ─┐ ┌─ Worker N ─┐ │ │ │ LuaJIT VM │ │ LuaJIT VM │ ... │ LuaJIT VM │ │ ← 每个 worker 内嵌一个 VM │ │ ngx_lua │ │ ngx_lua │ │ ngx_lua │ │ │ └────────────┘ └────────────┘ └────────────┘ │ │ ↕ 共享内存 (lua_shared_dict) 跨 worker 通信 │ └────────────────────────────────────────────────────┘关键点一个请求只在一个 Worker 内被处理Lua 代码就跑在那个 worker 的 VM 里。所有 worker 平等竞争请求。二、工作原理之一阶段模型phaseNginx 把一次 HTTP 请求切成11 个阶段各模块像流水线一样依次介入 。其中find-config、post-rewrite、post-access、try-files这 4 个不允许第三方模块注册剩下的是 OpenResty 的舞台。OpenResty 给每个可介入阶段配了xxx_by_lua*指令三种写法等价xxx_by_lua字符串、xxx_by_lua_block代码块、xxx_by_lua_file外部文件生产推荐。阶段指令典型用途能发起网络 IO配置加载init_by_lua预加载模块、申请共享内存❌worker 启动init_worker_by_lua启动定时器、健康检查仅 timer 中TLS 握手ssl_certificate_by_lua动态选证书✅rewriteset_by_lua/rewrite_by_lua改 URI、重定向、改参数✅accessaccess_by_lua鉴权、限流、IP 黑白名单​✅contentcontent_by_lua生成响应与 proxy_pass 二选一✅负载均衡balancer_by_lua自定义选后端✅响应头header_filter_by_lua改写响应头、注入 trace id❌响应体body_filter_by_lua流式改写响应体❌日志log_by_lua异步日志、指标上报✅两条铁律阶段越靠前拦截成本越低——鉴权放access阶段非法请求在 Nginx 内就 401 终结连上游连接都不会建立​阶段决定能用哪些 API——ngx.sleep、ngx.socket.tcp这类会 yield 的 API 在header_filter/body_filter/set_by_lua里不可用这是新手最常踩的坑一次请求的完整链路请求进入 ├─ init / init_worker (进程级只跑一次) ├─ ssl_certificate (HTTPS 握手) ├─ rewrite_by_lua → 改 URI、路由判断 ├─ access_by_lua → 鉴权、限流 ✦ 网关主战场 ├─ balancer_by_lua → 选后端 ├─ content_by_lua / proxy_pass → 出内容或转发 ├─ header_filter_by_lua→ 改响应头 ├─ body_filter_by_lua → 改响应体可能多次 └─ log_by_lua → 埋点、上报三、工作原理之二cosocket真正的黑科技这是理解 OpenResty 的钥匙。cosocket coroutine socket。问题背景很直接Nginx worker 是单线程事件循环。如果你在 Lua 里写一句传统的阻塞调用比如查 Redis整个 worker 进程被卡死事件循环停止该 worker 上所有并发请求全部暂停——Nginx 的性能模型直接崩塌。OpenResty 的解法是给每个请求绑一个Lua 协程把所有可能阻塞的 IO 都封装成 cosocketLua 代码: local res redis:get(key) ← 写法是完全同步的 │ ▼ ① 遇到网络 IO协程 yield让出控制权 ② 把 socket 事件注册进 Nginx 的 epoll 监听列表 ③ 控制权交回 Nginx 事件循环 → 去处理其他请求 │ ④ Redis 数据返回epoll 事件触发 ▼ ⑤ Nginx resume 该协程 → 从 yield 处继续往下执行开发者写同步代码底层跑异步非阻塞​ 。协程切换完全在用户态完成不陷入内核成本极低 。cosocket 支持 TCP、UDP、Unix Domain Socket是所有 lua-resty-非阻塞库的基础*——没有它lua-resty-redis、lua-resty-mysql 都无法存在 。主要 APIngx.socket.tcp()创建对象 →settimeouts()→connect()→send()→receive()/receiveuntil()→setkeepalive()连接池复用默认池大小 30空闲超时 60s。四、变量作用域并发安全的关键这也是架构上必须记住的搞错就是高并发下的血案类型作用域生命周期用途全局变量所有 worker 所有请求进程级⚠️ 只在 init 阶段用local 变量当前阶段当前请求最常用模块级变量​同一 worker 内所有请求共享​worker 级⚠️ 只读配置/常量写会有竞态ngx.ctx当前请求的所有阶段请求级跨阶段传递数据​ngx.shared.dict所有 worker显式删除前限流计数器、缓存、锁模块级变量被同一 worker 内所有请求共享高并发下写它会产生竞态条件——这是最隐蔽的坑 。五、回到你前面问的 AP这下串起来了前面说 Nginx 可以通过OpenResty lua-resty-openidc实现 OIDC 认证、变身简易 IAP。落地方式就是——在access_by_lua​ 阶段挂 Lua 脚本用lua-resty-openidc完成 OIDC 握手、验签 JWT然后把身份信息注入请求头X-User-Email、X-User-Roles转给后端。整个 OIDC 状态机跑在Nginx worker 进程内的 LuaJIT​ 里不产生额外网络跳转。对比一下前面提过的两种形态性能差异就在这外挂式 Forward Authauth_request子请求 → 多一次网络往返OpenResty Lua 原生OIDC 握手在 worker 进程内完成 → 无额外跳转性能显著更高顺带说一句Kong、APISIX 这两个主流 API 网关的底座都是 OpenResty——它们本质就是在access阶段那一堆 Lua 上做的插件体系。六、它的能力边界适合API 网关、接口鉴权、限流、灰度路由、简单 WAF、动态反代、日志增强、Header 处理、参数校验、黑白名单。不适合的任何阻塞式长逻辑——铁律只有一条不可阻塞。长时间占用 worker 就是事故事件循环被卡、全 worker 请求排队重量级业务逻辑——那是后端服务的事塞进网关会拖垮所有流量
返回列表