# noxway **Repository Path**: fierce_wolf/noxway ## Basic Information - **Project Name**: noxway - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-17 - **Last Updated**: 2026-09-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Noxway ![Docker](https://github.com/adrian-lorenz/noxway/actions/workflows/docker.yml/badge.svg) ![Tests](https://github.com/adrian-lorenz/noxway/actions/workflows/ci.yml/badge.svg) ![LeakGuard](https://github.com/adrian-lorenz/noxway/actions/workflows/leakguard.yml/badge.svg) ![Docker Pulls](https://img.shields.io/docker/pulls/noxway/noxway) ![Docker Image Version](https://img.shields.io/docker/v/noxway/noxway/latest) ![Go Version](https://img.shields.io/github/go-mod/go-version/adrian-lorenz/noxway) ![License](https://img.shields.io/github/license/adrian-lorenz/noxway) ![img_3.png](img_3.png) 一个用 Go 编写的轻量级、自包含 API 网关。 所有配置都通过内置的 Web 管理后台完成 —— 不依赖外部配置文件,也不需要额外的控制面板。 > 管理后台界面已做中文化,并支持右上角中 / 英切换。 ## 功能特性 **路由** - 基于路径的反向代理,每个服务可配置子端点 - 基于请求头的路由(按 header 值分发) - WebSocket 代理(按端点单独开启) - 端点级自定义超时 - 服务 IP 白名单 **安全** - 按服务配置的 Web 应用防火墙(WAF):SQL 注入、XSS、路径穿越、命令注入、请求体大小限制 - 端点级 JWT 预校验(转发前先验证入站 JWT) - IP 黑名单(精确 IP 或 CIDR 网段) - 管理后台访问白名单(精确 IP 或 DNS 主机名) - 基于每 IP 滑动窗口的限流 - 支持 TLS,内置 Let's Encrypt 证书申请 **管理后台** - 基于 HTMX 的内置界面,入口为 `/admin` - 实时仪表盘,含请求统计与图表 - 服务 / 端点完整增删改查 - 网关配置编辑器 - 按服务配置 WAF - 访问日志查看器 - 已编译进二进制,无需单独的前端进程 **基础设施** - 单个二进制,无运行时依赖 - 配置与日志全部落在 PostgreSQL,运行时不产生 JSON 文件 - 支持 Docker 部署 --- ## 界面截图 ![img.png](img.png) ![img_1.png](img_1.png) ![img_2.png](img_2.png) ## 快速开始 ### 1. 准备 `conf/.env` 部署相关的机密统一放在 `conf/` 下,不放仓库根目录: ```bash cp conf/.env.example conf/.env ``` 编辑 `conf/.env`,为两个密钥设置足够强壮的值: ```env DATABASE=postgres://noxway:你的数据库密码@localhost:5432/noxway?sslmode=disable POSTGRES_PASSWORD=你的数据库密码 JWTSECRET=一串很长的随机字符串 ``` Noxway 启动时会优先查找 `conf/.env`,找不到才回退到项目根目录的 `./.env`, 因此历史部署不用改。如果两个文件都不存在,就直接使用进程环境变量 (容器镜像正是这么运行的)。 用下面的命令生成一个安全的 JWT 密钥: ```bash openssl rand -hex 32 ``` ### 本地文件都在哪里 `conf/` 只放配置文件 —— 部署机密与 TLS 材料: | 路径 | 说明 | |------|------| | `conf/.env` | 部署机密 —— `DATABASE`、`POSTGRES_PASSWORD`、`JWTSECRET`(不提交) | | `conf/.env.example` | 配置模板 | | `conf/leakguard.toml` | CI 使用的密钥扫描器配置 | | `conf/certs/` | TLS 材料 —— `cert.pem`、`privkey.pem` 或 Let's Encrypt 的输出 | 日志属于运行产物而不是配置,因此留在仓库根目录: | 路径 | 说明 | |------|------| | `log/noxway.log` | 网关设置里启用日志导出后写入的访问日志 | | `logs/` | `shell/startup.*` 的运行产物(PID 文件、标准输出 / 错误输出) | 缺失的目录会自动创建。配置里仍指向旧位置(如 `./certs/...`)的值会在启动时 自动改写为新位置,而已经存在于旧 `certs/` 目录中的证书仍会继续使用。 ### 2. 启动 ```bash docker compose up -d ``` 网关与 PostgreSQL 会自动起来。首次启动时会把默认配置写入数据库。 ### 3. 设置管理员密码 默认账号为 `admin` / `admin`。请立刻修改密码,并配置管理后台 IP 白名单: ```bash curl -X POST http://localhost:8080/setAdmin \ -H "Content-Type: application/json" \ -d '{ "password": "admin", "newpassword": "你的新密码", "whitelist": ["你的IP地址"], "dnswhitelist": [] }' ``` `whitelist` 用来限制哪些 IP 可以访问管理后台与管理 API。 填 `[]` 表示不限制(生产环境不建议)。 > 提示:如果你是从本机 `curl` 调用该接口,脚本会把本机 IP(可能是 IPv6 的 `::1`) > 写进白名单,导致从浏览器用 `127.0.0.1` 访问时报「当前 IP 不允许访问」。 > 建议首次登录后到管理后台把白名单清空,或直接设为实际的管理 IP。 ### 4. 打开管理后台 ``` http://localhost:8080/admin ``` --- ## 环境变量 | 变量 | 是否必需 | 说明 | |------|----------|------| | `DATABASE` | 是 | PostgreSQL 连接串 —— docker-compose 会自动设置 | | `JWTSECRET` | 是 | 管理后台会话 JWT 的签名密钥(建议不少于 32 字符) | | `POSTGRES_PASSWORD` | 是 | `noxway` 数据库用户的密码(仅 docker-compose 用) | --- ## docker-compose.yml ```yaml services: noxway: build: . ports: - "8080:8080" - "443:443" volumes: - ./conf/certs:/app/conf/certs - ./log:/app/log env_file: - conf/.env environment: DATABASE: "postgres://noxway:${POSTGRES_PASSWORD}@db:5432/noxway?sslmode=disable" restart: unless-stopped depends_on: db: condition: service_healthy db: image: postgres:16-alpine environment: POSTGRES_DB: noxway POSTGRES_USER: noxway POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" volumes: - db_data:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U noxway -d noxway"] interval: 5s timeout: 5s retries: 10 volumes: db_data: ``` --- ## 配置说明 所有配置都持久化在 PostgreSQL 中,并通过管理后台维护。运行时不使用 JSON 文件。 ### 网关设置(`/admin/gateway`) | 配置项 | 说明 | |--------|------| | 端口 Port | HTTP 监听端口(默认 `8080`) | | SSL 端口 | HTTPS 监听端口(默认 `443`) | | 前缀 Prefix | 代理路由的 URL 前缀(默认 `/v1/`) | | CORS | 开启 CORS,可配置来源、方法、请求头 | | 限流 | 每 IP 在窗口期内的请求数,支持白名单 | | 黑名单 | 屏蔽 IP 或 CIDR 网段(例如 `10.0.0.0/8`) | | Let's Encrypt | 自动申请 TLS 证书 | | DNS 解析器 | 指定的 DNS 服务器,用于白名单 DNS 反查 | ### 服务与端点(`/admin/endpoints`) 每个**服务**对应一个 URL 路径前缀,包含一个基础端点和若干可选子端点。 子端点按请求头的值匹配 —— 例如把 `X-System: dev` 的请求转发到预发布后端, 其余流量仍走基础端点。 | 端点配置 | 说明 | |----------|------| | 端点 URL | 要转发到的后端地址 | | 启用 | 临时停用但不删除 | | 校验 SSL | 校验后端 TLS 证书 | | WebSocket 代理 | 将 WebSocket 连接桥接到后端 | | 覆盖超时 | 该端点的超时时间(秒) | | 请求头追加 | 转发前向请求注入请求头 | | 请求头替换 | 转发前替换请求头的值 | | 请求头校验 | 缺少指定请求头时拒绝请求 | | IP 白名单 | 该端点只允许列出的 IP 访问 | | JWT 预校验 | 转发前校验入站 JWT | | 客户端证书认证 | 基于客户端证书的双向 TLS | ### 重命名服务(`/admin/endpoints` → 重命名 按钮) 服务名就是网关 URL 的第一段。改名会同步做两件事: 1. 把服务名改掉; 2. 把「免 JWT 预检路由」里以 `/旧名` 开头的路径一并改成 `/新名`(否则这些入口会静默失效)。 改名**必须重启网关**才生效:gin 的路由是启动时一次性注册的, 后台的「重载网关」只刷新配置,不会注册新名字 —— 不重启的话新地址 404,旧地址反而还在。 调用方也要一起改: ``` GET /usermgr/v1/user/nickname ← 改名后失效 GET /user-mgr/v1/user/nickname ← 新地址 ``` 服务名的限制:不能与网关保留路径冲突(`admin`、`web`、`login`、`reload`、 `database`、`config_*`、`set_user`、`setAdmin`、`retiveCert`、`testservice1-3`), 不能包含空格或 `/ : * ? # \`,也不能和已有服务重名。 连字符、下划线、数字、点都可以,所以 `usermgr` 改成 `user-mgr` 没问题。 > 历史日志里的 `Service` 字段仍是旧名,仪表盘的「服务调用 Top」会按新旧两个名字分开统计。 ### WAF(`/admin/endpoints` → WAF 按钮) 按服务配置。开启后每个请求都会在转发前接受检查。 | 规则 | 拦截内容 | |------|----------| | SQL 注入 | UNION SELECT、DROP TABLE、OR 1=1 等特征 | | XSS | `