Add microwarp official and rotator variants (#4535)

This commit is contained in:
okxlin
2026-07-05 04:29:18 +08:00
committed by GitHub
parent 7978b863c9
commit 83ec0bc2b2
29 changed files with 1083 additions and 0 deletions
+51
View File
@@ -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
+32
View File
@@ -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
+14
View File
@@ -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
+96
View File
@@ -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
@@ -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
@@ -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}"
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose down --volumes
@@ -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
+13
View File
@@ -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
+88
View File
@@ -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
+34
View File
@@ -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
+10
View File
@@ -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}"
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose down --volumes
+11
View File
@@ -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
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

@@ -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
+110
View File
@@ -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
@@ -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
@@ -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 "$@"
@@ -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}"
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose down --volumes
@@ -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
+15
View File
@@ -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
+102
View File
@@ -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
@@ -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
+137
View File
@@ -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 "$@"
@@ -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}"
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose down --volumes
@@ -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