Nginx Proxy Manager 流式转发(Stream)完全指南:TCP/UDP 四层端口转发配置与源码解析
Nginx Proxy Manager 流式转发Stream完全指南TCP/UDP 四层端口转发配置与源码解析【免费下载链接】nginx-proxy-managerDocker container for managing Nginx proxy hosts with a simple, powerful interface项目地址: https://gitcode.com/GitHub_Trending/ng/nginx-proxy-managerStream 是 Nginx Proxy Manager 中用于四层TCP/UDP流量转发的功能它不依赖域名与 HTTP 协议而是直接把入站端口上的原始网络流量转发到内网另一台主机非常适合游戏服务器、FTP、SSH 等非 Web 服务的端口映射场景。本文将基于仓库内文档与源码系统讲解 Stream 的工作原理、界面配置步骤、端口与协议参数细节、SSL 支持以及底层 Nginx 配置生成机制读完即可独立完成一个可用的 TCP/UDP 端口转发。Stream 是什么为什么需要四层转发Nginx 的 Stream 模块ngx_stream是相对于 HTTP 七层代理而言的流代理能力。Nginx Proxy Manager 将它包装为页面上的Streams功能用于将 TCP/UDP 流量直接转发到网络中的另一台计算机而不做任何协议层的解析与改写。官方帮助文档 frontend/src/locale/src/HelpDoc/en/Streams.md 给出了精炼的定义A relatively new feature for Nginx, a Stream will serve to forward TCP/UDP traffic directly to another computer on the network. If youre running game servers, FTP or SSH servers this can come in handy.核心要点面向非 HTTP 服务游戏服务器、FTP、SSH、数据库端口、VoIP 等使用自定义协议或二进制协议的服务无法用 HTTP 反代处理只能走四层转发按端口转发一个 Stream 对应一对入站端口 → 目标主机:目标端口天然符合公网端口映射到内网服务的需求协议透明Nginx 只搬运字节流不关心上层是什么协议因此 TCP 与 UDP 都能覆盖。创建 Stream 的完整配置流程在 Nginx Proxy Manager 管理界面左侧菜单进入Streams点击添加按钮即可打开 Stream 编辑弹窗表单由 Details详情 与 SSL 两个标签页组成。前端表单实现在 frontend/src/modals/StreamModal.tsx字段说明如下。详情页核心字段字段必填说明取值范围 / 校验Incoming Port入站端口是公网Nginx Proxy Manager 所在主机监听的端口1 ~ 65535如8080Forward Host转发主机是流量的最终目的地支持域名、IPv4、IPv61 ~ 255 个字符Forward Port转发端口是目标主机上服务实际监听的端口1 ~ 65535如8081TCP Forwarding否是否开启 TCP 转发布尔值默认需至少开启一种协议UDP Forwarding否是否开启 UDP 转发布尔值同上后端 OpenAPI 请求示例backend/schema/paths/nginx/streams/post.json给出了完整负载结构{ incoming_port: 8888, forwarding_host: 127.0.0.1, forwarding_port: 8080, tcp_forwarding: true, udp_forwarding: false, certificate_id: 0, meta: {} }其中只有incoming_port、forwarding_host、forwarding_port三个字段是创建时的必填项tcp_forwarding与udp_forwarding默认为布尔开关。接口校验规格定义在 backend/schema/components/stream-object.jsonincoming_port与forwarding_port均为 1~65535 的整数forwarding_host允许域名如example.com、IPv4 地址或 IPv6 地址三种形式。TCP / UDP 协议的互斥联动表单中 TCP 与 UDP 是两个独立的开关但前端做了一层互斥保护当取消 TCP 时会自动强制开启 UDP反之亦然见 frontend/src/modals/StreamModal.tsx 中tcpForwarding与udpForwarding的onChange处理。这保证了一条 Stream 永远至少转发一种协议不会出现创建了却什么都不转发的无效配置。SSL 标签页Stream 同样支持为入站端口绑定 SSL 证书适合对 TLS 加密的自定义协议如openssl s_client测试的 TCP 服务做终止或透传。SSL 页签复用SSLCertificateField与SSLOptionsFields组件允许选择已有证书或现场签发新证书allowNew、forceDNSForNew并强制要求提供域名用于签发requireDomainNames。字段值范围、默认值与接口契约为了让配置更精确这里把后端 OpenAPI 规格中的关键约束汇总如下来源backend/schema/components/stream-object.jsonincoming_portinteger1 ~ 65535forwarding_portinteger1 ~ 65535forwarding_host支持三种格式——域名正则^(?:[^.*]\.?)[^.]$、IPv41.2.3.4形式、IPv6tcp_forwarding/udp_forwardingbooleanenabledboolean控制 Stream 是否启用certificate_id关联证书 ID0表示不启用 SSLmeta任意对象后端会写入nginx_online、nginx_err等状态字段见创建接口的响应示例。一个完整的 Stream 对象响应示例来自 backend/schema/paths/nginx/streams/post.json{ id: 1, created_on: 2024-10-09T02:33:45.000Z, modified_on: 2024-10-09T02:33:45.000Z, owner_user_id: 1, incoming_port: 9090, forwarding_host: router.internal, forwarding_port: 80, tcp_forwarding: true, udp_forwarding: false, meta: { nginx_online: true, nginx_err: null }, enabled: true, certificate_id: 0 }Stream 的 API 与权限模型Stream 与 Proxy Hosts 等其他资源一样通过 REST API 管理路由定义在 backend/routes/nginx/streams.js方法路径功能GET/api/nginx/streams列出全部 Stream支持expand、query参数POST/api/nginx/streams创建 StreamGET/api/nginx/streams/:stream_id查询单个 StreamPUT/api/nginx/streams/:stream_id更新 StreamDELETE/api/nginx/streams/:stream_id删除 StreamPOST/api/nginx/streams/:host_id/enable启用 StreamPOST/api/nginx/streams/:host_id/disable停用 Stream所有接口均要求 JWT 鉴权jwtdecode()中间件业务逻辑统一委托给 backend/internal/stream.js 的internalStream对象处理。权限方面创建 Stream 需要具备streams.manage权限或管理员角色校验规则见 backend/lib/access/streams-create.json普通用户需要permission_streams: manage且角色为user管理员admin直接放行。另外从 backend/internal/stream.js 的实现可以看出get/getAll会根据当前用户的permission_visibility过滤非all可见性时只能看到owner_user_id为当前用户的记录创建时自动写入owner_user_idcertificate_id传字符串new时会先调用createQuickCertificate快速签发证书再回填 ID每次创建 / 更新 / 启用 / 停用 / 删除都会写入审计日志internalAuditLog.addobject_type为stream。底层原理Stream 如何生成 Nginx 配置Stream 的核心实现是模板渲染。创建或更新成功后internalStream会调用internalNginx.configure(streamModel, stream, row)使用 backend/templates/stream.conf 模板生成对应的 Nginx 配置段。模板关键结构如下# ------------------------------------------------------------ # {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }} # ------------------------------------------------------------ {% if enabled %} {% if tcp_forwarding 1 or tcp_forwarding true -%} server { listen {{ incoming_port }} reuseport {%- if certificate %} ssl {%- endif %}; {% unless ipv6 -%} # {%- endunless -%} listen [::]:{{ incoming_port }} reuseport {%- if certificate %} ssl {%- endif %}; {%- include _certificates_stream.conf %} proxy_pass {{ forwarding_host }}:{{ forwarding_port }}; access_log /data/logs/stream-{{ id }}_access.log stream; error_log /data/logs/stream-{{ id }}_error.log warn; # Custom include /data/nginx/custom/server_stream[.]conf; include /data/nginx/custom/server_stream_tcp[.]conf; } {% endif %} {% if udp_forwarding 1 or udp_forwarding true -%} server { listen {{ incoming_port }} udp reuseport; {% unless ipv6 -%} # {%- endunless -%} listen [::]:{{ incoming_port }} udp reuseport; proxy_pass {{ forwarding_host }}:{{ forwarding_port }}; access_log /data/logs/stream-{{ id }}_access.log stream; error_log /data/logs/stream-{{ id }}_error.log warn; # Custom include /data/nginx/custom/server_stream[.]conf; include /data/nginx/custom/server_stream_udp[.]conf; } {% endif %} {% endif %}可以从模板中读出的实现事实TCP 与 UDP 各生成一个独立的server块TCP 使用listen port reuseport可选sslUDP 使用listen port udp reuseport二者都通过proxy_pass指向forwarding_host:forwarding_portIPv6 可选若实例关闭 IPv6ipv6为假对应行会被模板注释掉独立日志每个 Stream 拥有独立的访问日志/data/logs/stream-id_access.log与错误日志/data/logs/stream-id_error.log便于排查转发问题自定义配置挂载点支持在/data/nginx/custom/下放置server_stream.conf、server_stream_tcp.confTCP或server_stream_udp.confUDP追加自定义指令实现高级定制而不影响自动生成部分。SSL 证书的注入由 backend/templates/_certificates_stream.conf 完成Lets Encrypt 证书指向/etc/letsencrypt/live/npm-certificate_id/fullchain.pem自定义证书指向/data/custom_ssl/npm-certificate_id/fullchain.pem并附带密钥路径。数据模型与历史演进Stream 数据存储在stream表中ORM 模型见 backend/models/stream.js布尔字段is_deleted、enabled、tcp_forwarding、udp_forwarding在数据库中以 0/1 整数存储ORM 读写时自动转换表关联owner所属用户与certificateSSL 证书默认按incoming_port升序排列迁移记录 backend/migrations/20210423103500_stream_domain.js 显示早期字段名为forward_ip2021 年迁移为forwarding_host以同时支持 IP 与域名作为转发目标另一个相关迁移 backend/migrations/20240427161436_stream_ssl.js 表明 Stream 后来引入了 SSL 支持。另外由于 Stream 按端口而非域名路由backend/internal/stream.js 在创建时会显式删除domain_names字段streams arent routed by domain name so dont store domain names in the DB仅在签发新证书的辅助场景中临时使用域名。启停、删除与状态管理启用 / 停用通过POST /api/nginx/streams/:host_id/enable与/disable实现。启用时调用internalNginx.configure重新生成配置停用与删除时调用internalNginx.deleteConfig并reloadNginx。重复启用/停用会返回ValidationErrorStream is already enabled/disabled删除软删除is_deleted 1随后删除 Nginx 配置并热重载确保端口及时释放Nginx 状态回写每次配置生成后meta.nginx_online与meta.nginx_err会被更新前端可据此展示 Stream 当前是否生效。实战建议与注意事项端口冲突检查同一台 Nginx Proxy Manager 上incoming_port全局唯一创建前确认没有其他 Stream、Proxy Host 或系统服务占用该端口从源码注释看端口重复的强校验仍在 TODO 列表配置错误会在 Nginx reload 阶段暴露为nginx_err协议匹配目标服务是 TCP 就只开 TCP是 UDP如部分游戏服务器、DNS、VoIP就只开 UDP两者同时开启时 Nginx 会监听同一端口的 TCP 与 UDP 两种流量转发目标forwarding_host可以是内网 IP、域名或 IPv6但需确保 Nginx Proxy Manager 容器能路由到该地址Docker 部署时注意容器网络模式对目标可达性的影响SSL 使用场景若客户端与服务端之间有 TLS 握手如带 TLS 的自定义协议可绑定证书启用 SSL普通明文服务保持certificate_id: 0即可调试入口转发异常时先查看/data/logs/stream-id_access.log与stream-id_error.log也可在/data/nginx/custom/挂载自定义配置做限速、访问控制等扩展权限规划为普通用户分配 Stream 管理权限时注意其只能查看和操作自己创建的 Streampermission_visibility非all时按owner_user_id过滤。小结Stream 为 Nginx Proxy Manager 补齐了四层转发能力让游戏、FTP、SSH 等非 HTTP 服务也能通过图形界面一键完成端口映射。其背后是一条清晰的链路前端表单StreamModal.tsx→ REST APIroutes/nginx/streams.js→ 业务逻辑internal/stream.js→ 模板渲染templates/stream.conf→ Nginx 热重载每一步都在仓库源码中有据可查遇到问题时可以沿着这条链路快速定位。【免费下载链接】nginx-proxy-managerDocker container for managing Nginx proxy hosts with a simple, powerful interface项目地址: https://gitcode.com/GitHub_Trending/ng/nginx-proxy-manager创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考