diff --git a/apps/microwarp/README.md b/apps/microwarp/README.md new file mode 100644 index 000000000..f64ff501f --- /dev/null +++ b/apps/microwarp/README.md @@ -0,0 +1,51 @@ +# MicroWARP(1Panel v2) + +基于 `ghcr.io/ccbkkb/microwarp` 的轻量级 Cloudflare WARP 代理封装,统一收敛为 `microwarp` 单 key,并提供官方原版与定时轮换变体。 + +## 版本说明 + +### latest +- 官方原版 +- 仅提供 SOCKS5 代理 +- 不做自动 IP 轮换,适合需要稳定出口身份的场景 + +### http-latest +- 官方原版增强变体 +- 在 SOCKS5 基础上额外提供 HTTP 代理端口 +- 通过 `gogost/gost` sidecar 将 HTTP 转发到 SOCKS5 + +### rotator-latest +- 基于官方原版增加定时 WARP 身份重建 +- 轮换通过删除旧 `wg0.conf` 与账号缓存后重新执行上游初始化完成 +- 轮换时会有秒级短暂中断 + +### rotator-http-latest +- 在 `rotator-latest` 基础上额外提供 HTTP 代理端口 + +## 安装建议 + +- 只需官方 SOCKS5:安装 `latest` +- 需官方 SOCKS5 + HTTP:安装 `http-latest` +- 需要定时切换 WARP 身份:安装 `rotator-latest` +- 需要定时切换并同时提供 HTTP:安装 `rotator-http-latest` + +## 核心参数 + +- `PANEL_APP_PORT_SOCKS5`:SOCKS5 对外端口 +- `PANEL_APP_PORT_HTTP_PROXY`:HTTP 代理端口,仅 `*-http-latest` 版本使用 +- `APP_DATA_DIR_1`:WireGuard 持久化目录,保存 `wg0.conf` 与 `wgcf` 注册信息 +- `SOCKS_USER` / `SOCKS_PASS`:启用 SOCKS5 认证 +- `ENDPOINT_IP`:手动覆盖 WARP Endpoint +- `GH_PROXY` / `GITHUB_TOKEN`:辅助 `wgcf` 下载与 GitHub API 调用 +- `TAILSCALE_CIDR`:Tailscale 回程路由 CIDR,默认 `100.64.0.0/10` +- `MTU`:WireGuard MTU,默认 `1280` +- `WARP_WGCF_CONF`:可选完整 WireGuard 配置内容;也可直接将 `wg0.conf` 放入持久化目录 +- `ROTATE_INTERVAL_MINUTES`:轮换间隔(分钟),仅 `rotator-*` 版本使用,`0` 表示关闭 + +## 使用说明 + +- 默认使用外部网络 `1panel-network` +- 首次启动会自动注册 WARP 设备并生成 `/etc/wireguard/wg0.conf` +- 建议保留 `APP_DATA_DIR_1` 持久化目录,避免每次重启都重新注册 +- 如果设置了 `WARP_WGCF_CONF`,`rotator-*` 版本会自动关闭定时轮换,因为该配置已固定出口身份 +- `rotator-*` 版本的轮换逻辑是完整重建 WARP 身份,而不是调用上游并不存在的 rotate API diff --git a/apps/microwarp/data.yml b/apps/microwarp/data.yml new file mode 100644 index 000000000..aedffdcae --- /dev/null +++ b/apps/microwarp/data.yml @@ -0,0 +1,32 @@ +name: MicroWARP +tags: + - 工具 +title: 轻量级 Cloudflare WARP SOCKS5 代理,附带 HTTP 与定时轮换变体 +type: 工具 +description: 轻量级 Cloudflare WARP SOCKS5 代理,附带 HTTP 与定时轮换变体 +additionalProperties: + key: microwarp + name: MicroWARP + tags: + - Tool + shortDescZh: 轻量级 Cloudflare WARP SOCKS5 代理,附带 HTTP 与定时轮换变体 + shortDescEn: Lightweight Cloudflare WARP SOCKS5 proxy with official, HTTP, and rotator variants + description: + en: Lightweight Cloudflare WARP SOCKS5 proxy with official, HTTP, and rotator variants + zh: 轻量级 Cloudflare WARP SOCKS5 代理,附带 HTTP 与定时轮换变体 + zh-Hant: 輕量級 Cloudflare WARP SOCKS5 代理,附帶 HTTP 與定時輪換變體 + ja: 公式版、HTTP 変種、定期ローテーション変種を備えた軽量 Cloudflare WARP SOCKS5 プロキシ + ko: 공식판, HTTP 변형, 주기적 로테이터 변형을 함께 제공하는 경량 Cloudflare WARP SOCKS5 프록시 + ru: Легковесный SOCKS5-прокси Cloudflare WARP с официальным, HTTP- и rotator-вариантами + ms: Proksi SOCKS5 Cloudflare WARP ringan dengan varian rasmi, HTTP dan rotator + pt-br: Proxy SOCKS5 leve do Cloudflare WARP com variantes oficial, HTTP e rotator + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://github.com/ccbkkb/MicroWARP + github: https://github.com/ccbkkb/MicroWARP + document: https://github.com/ccbkkb/MicroWARP#readme + architectures: + - amd64 + - arm64 diff --git a/apps/microwarp/http-latest/.env.sample b/apps/microwarp/http-latest/.env.sample new file mode 100644 index 000000000..3f5f2e12e --- /dev/null +++ b/apps/microwarp/http-latest/.env.sample @@ -0,0 +1,14 @@ +CONTAINER_NAME=microwarp +PANEL_APP_PORT_SOCKS5=1080 +PANEL_APP_PORT_HTTP_PROXY=8080 +BIND_PORT=1080 +SOCKS_USER= +SOCKS_PASS= +ENDPOINT_IP= +GH_PROXY= +GITHUB_TOKEN= +TAILSCALE_CIDR=100.64.0.0/10 +MTU=1280 +WARP_WGCF_CONF= +TZ=Asia/Shanghai +APP_DATA_DIR_1=./data diff --git a/apps/microwarp/http-latest/data.yml b/apps/microwarp/http-latest/data.yml new file mode 100644 index 000000000..d8111df61 --- /dev/null +++ b/apps/microwarp/http-latest/data.yml @@ -0,0 +1,96 @@ +additionalProperties: + formFields: + - default: 1080 + envKey: PANEL_APP_PORT_SOCKS5 + labelEn: SOCKS5 Port + labelZh: SOCKS5 端口 + required: true + rule: paramPort + type: number + edit: true + - default: 8080 + envKey: PANEL_APP_PORT_HTTP_PROXY + labelEn: HTTP Proxy Port + labelZh: HTTP 代理端口 + required: true + rule: paramPort + type: number + edit: true + - default: 1080 + envKey: BIND_PORT + labelEn: Internal Bind Port + labelZh: 容器内部绑定端口 + required: true + rule: paramPort + type: number + edit: true + - default: "" + envKey: SOCKS_USER + labelEn: SOCKS Username + labelZh: SOCKS 用户名 + required: false + type: text + edit: true + - default: "" + envKey: SOCKS_PASS + labelEn: SOCKS Password + labelZh: SOCKS 密码 + required: false + type: text + edit: true + - default: "" + envKey: ENDPOINT_IP + labelEn: WARP Endpoint + labelZh: WARP 终结点 + required: false + type: text + edit: true + - default: "" + envKey: GH_PROXY + labelEn: wgcf Download Proxy + labelZh: wgcf 下载代理 + required: false + type: text + edit: true + - default: "" + envKey: GITHUB_TOKEN + labelEn: GitHub Token + labelZh: GitHub Token + required: false + type: text + edit: true + - default: 100.64.0.0/10 + envKey: TAILSCALE_CIDR + labelEn: Tailscale Return Route CIDR + labelZh: Tailscale 回程路由 CIDR + required: true + type: text + edit: true + - default: 1280 + envKey: MTU + labelEn: WireGuard MTU + labelZh: WireGuard MTU + required: true + type: number + edit: true + - default: "" + envKey: WARP_WGCF_CONF + labelEn: WireGuard Config Content + labelZh: WireGuard 配置内容 + required: false + type: text + edit: true + - default: Asia/Shanghai + envKey: TZ + labelEn: Timezone + labelZh: 时区 + required: true + type: text + edit: true + - default: ./data + envKey: APP_DATA_DIR_1 + labelEn: WireGuard Data Directory + labelZh: WireGuard 数据目录 + required: true + type: text + edit: true diff --git a/apps/microwarp/http-latest/docker-compose.yml b/apps/microwarp/http-latest/docker-compose.yml new file mode 100644 index 000000000..f4f3105dd --- /dev/null +++ b/apps/microwarp/http-latest/docker-compose.yml @@ -0,0 +1,52 @@ +services: + microwarp: + image: "ghcr.io/ccbkkb/microwarp:latest" + container_name: ${CONTAINER_NAME} + labels: + createdBy: "Apps" + ports: + - "${PANEL_APP_PORT_SOCKS5}:${BIND_PORT}" + environment: + - TZ=${TZ} + - BIND_ADDR=0.0.0.0 + - BIND_PORT=${BIND_PORT} + - SOCKS_USER=${SOCKS_USER:-} + - SOCKS_PASS=${SOCKS_PASS:-} + - ENDPOINT_IP=${ENDPOINT_IP:-} + - GH_PROXY=${GH_PROXY:-} + - GITHUB_TOKEN=${GITHUB_TOKEN:-} + - TAILSCALE_CIDR=${TAILSCALE_CIDR:-100.64.0.0/10} + - MTU=${MTU} + - WARP_WGCF_CONF=${WARP_WGCF_CONF:-} + cap_add: + - NET_ADMIN + - SYS_MODULE + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + volumes: + - "${APP_DATA_DIR_1}:/etc/wireguard" + restart: always + networks: + - 1panel-network + + http-proxy: + image: "gogost/gost:latest" + container_name: ${CONTAINER_NAME}-http + labels: + createdBy: "Apps" + depends_on: + - microwarp + command: + - "-L" + - "http://0.0.0.0:8080" + - "-F" + - "socks5://microwarp:${BIND_PORT}" + ports: + - "${PANEL_APP_PORT_HTTP_PROXY}:8080" + restart: always + networks: + - 1panel-network + +networks: + 1panel-network: + external: true diff --git a/apps/microwarp/http-latest/scripts/init.sh b/apps/microwarp/http-latest/scripts/init.sh new file mode 100644 index 000000000..cfef1b85e --- /dev/null +++ b/apps/microwarp/http-latest/scripts/init.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" diff --git a/apps/microwarp/http-latest/scripts/uninstall.sh b/apps/microwarp/http-latest/scripts/uninstall.sh new file mode 100755 index 000000000..ab8a8d674 --- /dev/null +++ b/apps/microwarp/http-latest/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down --volumes diff --git a/apps/microwarp/http-latest/scripts/upgrade.sh b/apps/microwarp/http-latest/scripts/upgrade.sh new file mode 100644 index 000000000..e17b81f76 --- /dev/null +++ b/apps/microwarp/http-latest/scripts/upgrade.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" +exit 0 diff --git a/apps/microwarp/latest/.env.sample b/apps/microwarp/latest/.env.sample new file mode 100644 index 000000000..cd98170d3 --- /dev/null +++ b/apps/microwarp/latest/.env.sample @@ -0,0 +1,13 @@ +CONTAINER_NAME=microwarp +PANEL_APP_PORT_SOCKS5=1080 +BIND_PORT=1080 +SOCKS_USER= +SOCKS_PASS= +ENDPOINT_IP= +GH_PROXY= +GITHUB_TOKEN= +TAILSCALE_CIDR=100.64.0.0/10 +MTU=1280 +WARP_WGCF_CONF= +TZ=Asia/Shanghai +APP_DATA_DIR_1=./data diff --git a/apps/microwarp/latest/data.yml b/apps/microwarp/latest/data.yml new file mode 100644 index 000000000..8efd5d680 --- /dev/null +++ b/apps/microwarp/latest/data.yml @@ -0,0 +1,88 @@ +additionalProperties: + formFields: + - default: 1080 + envKey: PANEL_APP_PORT_SOCKS5 + labelEn: SOCKS5 Port + labelZh: SOCKS5 端口 + required: true + rule: paramPort + type: number + edit: true + - default: 1080 + envKey: BIND_PORT + labelEn: Internal Bind Port + labelZh: 容器内部绑定端口 + required: true + rule: paramPort + type: number + edit: true + - default: "" + envKey: SOCKS_USER + labelEn: SOCKS Username + labelZh: SOCKS 用户名 + required: false + type: text + edit: true + - default: "" + envKey: SOCKS_PASS + labelEn: SOCKS Password + labelZh: SOCKS 密码 + required: false + type: text + edit: true + - default: "" + envKey: ENDPOINT_IP + labelEn: WARP Endpoint + labelZh: WARP 终结点 + required: false + type: text + edit: true + - default: "" + envKey: GH_PROXY + labelEn: wgcf Download Proxy + labelZh: wgcf 下载代理 + required: false + type: text + edit: true + - default: "" + envKey: GITHUB_TOKEN + labelEn: GitHub Token + labelZh: GitHub Token + required: false + type: text + edit: true + - default: 100.64.0.0/10 + envKey: TAILSCALE_CIDR + labelEn: Tailscale Return Route CIDR + labelZh: Tailscale 回程路由 CIDR + required: true + type: text + edit: true + - default: 1280 + envKey: MTU + labelEn: WireGuard MTU + labelZh: WireGuard MTU + required: true + type: number + edit: true + - default: "" + envKey: WARP_WGCF_CONF + labelEn: WireGuard Config Content + labelZh: WireGuard 配置内容 + required: false + type: text + edit: true + - default: Asia/Shanghai + envKey: TZ + labelEn: Timezone + labelZh: 时区 + required: true + type: text + edit: true + - default: ./data + envKey: APP_DATA_DIR_1 + labelEn: WireGuard Data Directory + labelZh: WireGuard 数据目录 + required: true + type: text + edit: true diff --git a/apps/microwarp/latest/docker-compose.yml b/apps/microwarp/latest/docker-compose.yml new file mode 100644 index 000000000..849805e40 --- /dev/null +++ b/apps/microwarp/latest/docker-compose.yml @@ -0,0 +1,34 @@ +services: + microwarp: + image: "ghcr.io/ccbkkb/microwarp:latest" + container_name: ${CONTAINER_NAME} + labels: + createdBy: "Apps" + ports: + - "${PANEL_APP_PORT_SOCKS5}:${BIND_PORT}" + environment: + - TZ=${TZ} + - BIND_ADDR=0.0.0.0 + - BIND_PORT=${BIND_PORT} + - SOCKS_USER=${SOCKS_USER:-} + - SOCKS_PASS=${SOCKS_PASS:-} + - ENDPOINT_IP=${ENDPOINT_IP:-} + - GH_PROXY=${GH_PROXY:-} + - GITHUB_TOKEN=${GITHUB_TOKEN:-} + - TAILSCALE_CIDR=${TAILSCALE_CIDR:-100.64.0.0/10} + - MTU=${MTU} + - WARP_WGCF_CONF=${WARP_WGCF_CONF:-} + cap_add: + - NET_ADMIN + - SYS_MODULE + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + volumes: + - "${APP_DATA_DIR_1}:/etc/wireguard" + restart: always + networks: + - 1panel-network + +networks: + 1panel-network: + external: true diff --git a/apps/microwarp/latest/scripts/init.sh b/apps/microwarp/latest/scripts/init.sh new file mode 100644 index 000000000..cfef1b85e --- /dev/null +++ b/apps/microwarp/latest/scripts/init.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" diff --git a/apps/microwarp/latest/scripts/uninstall.sh b/apps/microwarp/latest/scripts/uninstall.sh new file mode 100755 index 000000000..ab8a8d674 --- /dev/null +++ b/apps/microwarp/latest/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down --volumes diff --git a/apps/microwarp/latest/scripts/upgrade.sh b/apps/microwarp/latest/scripts/upgrade.sh new file mode 100644 index 000000000..e17b81f76 --- /dev/null +++ b/apps/microwarp/latest/scripts/upgrade.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" +exit 0 diff --git a/apps/microwarp/logo.png b/apps/microwarp/logo.png new file mode 100644 index 000000000..9cec3e62d Binary files /dev/null and b/apps/microwarp/logo.png differ diff --git a/apps/microwarp/rotator-http-latest/.env.sample b/apps/microwarp/rotator-http-latest/.env.sample new file mode 100644 index 000000000..6af95ff91 --- /dev/null +++ b/apps/microwarp/rotator-http-latest/.env.sample @@ -0,0 +1,16 @@ +CONTAINER_NAME=microwarp +PANEL_APP_PORT_SOCKS5=1080 +PANEL_APP_PORT_HTTP_PROXY=8080 +BIND_PORT=1080 +ROTATE_INTERVAL_MINUTES=0 +TEST_URL=https://cloudflare.com/cdn-cgi/trace +SOCKS_USER= +SOCKS_PASS= +ENDPOINT_IP= +GH_PROXY= +GITHUB_TOKEN= +TAILSCALE_CIDR=100.64.0.0/10 +MTU=1280 +WARP_WGCF_CONF= +TZ=Asia/Shanghai +APP_DATA_DIR_1=./data diff --git a/apps/microwarp/rotator-http-latest/data.yml b/apps/microwarp/rotator-http-latest/data.yml new file mode 100644 index 000000000..e983c3de4 --- /dev/null +++ b/apps/microwarp/rotator-http-latest/data.yml @@ -0,0 +1,110 @@ +additionalProperties: + formFields: + - default: 1080 + envKey: PANEL_APP_PORT_SOCKS5 + labelEn: SOCKS5 Port + labelZh: SOCKS5 端口 + required: true + rule: paramPort + type: number + edit: true + - default: 8080 + envKey: PANEL_APP_PORT_HTTP_PROXY + labelEn: HTTP Proxy Port + labelZh: HTTP 代理端口 + required: true + rule: paramPort + type: number + edit: true + - default: 1080 + envKey: BIND_PORT + labelEn: Internal Bind Port + labelZh: 容器内部绑定端口 + required: true + rule: paramPort + type: number + edit: true + - default: 0 + envKey: ROTATE_INTERVAL_MINUTES + labelEn: Rotate Interval Minutes + labelZh: 轮换间隔(分钟) + required: true + type: number + edit: true + - default: https://cloudflare.com/cdn-cgi/trace + envKey: TEST_URL + labelEn: Probe URL + labelZh: 探测 URL + required: true + type: text + edit: true + - default: "" + envKey: SOCKS_USER + labelEn: SOCKS Username + labelZh: SOCKS 用户名 + required: false + type: text + edit: true + - default: "" + envKey: SOCKS_PASS + labelEn: SOCKS Password + labelZh: SOCKS 密码 + required: false + type: text + edit: true + - default: "" + envKey: ENDPOINT_IP + labelEn: WARP Endpoint + labelZh: WARP 终结点 + required: false + type: text + edit: true + - default: "" + envKey: GH_PROXY + labelEn: wgcf Download Proxy + labelZh: wgcf 下载代理 + required: false + type: text + edit: true + - default: "" + envKey: GITHUB_TOKEN + labelEn: GitHub Token + labelZh: GitHub Token + required: false + type: text + edit: true + - default: 100.64.0.0/10 + envKey: TAILSCALE_CIDR + labelEn: Tailscale Return Route CIDR + labelZh: Tailscale 回程路由 CIDR + required: true + type: text + edit: true + - default: 1280 + envKey: MTU + labelEn: WireGuard MTU + labelZh: WireGuard MTU + required: true + type: number + edit: true + - default: "" + envKey: WARP_WGCF_CONF + labelEn: WireGuard Config Content + labelZh: WireGuard 配置内容 + required: false + type: text + edit: true + - default: Asia/Shanghai + envKey: TZ + labelEn: Timezone + labelZh: 时区 + required: true + type: text + edit: true + - default: ./data + envKey: APP_DATA_DIR_1 + labelEn: WireGuard Data Directory + labelZh: WireGuard 数据目录 + required: true + type: text + edit: true diff --git a/apps/microwarp/rotator-http-latest/docker-compose.yml b/apps/microwarp/rotator-http-latest/docker-compose.yml new file mode 100644 index 000000000..2fec22c49 --- /dev/null +++ b/apps/microwarp/rotator-http-latest/docker-compose.yml @@ -0,0 +1,56 @@ +services: + microwarp: + image: "ghcr.io/ccbkkb/microwarp:latest" + container_name: ${CONTAINER_NAME} + labels: + createdBy: "Apps" + ports: + - "${PANEL_APP_PORT_SOCKS5}:${BIND_PORT}" + environment: + - TZ=${TZ} + - BIND_ADDR=0.0.0.0 + - BIND_PORT=${BIND_PORT} + - ROTATE_INTERVAL_MINUTES=${ROTATE_INTERVAL_MINUTES} + - TEST_URL=${TEST_URL} + - SOCKS_USER=${SOCKS_USER:-} + - SOCKS_PASS=${SOCKS_PASS:-} + - ENDPOINT_IP=${ENDPOINT_IP:-} + - GH_PROXY=${GH_PROXY:-} + - GITHUB_TOKEN=${GITHUB_TOKEN:-} + - TAILSCALE_CIDR=${TAILSCALE_CIDR:-100.64.0.0/10} + - MTU=${MTU} + - WARP_WGCF_CONF=${WARP_WGCF_CONF:-} + cap_add: + - NET_ADMIN + - SYS_MODULE + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + volumes: + - "${APP_DATA_DIR_1}:/etc/wireguard" + - "./rotate.sh:/usr/local/bin/rotate.sh:ro" + restart: always + command: ["/bin/sh", "/usr/local/bin/rotate.sh"] + networks: + - 1panel-network + + http-proxy: + image: "gogost/gost:latest" + container_name: ${CONTAINER_NAME}-http + labels: + createdBy: "Apps" + depends_on: + - microwarp + command: + - "-L" + - "http://0.0.0.0:8080" + - "-F" + - "socks5://microwarp:${BIND_PORT}" + ports: + - "${PANEL_APP_PORT_HTTP_PROXY}:8080" + restart: always + networks: + - 1panel-network + +networks: + 1panel-network: + external: true diff --git a/apps/microwarp/rotator-http-latest/rotate.sh b/apps/microwarp/rotator-http-latest/rotate.sh new file mode 100644 index 000000000..d6e995c61 --- /dev/null +++ b/apps/microwarp/rotator-http-latest/rotate.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env sh +set -eu + +INTERVAL_MINUTES="${ROTATE_INTERVAL_MINUTES:-0}" +TEST_URL="${TEST_URL:-https://cloudflare.com/cdn-cgi/trace}" +SOCKS_ADDR="127.0.0.1:${BIND_PORT:-1080}" +WG_DIR="/etc/wireguard" +WG_CONF="${WG_DIR}/wg0.conf" +FIXED_CONFIG="${WARP_WGCF_CONF:-}" +LOG_PREFIX="[microwarp]" +ENTRY_PID="" + +log() { + echo "${LOG_PREFIX} $*" +} + +is_non_negative_int() { + case "$1" in + ''|*[!0-9]*) + return 1 + ;; + *) + return 0 + ;; + esac +} + +probe_ip() { + if ! command -v curl >/dev/null 2>&1; then + return 0 + fi + curl --max-time 20 --socks5-hostname "$SOCKS_ADDR" "$TEST_URL" 2>/dev/null | sed -n '1,6p' +} + +inject_fixed_config() { + if [ -z "$FIXED_CONFIG" ]; then + return 0 + fi + mkdir -p "$WG_DIR" + printf '%s\n' "$FIXED_CONFIG" > "$WG_CONF" + chmod 600 "$WG_CONF" || true + log "wg0.conf injected from WARP_WGCF_CONF" +} + +wait_for_proxy() { + attempts=0 + while [ "$attempts" -lt 30 ]; do + if [ -n "$ENTRY_PID" ] && ! kill -0 "$ENTRY_PID" 2>/dev/null; then + wait "$ENTRY_PID" || true + return 1 + fi + + if probe_output="$(probe_ip)"; then + if [ -n "$probe_output" ]; then + printf '%s\n' "$probe_output" + return 0 + fi + fi + + attempts=$((attempts + 1)) + sleep 2 + done + return 1 +} + +stop_runtime() { + if [ -n "$ENTRY_PID" ] && kill -0 "$ENTRY_PID" 2>/dev/null; then + kill "$ENTRY_PID" 2>/dev/null || true + wait "$ENTRY_PID" || true + fi + ENTRY_PID="" +} + +teardown_for_rotation() { + stop_runtime + if ip link show wg0 >/dev/null 2>&1; then + wg-quick down wg0 >/dev/null 2>&1 || true + fi + rm -f "$WG_CONF" "$WG_DIR/wgcf-account.toml" "$WG_DIR/wgcf-profile.conf" "$WG_DIR/extra.env" +} + +start_runtime() { + inject_fixed_config + log "starting MicroWARP runtime" + /app/entrypoint.sh & + ENTRY_PID=$! + if probe_output="$(wait_for_proxy)"; then + printf '%s\n' "$probe_output" + return 0 + fi + log "runtime did not become ready in time" + return 1 +} + +on_signal() { + log "received stop signal" + stop_runtime + exit 0 +} + +main() { + interval="$INTERVAL_MINUTES" + if ! is_non_negative_int "$interval"; then + log "invalid ROTATE_INTERVAL_MINUTES=${interval}, fallback to 0" + interval=0 + fi + + if [ -n "$FIXED_CONFIG" ] && [ "$interval" -gt 0 ]; then + log "WARP_WGCF_CONF is set, scheduled rotation disabled because the config is pinned" + interval=0 + fi + + trap on_signal INT TERM + + if ! start_runtime; then + exit 1 + fi + + if [ "$interval" -eq 0 ]; then + log "scheduled rotation disabled" + wait "$ENTRY_PID" + exit $? + fi + + log "scheduled WARP identity rebuild enabled every ${interval} minute(s)" + while true; do + sleep "$((interval * 60))" + log "trigger scheduled WARP identity rebuild" + if ! rotate_output="$(teardown_for_rotation; start_runtime)"; then + log "rotation failed" + exit 1 + fi + printf '%s\n' "$rotate_output" + done +} + +main "$@" diff --git a/apps/microwarp/rotator-http-latest/scripts/init.sh b/apps/microwarp/rotator-http-latest/scripts/init.sh new file mode 100644 index 000000000..cfef1b85e --- /dev/null +++ b/apps/microwarp/rotator-http-latest/scripts/init.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" diff --git a/apps/microwarp/rotator-http-latest/scripts/uninstall.sh b/apps/microwarp/rotator-http-latest/scripts/uninstall.sh new file mode 100755 index 000000000..ab8a8d674 --- /dev/null +++ b/apps/microwarp/rotator-http-latest/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down --volumes diff --git a/apps/microwarp/rotator-http-latest/scripts/upgrade.sh b/apps/microwarp/rotator-http-latest/scripts/upgrade.sh new file mode 100644 index 000000000..e17b81f76 --- /dev/null +++ b/apps/microwarp/rotator-http-latest/scripts/upgrade.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" +exit 0 diff --git a/apps/microwarp/rotator-latest/.env.sample b/apps/microwarp/rotator-latest/.env.sample new file mode 100644 index 000000000..923b482db --- /dev/null +++ b/apps/microwarp/rotator-latest/.env.sample @@ -0,0 +1,15 @@ +CONTAINER_NAME=microwarp +PANEL_APP_PORT_SOCKS5=1080 +BIND_PORT=1080 +ROTATE_INTERVAL_MINUTES=0 +TEST_URL=https://cloudflare.com/cdn-cgi/trace +SOCKS_USER= +SOCKS_PASS= +ENDPOINT_IP= +GH_PROXY= +GITHUB_TOKEN= +TAILSCALE_CIDR=100.64.0.0/10 +MTU=1280 +WARP_WGCF_CONF= +TZ=Asia/Shanghai +APP_DATA_DIR_1=./data diff --git a/apps/microwarp/rotator-latest/data.yml b/apps/microwarp/rotator-latest/data.yml new file mode 100644 index 000000000..a45b208a2 --- /dev/null +++ b/apps/microwarp/rotator-latest/data.yml @@ -0,0 +1,102 @@ +additionalProperties: + formFields: + - default: 1080 + envKey: PANEL_APP_PORT_SOCKS5 + labelEn: SOCKS5 Port + labelZh: SOCKS5 端口 + required: true + rule: paramPort + type: number + edit: true + - default: 1080 + envKey: BIND_PORT + labelEn: Internal Bind Port + labelZh: 容器内部绑定端口 + required: true + rule: paramPort + type: number + edit: true + - default: 0 + envKey: ROTATE_INTERVAL_MINUTES + labelEn: Rotate Interval Minutes + labelZh: 轮换间隔(分钟) + required: true + type: number + edit: true + - default: https://cloudflare.com/cdn-cgi/trace + envKey: TEST_URL + labelEn: Probe URL + labelZh: 探测 URL + required: true + type: text + edit: true + - default: "" + envKey: SOCKS_USER + labelEn: SOCKS Username + labelZh: SOCKS 用户名 + required: false + type: text + edit: true + - default: "" + envKey: SOCKS_PASS + labelEn: SOCKS Password + labelZh: SOCKS 密码 + required: false + type: text + edit: true + - default: "" + envKey: ENDPOINT_IP + labelEn: WARP Endpoint + labelZh: WARP 终结点 + required: false + type: text + edit: true + - default: "" + envKey: GH_PROXY + labelEn: wgcf Download Proxy + labelZh: wgcf 下载代理 + required: false + type: text + edit: true + - default: "" + envKey: GITHUB_TOKEN + labelEn: GitHub Token + labelZh: GitHub Token + required: false + type: text + edit: true + - default: 100.64.0.0/10 + envKey: TAILSCALE_CIDR + labelEn: Tailscale Return Route CIDR + labelZh: Tailscale 回程路由 CIDR + required: true + type: text + edit: true + - default: 1280 + envKey: MTU + labelEn: WireGuard MTU + labelZh: WireGuard MTU + required: true + type: number + edit: true + - default: "" + envKey: WARP_WGCF_CONF + labelEn: WireGuard Config Content + labelZh: WireGuard 配置内容 + required: false + type: text + edit: true + - default: Asia/Shanghai + envKey: TZ + labelEn: Timezone + labelZh: 时区 + required: true + type: text + edit: true + - default: ./data + envKey: APP_DATA_DIR_1 + labelEn: WireGuard Data Directory + labelZh: WireGuard 数据目录 + required: true + type: text + edit: true diff --git a/apps/microwarp/rotator-latest/docker-compose.yml b/apps/microwarp/rotator-latest/docker-compose.yml new file mode 100644 index 000000000..bee627cab --- /dev/null +++ b/apps/microwarp/rotator-latest/docker-compose.yml @@ -0,0 +1,38 @@ +services: + microwarp: + image: "ghcr.io/ccbkkb/microwarp:latest" + container_name: ${CONTAINER_NAME} + labels: + createdBy: "Apps" + ports: + - "${PANEL_APP_PORT_SOCKS5}:${BIND_PORT}" + environment: + - TZ=${TZ} + - BIND_ADDR=0.0.0.0 + - BIND_PORT=${BIND_PORT} + - ROTATE_INTERVAL_MINUTES=${ROTATE_INTERVAL_MINUTES} + - TEST_URL=${TEST_URL} + - SOCKS_USER=${SOCKS_USER:-} + - SOCKS_PASS=${SOCKS_PASS:-} + - ENDPOINT_IP=${ENDPOINT_IP:-} + - GH_PROXY=${GH_PROXY:-} + - GITHUB_TOKEN=${GITHUB_TOKEN:-} + - TAILSCALE_CIDR=${TAILSCALE_CIDR:-100.64.0.0/10} + - MTU=${MTU} + - WARP_WGCF_CONF=${WARP_WGCF_CONF:-} + cap_add: + - NET_ADMIN + - SYS_MODULE + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + volumes: + - "${APP_DATA_DIR_1}:/etc/wireguard" + - "./rotate.sh:/usr/local/bin/rotate.sh:ro" + restart: always + command: ["/bin/sh", "/usr/local/bin/rotate.sh"] + networks: + - 1panel-network + +networks: + 1panel-network: + external: true diff --git a/apps/microwarp/rotator-latest/rotate.sh b/apps/microwarp/rotator-latest/rotate.sh new file mode 100644 index 000000000..d6e995c61 --- /dev/null +++ b/apps/microwarp/rotator-latest/rotate.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env sh +set -eu + +INTERVAL_MINUTES="${ROTATE_INTERVAL_MINUTES:-0}" +TEST_URL="${TEST_URL:-https://cloudflare.com/cdn-cgi/trace}" +SOCKS_ADDR="127.0.0.1:${BIND_PORT:-1080}" +WG_DIR="/etc/wireguard" +WG_CONF="${WG_DIR}/wg0.conf" +FIXED_CONFIG="${WARP_WGCF_CONF:-}" +LOG_PREFIX="[microwarp]" +ENTRY_PID="" + +log() { + echo "${LOG_PREFIX} $*" +} + +is_non_negative_int() { + case "$1" in + ''|*[!0-9]*) + return 1 + ;; + *) + return 0 + ;; + esac +} + +probe_ip() { + if ! command -v curl >/dev/null 2>&1; then + return 0 + fi + curl --max-time 20 --socks5-hostname "$SOCKS_ADDR" "$TEST_URL" 2>/dev/null | sed -n '1,6p' +} + +inject_fixed_config() { + if [ -z "$FIXED_CONFIG" ]; then + return 0 + fi + mkdir -p "$WG_DIR" + printf '%s\n' "$FIXED_CONFIG" > "$WG_CONF" + chmod 600 "$WG_CONF" || true + log "wg0.conf injected from WARP_WGCF_CONF" +} + +wait_for_proxy() { + attempts=0 + while [ "$attempts" -lt 30 ]; do + if [ -n "$ENTRY_PID" ] && ! kill -0 "$ENTRY_PID" 2>/dev/null; then + wait "$ENTRY_PID" || true + return 1 + fi + + if probe_output="$(probe_ip)"; then + if [ -n "$probe_output" ]; then + printf '%s\n' "$probe_output" + return 0 + fi + fi + + attempts=$((attempts + 1)) + sleep 2 + done + return 1 +} + +stop_runtime() { + if [ -n "$ENTRY_PID" ] && kill -0 "$ENTRY_PID" 2>/dev/null; then + kill "$ENTRY_PID" 2>/dev/null || true + wait "$ENTRY_PID" || true + fi + ENTRY_PID="" +} + +teardown_for_rotation() { + stop_runtime + if ip link show wg0 >/dev/null 2>&1; then + wg-quick down wg0 >/dev/null 2>&1 || true + fi + rm -f "$WG_CONF" "$WG_DIR/wgcf-account.toml" "$WG_DIR/wgcf-profile.conf" "$WG_DIR/extra.env" +} + +start_runtime() { + inject_fixed_config + log "starting MicroWARP runtime" + /app/entrypoint.sh & + ENTRY_PID=$! + if probe_output="$(wait_for_proxy)"; then + printf '%s\n' "$probe_output" + return 0 + fi + log "runtime did not become ready in time" + return 1 +} + +on_signal() { + log "received stop signal" + stop_runtime + exit 0 +} + +main() { + interval="$INTERVAL_MINUTES" + if ! is_non_negative_int "$interval"; then + log "invalid ROTATE_INTERVAL_MINUTES=${interval}, fallback to 0" + interval=0 + fi + + if [ -n "$FIXED_CONFIG" ] && [ "$interval" -gt 0 ]; then + log "WARP_WGCF_CONF is set, scheduled rotation disabled because the config is pinned" + interval=0 + fi + + trap on_signal INT TERM + + if ! start_runtime; then + exit 1 + fi + + if [ "$interval" -eq 0 ]; then + log "scheduled rotation disabled" + wait "$ENTRY_PID" + exit $? + fi + + log "scheduled WARP identity rebuild enabled every ${interval} minute(s)" + while true; do + sleep "$((interval * 60))" + log "trigger scheduled WARP identity rebuild" + if ! rotate_output="$(teardown_for_rotation; start_runtime)"; then + log "rotation failed" + exit 1 + fi + printf '%s\n' "$rotate_output" + done +} + +main "$@" diff --git a/apps/microwarp/rotator-latest/scripts/init.sh b/apps/microwarp/rotator-latest/scripts/init.sh new file mode 100644 index 000000000..cfef1b85e --- /dev/null +++ b/apps/microwarp/rotator-latest/scripts/init.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" diff --git a/apps/microwarp/rotator-latest/scripts/uninstall.sh b/apps/microwarp/rotator-latest/scripts/uninstall.sh new file mode 100755 index 000000000..ab8a8d674 --- /dev/null +++ b/apps/microwarp/rotator-latest/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down --volumes diff --git a/apps/microwarp/rotator-latest/scripts/upgrade.sh b/apps/microwarp/rotator-latest/scripts/upgrade.sh new file mode 100644 index 000000000..e17b81f76 --- /dev/null +++ b/apps/microwarp/rotator-latest/scripts/upgrade.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail + +app_data_dir="${APP_DATA_DIR_1:-}" +if [[ -z "${app_data_dir}" && -f ./.env ]]; then + app_data_dir="$(sed -n 's/^APP_DATA_DIR_1=\"\{0,1\}\(.*\)\"\{0,1\}$/\1/p' ./.env | tail -n 1)" +fi +app_data_dir="${app_data_dir:-./data}" + +mkdir -p "${app_data_dir}" +exit 0