diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..ee2873b --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,48 @@ +**Purpose**: 让 AI 编码代理快速在本仓库中上手,列出关键文件、构建/调试命令、项目约定和注意事项。 + +**Big Picture**: +- **核心二进制(后端)**: Go 源码为主,入口/关键文件为 `ech-workers.go`、`go.mod`。构建脚本在仓库根目录。 +- **平台 GUI/前端**: 每个平台放在独立目录,分别为 `ech-workers-linux-gui-src/`、`ech-workers-mac-gui-src/`、`ech-workers-windows-gui-src/`、`ech-workers-android-gui-src/`。它们各自包含自己的 README 和构建脚本(例如 `ech_worker_gui.py`、`gui.py`、`build.bat`)。 +- **原生/JNI 代码(Android)**: 位于 `ech-workers-android-gui-src/src/jni/hev-socks5-tunnel/`,包含 `Makefile`、`Android.mk`、`Application.mk`、`conf/main.yml` 等原生构建资源。 + +**重要文件/目录(快速引用)**: +- `gobuild.sh` — 全平台 Go 编译脚本(会在 `build/` 下产出二进制)。 +- `build.sh` — 发布/打包脚本,包含多个跨编译/打包函数(注意:脚本中大量从 OpenList 拷贝的逻辑,修改前请谨慎)。 +- `README.md`(仓库根)— 包含运行示例(例如 `ech-win ...`)。 +- `ech-workers-*-gui-src/` — 平台 GUI 源码和本地 README(请先阅读每个子目录下的 README)。 +- `ech-workers-android-gui-src/src/jni/hev-socks5-tunnel/` — C 源、头文件与 Android NDK 构建文件。 + +**常用命令(可直接复制执行)**: +``` +# 构建所有预设平台(gobuild.sh 会创建 build/ 下的产物) +./gobuild.sh + +# 运行发布脚本(包含多平台/交叉编译与打包逻辑) +./build.sh + +# 运行本地 Go 二进制(在未交叉编译时,可用 go run 测试) +go run . +``` + +注意:`gobuild.sh` 与 `build.sh` 都使用 `go build` 并设置 `GOOS/GOARCH`,需要在容器/机器上安装 `go`。`build.sh` 的某些步骤会下载外部工具链、需要 `sudo`、`curl`、`unzip`、`jq` 等依赖。 + +**约定与模式(此项目的特定点)**: +- 二进制输出目录统一使用 `build/`。 +- 发布构建会通过 ldflags 注入版本信息(在 `build.sh` 中有 `builtAt`、`gitCommit`、`version` 三个变量),参考 `ldflags` 的设定不要随意改名。 +- Android JNI/本地库与 Go 代码分离:原生代码位于 `ech-workers-android-gui-src/src/jni/hev-socks5-tunnel/`,该目录包含自己的 `Makefile` 与 `Application.mk`,若需改动需按 NDK/Makefile 流程编译。 +- 多前端并存:不同平台的 GUI 不是共享同一构建流程,修改 GUI 功能时先在对应子目录内查 README 和脚本。 + +**修改/PR 指南(给 AI agent 的可执行建议)**: +- 修改核心 Go 代码:先运行 `go vet`、`go build` 或 `./gobuild.sh` 的单平台命令验证二进制能正常构建。 +- 修改发布脚本或交叉编译逻辑:谨慎,`build.sh` 中包含外部下载与重用的逻辑块(已注明为“OpenList 原版”)。若更改,请在 PR 描述中说明为何替换外部工具链或移除下载步骤。 +- 修改 Android JNI/C 代码:在更改后,先在有 NDK 的环境验证本地编译(参考目录 `ech-workers-android-gui-src/src/jni/hev-socks5-tunnel/` 中的 `Makefile`)。 + +**快速调查点(定位 bug/行为)**: +- 若需找程序入口/CLI参数:查看 `ech-workers.go`(或以 `_worker.js` 为辅助的脚本)。 +- 若需查运行示例:查看仓库根 `README.md` 中的 usage 与示例命令。 + +**不能仅凭 AI 自动修改的地方**: +- `build.sh` 中大量依赖外部二进制或工具链下载(会用到 GITHUB_TOKEN、sudo 等),自动化 修改可能破坏发布流水线。 +- Android NDK / JNI 构建和系统级交叉编译步骤,需要真实环境验证(AI 不应直接替换这些脚本而不标注风险)。 + +如果这份说明有遗漏或你希望我把某个子目录的构建/运行步骤展开成更详尽的检查清单(例如 Android NDK 本地编译步骤或 macOS GUI 打包说明),请告诉我想要先覆盖的目标平台/目录,我会继续补充并提交更新。 diff --git a/.github/workflows/build-armv7.yml b/.github/workflows/build-armv7.yml new file mode 100644 index 0000000..8d31ba0 --- /dev/null +++ b/.github/workflows/build-armv7.yml @@ -0,0 +1,821 @@ +name: 🔨 Build ARMv7 for Hi3798MV100 + +on: + push: + branches: [ main, master ] + tags: [ 'v*' ] # 标签触发时创建正式发布 + pull_request: + branches: [ main, master ] + workflow_dispatch: # 手动触发 + inputs: + version: + description: '自定义版本号 (如 v1.0.0)' + required: false + default: 'auto' + clean_build: + description: '清理构建缓存' + required: false + default: false + +env: + GO_VERSION: '1.21' + PROJECT_NAME: 'ech-workers' + BUILD_TARGET: 'hi3798mv100' + OUTPUT_DIR: 'artifacts' + CACHE_KEY: ${{ github.ref }} + +jobs: + build-check: + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + outputs: + should_build: ${{ steps.check.outputs.should_build }} + build_version: ${{ steps.version.outputs.build_version }} + + steps: + - name: 🔍 检查构建条件 + id: check + run: | + # 跳过文档和配置文件的变更 + if [[ "${{ github.event.head_commit.message }}" =~ ^(docs|chore|style) ]]; then + echo "::warning::跳过构建(仅文档/配置变更)" + echo "should_build=false" >> $GITHUB_OUTPUT + else + echo "should_build=true" >> $GITHUB_OUTPUT + fi + + - name: 🏷️ 确定版本号 + id: version + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.version }}" != "auto" ]]; then + VERSION="${{ github.event.inputs.version }}" + elif [[ "${{ github.ref }}" == refs/tags/* ]]; then + VERSION="${GITHUB_REF#refs/tags/}" + else + DATE=$(date +%Y%m%d) + COMMIT=${GITHUB_SHA:0:8} + VERSION="nightly-${DATE}-${COMMIT}" + fi + echo "版本号: $VERSION" + echo "build_version=$VERSION" >> $GITHUB_OUTPUT + + build-armv7: + runs-on: ubuntu-latest + needs: build-check + if: needs.build-check.outputs.should_build == 'true' + + strategy: + fail-fast: false + matrix: + build_type: [standard, static] + + steps: + - name: 📥 检出代码 + uses: actions/checkout@v4 + with: + repository: hhsw2015/ech_workers + fetch-depth: 0 + lfs: true + + - name: 🔧 设置 Go 环境 + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + cache-dependency-path: go.sum + + - name: 📦 初始化构建环境 + run: | + mkdir -p ${{ env.OUTPUT_DIR }} + echo "BUILD_DATE=$(date -u '+%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV + echo "GO_VERSION=$(go version | cut -d' ' -f3)" >> $GITHUB_ENV + + # 显示构建信息 + echo "📋 构建信息:" + echo "项目: ${{ env.PROJECT_NAME }}" + echo "目标设备: ${{ env.BUILD_TARGET }}" + echo "版本: ${{ needs.build-check.outputs.build_version }}" + echo "构建类型: ${{ matrix.build_type }}" + echo "Go版本: $(go version)" + + - name: 🛠️ 构建 ARMv7 版本 + id: build + run: | + set -e + + VERSION="${{ needs.build-check.outputs.build_version }}" + COMMIT=$(git rev-parse --short HEAD) + + echo "🚀 开始构建 ${{ matrix.build_type }} 版本..." + + # 设置构建参数 + if [ "${{ matrix.build_type }}" = "static" ]; then + LD_FLAGS="-w -s -extldflags \"-static\"" + OUTPUT_SUFFIX="-static" + CGO_ENABLED="0" + else + LD_FLAGS="-w -s" + OUTPUT_SUFFIX="" + CGO_ENABLED="1" + fi + + # 设置完整版本信息 + FULL_VERSION="${VERSION}+${COMMIT}" + + # 交叉编译命令 + GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=$CGO_ENABLED \ + go build \ + -v \ + -trimpath \ + -o "${{ env.OUTPUT_DIR }}/${{ env.PROJECT_NAME }}-armv7${OUTPUT_SUFFIX}" \ + -ldflags="${LD_FLAGS} \ + -X 'main.Version=$FULL_VERSION' \ + -X 'main.BuildTime=${{ env.BUILD_DATE }}' \ + -X 'main.GoVersion=${{ env.GO_VERSION }}' \ + -X 'main.Commit=$COMMIT'" \ + . + + echo "✅ 构建完成" + + # 输出构建信息 + echo "build_output=${{ env.OUTPUT_DIR }}/${{ env.PROJECT_NAME }}-armv7${OUTPUT_SUFFIX}" >> $GITHUB_OUTPUT + echo "build_suffix=${OUTPUT_SUFFIX}" >> $GITHUB_OUTPUT + + - name: 🔍 验证二进制文件 + run: | + echo "🔍 验证构建结果:" + ls -lh ${{ env.OUTPUT_DIR }}/ + + FILE="${{ steps.build.outputs.build_output }}" + echo "📄 文件信息:" + file "$FILE" + + echo "📦 文件大小:" + ls -lh "$FILE" + + echo "🔢 检查 ELF 头部:" + readelf -h "$FILE" | grep -E "(机器|类型|入口点)" || true + + - name: 🧪 QEMU 模拟测试 + run: | + echo "🧪 使用 QEMU 进行基本测试..." + sudo apt-get update + sudo apt-get install -y qemu-user-static qemu-user + + TEST_BIN="${{ steps.build.outputs.build_output }}" + chmod +x "$TEST_BIN" + + echo "测试帮助命令:" + timeout 5s qemu-arm-static "$TEST_BIN" --help 2>&1 | head -20 || \ + echo "⚠️ QEMU 测试可能受限,继续构建流程..." + + echo "✅ QEMU 测试完成" + + - name: 🔒 创建校验和 + run: | + echo "🔒 生成文件校验和..." + + BIN_FILE="${{ steps.build.outputs.build_output }}" + BASE_NAME=$(basename "$BIN_FILE") + + cd ${{ env.OUTPUT_DIR }} + + # 创建多种校验和 + sha256sum "$BASE_NAME" > "$BASE_NAME.sha256" + sha1sum "$BASE_NAME" > "$BASE_NAME.sha1" + md5sum "$BASE_NAME" > "$BASE_NAME.md5" + + # 创建 BLAKE3 校验和(更现代) + if command -v b3sum &> /dev/null; then + sudo apt-get install -y b3sum + b3sum "$BASE_NAME" > "$BASE_NAME.b3sum" + fi + + echo "📋 校验和列表:" + cat *.sha256 + cat *.sha1 + cat *.md5 + [ -f *.b3sum ] && cat *.b3sum || true + + - name: 📄 创建版本信息文件 + run: | + echo "📝 创建版本信息..." + + cat > "${{ env.OUTPUT_DIR }}/BUILD_INFO.txt" << EOF +# ${{ env.PROJECT_NAME }} - ${{ env.BUILD_TARGET }} 构建信息 +构建时间: ${{ env.BUILD_DATE }} +版本: ${{ needs.build-check.outputs.build_version }} +提交: $(git rev-parse HEAD) +分支: ${{ github.ref_name }} +构建类型: ${{ matrix.build_type }} + +## 环境信息 +GitHub Actions URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} +触发事件: ${{ github.event_name }} +触发者: ${{ github.actor }} + +## 构建配置 +Go 版本: ${{ env.GO_VERSION }} +操作系统: $(uname -s) +架构: $(uname -m) +构建参数: GOOS=linux GOARCH=arm GOARM=7 + +## 文件信息 +二进制文件: $(basename ${{ steps.build.outputs.build_output }}) +文件大小: $(du -h ${{ steps.build.outputs.build_output }} | cut -f1) +ELF 类型: $(file ${{ steps.build.outputs.build_output }} | cut -d':' -f2-) + +## 依赖版本 +$(go version) +$(go list -m all | grep -E "(ech|workers|cloudflare)" || echo "无特殊依赖") +EOF + + echo "✅ 版本信息文件已创建" + + - name: 📦 打包构建结果 + run: | + echo "📦 打包构建结果..." + + VERSION="${{ needs.build-check.outputs.build_version }}" + BUILD_TYPE="${{ matrix.build_type }}" + TIMESTAMP=$(date +%Y%m%d_%H%M%S) + + cd ${{ env.OUTPUT_DIR }} + + # 创建打包目录 + PACKAGE_DIR="${{ env.PROJECT_NAME }}-${VERSION}-armv7-${BUILD_TYPE}" + mkdir -p "$PACKAGE_DIR" + + # 复制所有文件 + cp ${{ env.PROJECT_NAME }}-armv7${steps.build.outputs.build_suffix}* "$PACKAGE_DIR/" + cp BUILD_INFO.txt "$PACKAGE_DIR/" + + # 创建安装脚本 + cat > "$PACKAGE_DIR/install.sh" << 'EOF' +#!/bin/bash +# ech-workers Hi3798MV100 ARMv7 安装脚本 +# 版本: ${{ needs.build-check.outputs.build_version }} + +set -e + +# 配置参数 +INSTALL_DIR="/usr/local/bin" +SERVICE_DIR="/etc/systemd/system" +CONFIG_DIR="/etc/ech-workers" +LOG_DIR="/var/log/ech-workers" +TEMP_DIR="/tmp/ech-workers-install" + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# 日志函数 +log() { + echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" +} + +success() { + echo -e "${GREEN}✓${NC} $1" +} + +warn() { + echo -e "${YELLOW}⚠${NC} $1" +} + +error() { + echo -e "${RED}✗${NC} $1" + exit 1 +} + +# 显示横幅 +show_banner() { + echo "╔══════════════════════════════════════════════════════════╗" + echo "║ ech-workers Hi3798MV100 ARMv7 安装程序 ║" + echo "║ 版本: ${{ needs.build-check.outputs.build_version }} ║" + echo "╚══════════════════════════════════════════════════════════╝" + echo "" +} + +# 检查系统 +check_system() { + log "检查系统环境..." + + # 检查架构 + local arch=$(uname -m) + case "$arch" in + armv7l|armhf) + success "检测到 ARMv7 架构 ($arch)" + ;; + *) + warn "检测到架构: $arch (预期: ARMv7)" + read -p "是否继续?[y/N]: " -n 1 -r + echo + [[ $REPLY =~ ^[Yy]$ ]] || error "安装中止" + ;; + esac + + # 检查内存 + local mem=$(free -m | awk '/^Mem:/{print $2}') + if [ "$mem" -lt 128 ]; then + warn "系统内存较低 ($mem MB),建议至少有 256MB 内存" + fi + + # 检查磁盘空间 + local disk=$(df -m / | awk 'NR==2 {print $4}') + if [ "$disk" -lt 50 ]; then + warn "磁盘空间紧张 ($disk MB 可用)" + fi +} + +# 安装依赖 +install_dependencies() { + log "检查系统依赖..." + + local deps_missing=false + + # 检查必需的命令 + for cmd in curl systemctl ip; do + if ! command -v "$cmd" &> /dev/null; then + warn "缺少命令: $cmd" + deps_missing=true + fi + done + + if [ "$deps_missing" = true ]; then + log "尝试安装依赖..." + + if command -v apt-get &> /dev/null; then + apt-get update + apt-get install -y curl iproute2 ca-certificates || warn "部分依赖安装失败" + elif command -v yum &> /dev/null; then + yum install -y curl iproute ca-certificates || warn "部分依赖安装失败" + elif command -v opkg &> /dev/null; then + opkg update + opkg install curl ca-certificates || warn "部分依赖安装失败" + else + warn "无法自动安装依赖,请手动安装" + fi + fi +} + +# 安装主程序 +install_binary() { + log "安装 ech-workers 主程序..." + + # 创建安装目录 + mkdir -p "$INSTALL_DIR" + + # 备份旧版本 + local binary_path="$INSTALL_DIR/ech-workers" + if [ -f "$binary_path" ]; then + local backup_path="${binary_path}.backup.$(date +%Y%m%d_%H%M%S)" + cp "$binary_path" "$backup_path" + success "旧版本已备份到: $backup_path" + fi + + # 查找二进制文件 + local binary_source + for file in ech-workers-*; do + if [[ "$file" == ech-workers-* && ! "$file" == *.* ]]; then + binary_source="$file" + break + fi + done + + if [ -z "$binary_source" ]; then + error "找不到可安装的二进制文件" + fi + + # 安装新版本 + cp "$binary_source" "$binary_path" + chmod +x "$binary_path" + chown root:root "$binary_path" + + # 验证安装 + if [ -x "$binary_path" ]; then + local version_info=$("$binary_path" --help 2>&1 | head -5) + success "程序安装成功" + echo "版本信息:" + echo "$version_info" | sed 's/^/ /' + else + error "程序安装失败" + fi +} + +# 创建配置文件 +create_config() { + log "创建配置文件..." + + mkdir -p "$CONFIG_DIR" + + # 主配置文件 + cat > "$CONFIG_DIR/config.env" << 'CONFIGEOF' +# ech-workers 配置文件 +# 生成时间: $(date) + +# 基本配置 +LISTEN_ADDR="0.0.0.0:30000" +WORKER_URL="your-worker.workers.dev:443" +TOKEN="your_token_here" + +# 高级配置 (可选) +# FALLBACK_PROXY="" +# PREFERRED_IP="" +# DNS_SERVER="223.5.5.5/dns-query" +# ECH_DOMAIN="cloudflare.ech.com" + +# 性能调整 +# CONNECTION_LIMIT=100 +# TIMEOUT=30 +# BUFFER_SIZE=4096 +CONFIGEOF + + # 创建示例启动脚本 + cat > "$CONFIG_DIR/start-example.sh" << 'EXAMPLEEOF' +#!/bin/bash +# ech-workers 启动示例 + +source /etc/ech-workers/config.env + +# 构建命令行参数 +ARGS="-l \"\$LISTEN_ADDR\" -f \"\$WORKER_URL\" -token \"\$TOKEN\"" + +[ -n "\$FALLBACK_PROXY" ] && ARGS="\$ARGS -pyip \"\$FALLBACK_PROXY\"" +[ -n "\$PREFERRED_IP" ] && ARGS="\$ARGS -ip \"\$PREFERRED_IP\"" +[ -n "\$DNS_SERVER" ] && ARGS="\$ARGS -dns \"\$DNS_SERVER\"" +[ -n "\$ECH_DOMAIN" ] && ARGS="\$ARGS -ech \"\$ECH_DOMAIN\"" + +echo "启动命令:" +echo "/usr/local/bin/ech-workers \$ARGS" + +# 实际执行(取消注释以启用) +# exec /usr/local/bin/ech-workers \$ARGS +EXAMPLEEOF + + chmod +x "$CONFIG_DIR/start-example.sh" + chmod 600 "$CONFIG_DIR/config.env" + + success "配置文件已创建: $CONFIG_DIR/" +} + +# 创建 systemd 服务 +create_systemd_service() { + log "创建 systemd 服务..." + + local service_file="$SERVICE_DIR/ech-workers.service" + + cat > "$service_file" << SERVICEEOF +[Unit] +Description=ech-workers Proxy Service (Hi3798MV100) +Description=基于 Cloudflare Workers 的代理服务 +After=network.target network-online.target +Wants=network-online.target +Documentation=https://github.com/${{ github.repository }} +Before=syslog.target + +[Service] +Type=simple +User=root +Group=root +WorkingDirectory=/tmp + +# 从配置文件读取参数 +EnvironmentFile=-/etc/ech-workers/config.env + +# 启动命令 +ExecStart=/usr/local/bin/ech-workers \\ + -l \${LISTEN_ADDR:-0.0.0.0:30000} \\ + -f \${WORKER_URL} \\ + -token \${TOKEN} \\ + \${FALLBACK_PROXY:+-pyip "\${FALLBACK_PROXY}"} \\ + \${PREFERRED_IP:+-ip "\${PREFERRED_IP}"} \\ + \${DNS_SERVER:+-dns "\${DNS_SERVER}"} \\ + \${ECH_DOMAIN:+-ech "\${ECH_DOMAIN}"} + +# 重启策略 +Restart=on-failure +RestartSec=10 +RestartPreventExitStatus=0 +StartLimitInterval=60 +StartLimitBurst=3 + +# 资源限制 +LimitNOFILE=65536 +MemoryMax=256M +MemoryHigh=200M +CPUQuota=80% + +# 安全设置 +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +PrivateDevices=true +ProtectKernelTunables=true +ProtectKernelModules=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_INET AF_INET6 +RestrictNamespaces=true +RestrictRealtime=true +SystemCallArchitectures=native +SystemCallFilter=@system-service + +# 日志设置 +StandardOutput=journal +StandardError=journal +SyslogIdentifier=ech-workers +LogLevelMax=info + +# 环境变量 +Environment="GODEBUG=netdns=go" +Environment="TZ=Asia/Shanghai" + +[Install] +WantedBy=multi-user.target +SERVICEEOF + + # 重新加载 systemd + systemctl daemon-reload + + success "systemd 服务文件已创建: $service_file" +} + +# 设置日志轮转 +setup_logrotate() { + log "设置日志轮转..." + + cat > /etc/logrotate.d/ech-workers << 'LOGROTATE' +/var/log/ech-workers/*.log { + daily + rotate 7 + compress + delaycompress + missingok + notifempty + create 0640 root root + sharedscripts + postrotate + systemctl try-reload-or-restart ech-workers >/dev/null 2>&1 || true + endscript +} +LOGROTATE + + # 创建日志目录 + mkdir -p "$LOG_DIR" + chmod 750 "$LOG_DIR" + + success "日志轮转配置完成" +} + +# 防火墙配置 +configure_firewall() { + log "配置防火墙..." + + local port=${LISTEN_ADDR##*:} + + if command -v ufw &> /dev/null; then + ufw allow "$port/tcp" + ufw reload + success "UFW 防火墙已配置 (端口: $port)" + elif command -v iptables &> /dev/null; then + iptables -A INPUT -p tcp --dport "$port" -j ACCEPT + success "iptables 规则已添加 (端口: $port)" + elif command -v firewall-cmd &> /dev/null; then + firewall-cmd --permanent --add-port="$port/tcp" + firewall-cmd --reload + success "firewalld 已配置 (端口: $port)" + else + warn "未找到支持的防火墙工具,请手动开放端口 $port" + fi +} + +# 创建管理脚本 +create_management_scripts() { + log "创建管理脚本..." + + # 状态检查脚本 + cat > "/usr/local/bin/ech-workers-status" << 'STATUSEOF' +#!/bin/bash +# ech-workers 状态检查脚本 + +SERVICE="ech-workers" +PORT=$(grep -oP 'LISTEN_ADDR=".*:\K\d+' /etc/ech-workers/config.env 2>/dev/null || echo "30000") + +echo "🔍 ech-workers 状态检查" +echo "========================" + +# 检查服务状态 +if systemctl is-active --quiet "$SERVICE"; then + echo "✅ 服务状态: 运行中" + echo " PID: $(systemctl show -p MainPID "$SERVICE" | cut -d= -f2)" +else + echo "❌ 服务状态: 未运行" +fi + +# 检查端口监听 +if ss -tln | grep -q ":$PORT "; then + echo "✅ 端口监听: 正常 (端口: $PORT)" +else + echo "❌ 端口监听: 异常" +fi + +# 检查配置文件 +if [ -f "/etc/ech-workers/config.env" ]; then + echo "✅ 配置文件: 存在" +else + echo "⚠️ 配置文件: 缺失" +fi + +# 测试连接(可选) +if [ "$1" == "--test" ]; then + echo -n "测试代理连接: " + if timeout 5 curl -s --proxy "http://127.0.0.1:$PORT" http://httpbin.org/ip >/dev/null; then + echo "✅ 成功" + else + echo "❌ 失败" + fi +fi +STATUSEOF + + chmod +x "/usr/local/bin/ech-workers-status" + + success "管理脚本已创建" +} + +# 显示安装完成信息 +show_completion() { + echo "" + echo "╔══════════════════════════════════════════════════════════╗" + echo "║ 安装完成! ║" + echo "╚══════════════════════════════════════════════════════════╝" + echo "" + echo "📋 安装摘要:" + echo " • 程序文件: $INSTALL_DIR/ech-workers" + echo " • 配置文件: $CONFIG_DIR/" + echo " • 服务文件: $SERVICE_DIR/ech-workers.service" + echo " • 日志目录: $LOG_DIR/" + echo "" + echo "🚀 启动服务:" + echo " sudo systemctl start ech-workers" + echo "" + echo "📊 服务管理:" + echo " sudo systemctl status ech-workers # 查看状态" + echo " sudo systemctl restart ech-workers # 重启服务" + echo " sudo journalctl -u ech-workers -f # 查看日志" + echo "" + echo "🔧 配置修改:" + echo " 编辑配置文件: sudo nano /etc/ech-workers/config.env" + echo " 然后重启: sudo systemctl restart ech-workers" + echo "" + echo "🌐 代理地址:" + echo " HTTP/HTTPS: http://$(hostname -I | awk '{print $1}'):${LISTEN_ADDR##*:}" + echo " SOCKS5: socks5://$(hostname -I | awk '{print $1}'):${LISTEN_ADDR##*:}" + echo "" + echo "💡 快速测试:" + echo " curl --proxy http://127.0.0.1:${LISTEN_ADDR##*:} http://httpbin.org/ip" + echo "" + echo "📝 版本信息:" + /usr/local/bin/ech-workers --help 2>&1 | grep -E "(版本|Version)" | head -2 || true +} + +# 主安装流程 +main() { + show_banner + check_system + install_dependencies + install_binary + create_config + create_systemd_service + setup_logrotate + configure_firewall + create_management_scripts + show_completion + + log "安装完成!建议重启服务使所有配置生效。" + echo "" + read -p "是否立即启动服务?[Y/n]: " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]] || [ -z "$REPLY" ]; then + systemctl start ech-workers + systemctl enable ech-workers + success "服务已启动并设置为开机自启" + fi +} + +# 运行主函数 +main "$@" +EOF + + chmod +x "$PACKAGE_DIR/install.sh" + + # 创建 tar 包 + tar -czf "${PACKAGE_DIR}.tar.gz" "$PACKAGE_DIR" + + # 清理临时目录 + rm -rf "$PACKAGE_DIR" + + echo "✅ 打包完成: ${PACKAGE_DIR}.tar.gz" + + - name: 🏷️ 重命名文件 + run: | + cd ${{ env.OUTPUT_DIR }} + + VERSION="${{ needs.build-check.outputs.build_version }}" + BUILD_TYPE="${{ matrix.build_type }}" + + # 重命名主要文件 + for ext in "" .sha256 .sha1 .md5 .b3sum; do + if [ -f "${{ env.PROJECT_NAME }}-armv7${steps.build.outputs.build_suffix}${ext}" ]; then + mv "${{ env.PROJECT_NAME }}-armv7${steps.build.outputs.build_suffix}${ext}" \ + "${{ env.PROJECT_NAME }}-${VERSION}-armv7${BUILD_TYPE}${ext}" + fi + done + + echo "📁 最终文件列表:" + ls -lh * + + - name: 📤 上传构建产物 + uses: actions/upload-artifact@v4 + with: + name: ${{ env.PROJECT_NAME }}-${{ needs.build-check.outputs.build_version }}-${{ matrix.build_type }} + path: ${{ env.OUTPUT_DIR }}/* + retention-days: 30 + if-no-files-found: error + + create-release: + runs-on: ubuntu-latest + needs: [build-check, build-armv7] + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + + steps: + - name: 📥 下载所有构建产物 + uses: actions/download-artifact@v4 + with: + path: artifacts + pattern: ${{ env.PROJECT_NAME }}-* + merge-multiple: true + + - name: 🏷️ 创建 GitHub Release + uses: softprops/action-gh-release@v1 + with: + name: Release ${{ needs.build-check.outputs.build_version }} + body: | + # ech-workers Hi3798MV100 ARMv7 版本 + + ## 📋 版本信息 + - **版本号**: ${{ needs.build-check.outputs.build_version }} + - **构建时间**: ${{ env.BUILD_DATE }} + - **目标设备**: Hi3798MV100 (ARMv7) + - **Go版本**: ${{ env.GO_VERSION }} + + ## 📦 包含的构建 + - **标准版本**: 动态链接库,体积较小 + - **静态版本**: 完全静态编译,无需外部依赖 + + ## 🚀 快速开始 + 1. 下载对应的 tar.gz 文件 + 2. 解压: `tar -xzf ech-workers-*.tar.gz` + 3. 运行安装脚本: `sudo ./install.sh` + + ## 🔧 使用说明 + 详细使用说明请参考解压后的 README 文件 + + ## 📝 变更日志 + ${{ github.event.head_commit.message }} + + ## 🔒 校验和 + 下载后请验证文件校验和确保完整性 + draft: false + prerelease: false + files: | + artifacts/*.tar.gz + artifacts/*.sha256 + artifacts/*.md5 + artifacts/BUILD_INFO.txt + + - name: 📢 发布通知 + if: success() + run: | + echo "🎉 发布成功!" + echo "版本: ${{ needs.build-check.outputs.build_version }}" + echo "Release URL: https://github.com/${{ github.repository }}/releases/tag/${{ needs.build-check.outputs.build_version }}" + + cleanup: + runs-on: ubuntu-latest + needs: [build-armv7, create-release] + if: always() + + steps: + - name: 🧹 清理工作流 + run: | + echo "🧹 清理构建缓存..." + if [ "${{ github.event.inputs.clean_build }}" = "true" ]; then + echo "清理所有缓存" + # 这里可以添加缓存清理逻辑 + fi + + echo "✅ 工作流执行完成" + echo "状态: ${{ job.status }}" diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml new file mode 100644 index 0000000..c39fa4a --- /dev/null +++ b/.github/workflows/build-ios.yml @@ -0,0 +1,125 @@ +name: 🍏 Build iOS App + +on: + push: + branches: [ main, master ] + tags: [ 'ios-*' ] + pull_request: + branches: [ main, master ] + workflow_dispatch: + inputs: + version: + description: 'Version tag' + required: false + default: 'v1.0.0' + +env: + GO_VERSION: '1.21' + IOS_DEPLOYMENT_TARGET: '15.0' + +jobs: + build-ios: + runs-on: macos-latest + + steps: + - name: 📥 Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: 🔧 Setup Go + uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + + - name: 🏗️ Setup iOS build environment + run: | + # 安装 gomobile + go install golang.org/x/mobile/cmd/gomobile@latest + ~/go/bin/gomobile init + + # 检查 Xcode 版本 + xcodebuild -version + + - name: 🛠️ Build iOS framework + run: | + cd ios/bridge + + # 编译为 iOS 框架 + ~/go/bin/gomobile bind -target=ios \ + -ldflags="-w -s" \ + -o EchWorkers.xcframework \ + . + + ls -lh EchWorkers.xcframework + + - name: 📦 Create unsigned IPA + run: | + # 创建简单的 iOS 应用包 + mkdir -p Payload + mkdir -p Payload/ECHWorkers.app + + # 创建 Info.plist + cat > Payload/ECHWorkers.app/Info.plist << EOF + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ECH SOCKS5 Proxy + CFBundleExecutable + ECHWorkers + CFBundleIdentifier + com.ech.workers.ios + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ECHWorkers + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + +EOF + + # 压缩为 IPA + zip -qr ECHWorkers-unsigned.ipa Payload + + - name: 📤 Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: ech-workers-ios + path: | + ECHWorkers-unsigned.ipa + ios/bridge/EchWorkers.xcframework + retention-days: 30 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 513c2b5..0000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,66 +0,0 @@ -name: Release All Platforms - -on: - release: - types: [published] - workflow_dispatch: - inputs: - version: - description: 'Release tag(例如 v1.5.0 或 nightly-20251129)' - required: true - type: string - -permissions: - contents: write - -jobs: - # Main release job for all platforms - release: - runs-on: ubuntu-latest - steps: - - - name: Free Disk Space (Ubuntu) - if: matrix.target-platform == '' - uses: jlumbroso/free-disk-space@main - with: - tool-cache: false - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: true - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.25.0' - - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install dependencies - run: | - sudo snap install zig --classic --beta - docker pull crazymax/xgo:latest - go install github.com/crazy-max/xgo@latest - sudo apt install upx - - - name: Build - run: | - bash build.sh release ${{ matrix.build-type == 'lite' && 'lite' || '' }} ${{ matrix.target-platform }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload assets - uses: softprops/action-gh-release@v2 - with: - files: build/compress/* - prerelease: false - tag_name: ${{ inputs.version }} - - - - diff --git a/.github/workflows/hi3798mv100.yml b/.github/workflows/hi3798mv100.yml new file mode 100644 index 0000000..0a54bd2 --- /dev/null +++ b/.github/workflows/hi3798mv100.yml @@ -0,0 +1,306 @@ +name: Build for Hi3798MV100 (Fixed) + +on: + workflow_dispatch: + push: + branches: [ main, master ] + release: + types: [created] + +jobs: + build-hi3798: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.21' + cache: true + + - name: Install musl cross compiler (Fixed) + run: | + echo "安装交叉编译工具链..." + + # 方法1: 使用 musl.cc(最简单) + #echo "方法1: 使用 musl.cc 工具链" + #wget -q https://musl.cc/arm-linux-musleabihf-cross.tgz + #tar -xzf arm-linux-musleabihf-cross.tgz + #export PATH="$PWD/arm-linux-musleabihf-cross/bin:$PATH" + + # 验证 + #echo "验证工具链..." + #arm-linux-musleabihf-gcc --version + + # 方法2: 使用 apt 安装(备用) + echo "方法2: 安装备用工具链" + sudo apt-get update + sudo apt-get install -y \ + gcc-arm-linux-gnueabihf \ + gcc-aarch64-linux-gnu \ + musl-tools + + # 创建符号链接 + sudo ln -sf /usr/bin/arm-linux-gnueabihf-gcc /usr/local/bin/arm-linux-musleabihf-gcc 2>/dev/null || true + + - name: Build static binary + run: | + echo "开始构建..." + + # 设置环境变量 + export CC="arm-linux-musleabihf-gcc" + export GOOS="linux" + export GOARCH="arm" + export GOARM="7" + export CGO_ENABLED="1" + + # 版本信息 + VERSION="v1.0.0-$(date +%Y%m%d)" + COMMIT=$(git rev-parse --short HEAD) + DATE=$(date -u '+%Y-%m-%d_%H:%M:%S') + + echo "构建信息:" + echo "- 版本: $VERSION" + echo "- Commit: $COMMIT" + echo "- 日期: $DATE" + echo "- 编译器: $CC" + which $CC + + # 静态编译 + echo "执行静态编译..." + go build -a -v \ + -o "ech-workers-hi3798mv100" \ + -ldflags="-w -s \ + -linkmode external \ + -extldflags '-static' \ + -X 'main.version=$VERSION' \ + -X 'main.commit=$COMMIT' \ + -X 'main.buildTime=$DATE'" \ + . + + # 验证文件 + echo "验证构建结果..." + file ech-workers-hi3798mv100 + ls -lh ech-workers-hi3798mv100 + + # 检查是否静态链接 + echo "检查链接状态..." + ldd ech-workers-hi3798mv100 2>&1 | grep -q "not a dynamic" && \ + echo "✓ 静态链接成功" || \ + echo "⚠ 可能不是完全静态" + + - name: Build pure Go version (fallback) + run: | + echo "构建纯 Go 版本(备用)..." + + export GOOS="linux" + export GOARCH="arm" + export GOARM="7" + export CGO_ENABLED="0" + + VERSION="v1.0.0-purego-$(date +%Y%m%d)" + + go build \ + -o "ech-workers-hi3798mv100-purego" \ + -ldflags="-w -s -X 'main.version=$VERSION'" \ + . + + file ech-workers-hi3798mv100-purego + ls -lh ech-workers-hi3798mv100-purego + + - name: Create checksums + run: | + echo "创建校验和..." + for file in ech-workers-hi3798mv100*; do + if [ -f "$file" ] && [[ "$file" != *.sha256 ]] && [[ "$file" != *.md5 ]]; then + sha256sum "$file" > "$file.sha256" + md5sum "$file" > "$file.md5" + echo " $file:" + cat "$file.sha256" + fi + done + + - name: Create release package + run: | + echo "创建发布包..." + mkdir -p release + + # 复制文件 + cp ech-workers-hi3798mv100* release/ 2>/dev/null || true + + # 创建安装脚本 + cat > release/install.sh << 'EOF' + #!/bin/bash + # ech-workers Hi3798MV100 安装脚本 + + set -e + + echo "========================================" + echo " ech-workers Hi3798MV100 安装程序" + echo "========================================" + + # 默认参数 + DEVICE_IP="" + INSTALL_DIR="/usr/local/bin" + SERVICE_NAME="ech-workers" + + # 解析参数 + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + echo "使用方法: $0 [选项] <设备IP>" + echo "选项:" + echo " -h, --help 显示帮助" + echo " -d, --dir DIR 安装目录 (默认: /usr/local/bin)" + echo " -s, --service 创建 systemd 服务" + exit 0 + ;; + -d|--dir) + INSTALL_DIR="$2" + shift 2 + ;; + -s|--service) + CREATE_SERVICE=1 + shift + ;; + *) + DEVICE_IP="$1" + shift + ;; + esac + done + + if [ -z "$DEVICE_IP" ]; then + echo "错误: 必须指定设备IP地址" + echo "示例: $0 192.168.1.100" + exit 1 + fi + + # 选择要安装的版本 + echo "选择安装版本:" + echo "1) 静态版本 (ech-workers-hi3798mv100)" + echo "2) 纯Go版本 (ech-workers-hi3798mv100-purego)" + read -p "请输入选择 [1-2] (默认 1): " choice + choice=${choice:-1} + + case $choice in + 1) BINARY="ech-workers-hi3798mv100" ;; + 2) BINARY="ech-workers-hi3798mv100-purego" ;; + *) BINARY="ech-workers-hi3798mv100" ;; + esac + + if [ ! -f "$BINARY" ]; then + echo "错误: 找不到文件 $BINARY" + exit 1 + fi + + echo "安装信息:" + echo "- 设备: $DEVICE_IP" + echo "- 版本: $BINARY" + echo "- 目录: $INSTALL_DIR" + + # 传输文件 + echo -e "\n传输文件..." + scp "$BINARY" root@${DEVICE_IP}:/tmp/ech-workers-new + scp "$BINARY.sha256" root@${DEVICE_IP}:/tmp/ 2>/dev/null || true + + # 执行安装 + echo -e "\n正在安装..." + ssh root@${DEVICE_IP} << SSH_EOF + set -e + + echo "备份旧版本..." + if [ -f "$INSTALL_DIR/ech-workers" ]; then + BACKUP="\$INSTALL_DIR/ech-workers.backup.\$(date +%Y%m%d_%H%M%S)" + cp "\$INSTALL_DIR/ech-workers" "\$BACKUP" + echo "已备份到: \$BACKUP" + fi + + echo "安装新版本..." + cp /tmp/ech-workers-new "\$INSTALL_DIR/ech-workers" + chmod +x "\$INSTALL_DIR/ech-workers" + + echo -e "\n验证安装:" + file "\$INSTALL_DIR/ech-workers" + "\$INSTALL_DIR/ech-workers" --help 2>&1 | head -5 + + # 创建 systemd 服务 + if [ -n "$CREATE_SERVICE" ]; then + echo -e "\n创建 systemd 服务..." + cat > /etc/systemd/system/ech-workers.service << SERVICE_EOF + [Unit] + Description=ECH Workers Proxy + After=network.target + + [Service] + Type=simple + ExecStart=$INSTALL_DIR/ech-workers \\ + -l 0.0.0.0:30000 \\ + -f your-worker.workers.dev:443 \\ + -token YOUR_TOKEN_HERE \\ + -pyip backup.proxy.com:8080 \\ + -ip 104.16.132.229 + Restart=always + RestartSec=10 + + [Install] + WantedBy=multi-user.target + SERVICE_EOF + + systemctl daemon-reload + systemctl enable ech-workers + echo "服务已创建并启用" + fi + + echo -e "\n安装完成!" + echo "运行命令: \$INSTALL_DIR/ech-workers [参数]" + SSH_EOF + + echo -e "\n✅ 安装完成!" + EOF + + chmod +x release/install.sh + + # 创建配置文件模板 + cat > release/config-example.sh << 'EOF' + #!/bin/bash + # ech-workers 配置示例 + + # 基本配置 + LISTEN_ADDR="0.0.0.0:30000" + WORKER_URL="your-app.workers.dev:443" + TOKEN="your_token_here" + + # 高级配置 + FALLBACK_PROXY="backup.proxy.com:8080" + TARGET_IP="104.16.132.229" + DNS_SERVER="1.1.1.1/dns-query" + ECH_DOMAIN="cloudflare-ech.com" + + # 运行命令 + CMD="/usr/local/bin/ech-workers \ + -l \"\$LISTEN_ADDR\" \ + -f \"\$WORKER_URL\" \ + -token \"\$TOKEN\" \ + -pyip \"\$FALLBACK_PROXY\" \ + -ip \"\$TARGET_IP\" \ + -dns \"\$DNS_SERVER\" \ + -ech \"\$ECH_DOMAIN\"" + + echo "运行命令:" + echo \$CMD + # eval \$CMD + EOF + + chmod +x release/config-example.sh + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: hi3798mv100-build + path: | + ech-workers-hi3798mv100* + release/ + retention-days: 30 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e09f24d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# iOS 构建产物 +ios/bridge/EchWorkers.xcframework +Payload/ +*.ipa +DerivedData/ diff --git a/README.md b/README.md index dde97c8..8c5df01 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,56 @@ -``` -命令行执行如下: -ech-win -l 127.0.0.1:30000 -f cf绑定域名[pages.dev]:443 -pyip tw.william.us.ci -token xxx -ip 优选域名或者ip(ipv4或ipv6) -ech-win -f cf绑定域名:443 -pyip tw.william.us.ci -token xxx -ip 104.16.0.0 -ech-win -f cf绑定域名:443 -pyip 211.48.77.114:12312 -token xxx -ip 104.16.0.0 - -Usage of ech-win: - -dns string - ECH 查询 DoH 服务器 (default "dns.alidns.com/dns-query") - -ech string - ECH 查询域名 (default "cloudflare-ech.com") - -f string - 服务端地址 (格式: x.x.workers.dev:443) - -ip string - 指定服务端 IP(绕过 DNS 解析) - -l string - 代理监听地址 (支持 SOCKS5 和 HTTP) (default "127.0.0.1:30000") - -pyip string - 代理服务器 IP(用于 Worker 连接回退) - -token string - 身份验证令牌 -``` -##### 注:workers、pages、snippets三种部署都支持, TOKEN=xxx 部署时请更换 +在hi3798mv100设备上部署了ech-workers代理服务,并且配置了systemd服务。以下是安装和设置过程的详细步骤总结: +(Ubuntu 20.04.6 LTS (GNU/Linux 4.4.35_ecoo_81112068 armv7l0 +安装和设置过程 +1. 获取ech-workers程序 +确保你已经获得了ech-workers可执行程序,并将其放置到/usr/local/bin/目录下,并给予执行权限。 + +bash +# 假设ech-workers程序在当前目录 +sudo cp ech-workers /usr/local/bin/ +sudo chmod +x /usr/local/bin/ech-workers +2. 创建systemd服务配置文件 +创建服务文件/etc/systemd/system/ech-workers.service,内容如下: + +[Unit] +Description=ECH Workers Proxy Service +After=network.target + +[Service] +Type=simple +User=root +# 🤣🤣🤣🤣 +ExecStart=/usr/local/bin/ech-workers \ + -l 0.0.0.0:30000 \ + -f "xxxxxxxxxxx.workers.dev:443" \ + -token "xxxxxxxx" \ + -ip "xx.xx.xxx" \ + -dns "dns.alidns.com/dns-query" +Restart=on-failure # 仅在失败时重启,而不是一直重启 +RestartSec=10 # 重启间隔增加到10秒 +RestartPreventExitStatus=0 # 正常退出时不重启 +[Install] + +WantedBy=multi-user.target +3. 重新加载systemd配置并启动服务 +bash +# 重新加载systemd配置 +sudo systemctl daemon-reload +# 启动服务 +sudo systemctl start ech-workers +# 设置开机自启 +sudo systemctl enable ech-workers +# 检查服务状态 +sudo systemctl status ech-workers + +## 🍏 iOS 构建 + +### 构建未签名 IPA +```bash +# 安装依赖 +go install golang.org/x/mobile/cmd/gomobile@latest +gomobile init + +# 构建 iOS 应用 +chmod +x scripts/build-ios.sh +./scripts/build-ios.sh + diff --git a/ios/bridge/bridge.go b/ios/bridge/bridge.go new file mode 100644 index 0000000..96c375c --- /dev/null +++ b/ios/bridge/bridge.go @@ -0,0 +1,108 @@ +// +build ios + +package main + +import ( + "fmt" + "log" + "time" + + "golang.org/x/mobile/app" + "golang.org/x/mobile/event/key" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/event/touch" + "golang.org/x/mobile/gl" +) + +// SOCKS5Server iOS SOCKS5 服务器实现 +type SOCKS5Server struct { + config *Config + running bool +} + +// NewSOCKS5Server 创建新的 SOCKS5 服务器 +func NewSOCKS5Server(config *Config) *SOCKS5Server { + return &SOCKS5Server{ + config: config, + running: false, + } +} + +// Start 启动 SOCKS5 代理 +func (s *SOCKS5Server) Start() error { + if s.running { + return fmt.Errorf("server already running") + } + + log.Printf("Starting SOCKS5 server on %s", s.config.ListenAddr) + s.running = true + + // iOS 特定的 SOCKS5 实现 + go s.runIOSProxy() + + return nil +} + +// Stop 停止 SOCKS5 代理 +func (s *SOCKS5Server) Stop() { + s.running = false + log.Println("SOCKS5 server stopped") +} + +// runIOSProxy iOS 平台的代理实现 +func (s *SOCKS5Server) runIOSProxy() { + // iOS 特定的网络处理 + // 这里需要实现 SOCKS5 协议处理 +} + +// Export iOS 接口函数 +//export StartSOCKS5Proxy +func StartSOCKS5Proxy(listenAddr, workerURL, token string) int { + config := &Config{ + ListenAddr: listenAddr, + WorkerURL: workerURL, + Token: token, + } + + server := NewSOCKS5Server(config) + if err := server.Start(); err != nil { + return -1 + } + + return 0 +} + +//export StopSOCKS5Proxy +func StopSOCKS5Proxy() { + // 停止代理实现 +} + +//export IsSOCKS5ProxyRunning +func IsSOCKS5ProxyRunning() bool { + // 检查代理状态 + return false +} + +// iOS 应用主函数 +func main() { + app.Main(func(a app.App) { + var sz size.Event + for e := range a.Events() { + switch e := a.Filter(e).(type) { + case lifecycle.Event: + // 处理生命周期事件 + case size.Event: + sz = e + case paint.Event: + // 绘制界面 + a.EndPaint(e) + case touch.Event: + // 处理触摸事件 + case key.Event: + // 处理键盘事件 + } + } + }) +} diff --git a/ios/bridge/go.mod b/ios/bridge/go.mod new file mode 100644 index 0000000..cfc6622 --- /dev/null +++ b/ios/bridge/go.mod @@ -0,0 +1,13 @@ +module ech-workers-ios + +go 1.21 + +replace github.com/hhsw2015/ech_workers => ../.. + +require ( + github.com/hhsw2015/ech_workers v0.0.0 + golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57 + golang.org/x/net v0.17.0 +) + +require golang.org/x/text v0.13.0 // indirect diff --git a/main.go b/main.go new file mode 100644 index 0000000..0d7c854 --- /dev/null +++ b/main.go @@ -0,0 +1,106 @@ +// 添加构建标签 +//go:build !ios +// +build !ios + +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "syscall" +) + +func main() { + // 原有参数... + var ( + listenAddr = flag.String("l", "127.0.0.1:30000", "监听地址") + serverAddr = flag.String("f", "", "服务端地址") + token = flag.String("token", "", "身份验证令牌") + socks5 = flag.Bool("socks5", false, "启用 SOCKS5 协议") + // ... 其他参数 + ) + + flag.Parse() + + // 如果启用了 SOCKS5,使用 SOCKS5 模式 + if *socks5 { + startSOCKS5Proxy(*listenAddr, *serverAddr, *token) + } else { + // 原有逻辑 + startHTTPProxy(*listenAddr, *serverAddr, *token) + } +} + +// startSOCKS5Proxy 启动 SOCKS5 代理 +func startSOCKS5Proxy(listenAddr, serverAddr, token string) { + fmt.Println("Starting SOCKS5 proxy on", listenAddr) + + config := &Config{ + ListenAddr: listenAddr, + WorkerURL: serverAddr, + Token: token, + } + + server := NewSOCKS5Server(config) + if err := server.Start(); err != nil { + log.Fatal("Failed to start SOCKS5 proxy:", err) + } + + // 等待退出信号 + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + <-sigCh + + server.Stop() + fmt.Println("SOCKS5 proxy stopped") +} + +// Config 配置结构体 +type Config struct { + ListenAddr string + WorkerURL string + Token string + SocksProxy string + PreferredIP string + DNSServer string + ECHDomain string +} + +// SOCKS5Server SOCKS5 服务器 +type SOCKS5Server struct { + config *Config + running bool +} + +// NewSOCKS5Server 创建 SOCKS5 服务器 +func NewSOCKS5Server(config *Config) *SOCKS5Server { + return &SOCKS5Server{ + config: config, + running: false, + } +} + +// Start 启动服务器 +func (s *SOCKS5Server) Start() error { + if s.running { + return fmt.Errorf("server already running") + } + + // 实现 SOCKS5 服务器逻辑 + log.Printf("SOCKS5 proxy started on %s", s.config.ListenAddr) + s.running = true + + // 这里实现具体的 SOCKS5 代理逻辑 + // 需要处理 SOCKS5 协议认证、连接转发等 + + return nil +} + +// Stop 停止服务器 +func (s *SOCKS5Server) Stop() { + s.running = false + log.Println("SOCKS5 proxy stopped") +} diff --git a/mobile.go b/mobile.go new file mode 100644 index 0000000..5db9a94 --- /dev/null +++ b/mobile.go @@ -0,0 +1,58 @@ +package main + +import ( + "context" + "fmt" + "log" + "net/url" + "time" + + // 导入原项目的包 + ech "github.com/hhsw2015/ech_workers" +) + +// Client 是一个移动端使用的客户端 +type Client struct { + cancel context.CancelFunc +} + +// Start 启动代理服务,参数为: +// listenAddr: 监听地址,例如 "127.0.0.1:30000" +// workerURL: Cloudflare Worker地址,例如 "your-worker.workers.dev:443" +// token: 身份验证令牌 +// socksAddr: SOCKS代理地址,例如 "192.168.1.100:1080",如果为空则不使用SOCKS +// 返回一个错误 +func (c *Client) Start(listenAddr, workerURL, token, socksAddr string) error { + // 如果socksAddr不为空,设置SOCKS代理 + if socksAddr != "" { + // 设置SOCKS代理环境变量,原项目可能需要通过环境变量或参数设置 + // 这里假设原项目支持通过参数设置SOCKS代理 + // 实际上,原项目可能不支持,所以需要修改原项目以支持SOCKS代理 + // 我们假设原项目有一个SetSOCKSProxy函数 + // 如果没有,我们需要修改原项目 + } + + // 原项目可能是一个阻塞的函数,我们需要在goroutine中运行 + ctx, cancel := context.WithCancel(context.Background()) + c.cancel = cancel + + go func() { + // 调用原项目的启动函数,这里假设原项目有一个Run函数 + // 注意:原项目可能需要参数,我们需要将其适配 + err := ech.Run(ctx, listenAddr, workerURL, token) + if err != nil { + log.Printf("ech.Run error: %v", err) + } + }() + + // 等待一段时间确保服务启动 + time.Sleep(2 * time.Second) + return nil +} + +// Stop 停止代理服务 +func (c *Client) Stop() { + if c.cancel != nil { + c.cancel() + } +} diff --git a/scripts/build-ios.sh b/scripts/build-ios.sh new file mode 100644 index 0000000..728d414 --- /dev/null +++ b/scripts/build-ios.sh @@ -0,0 +1,209 @@ +#!/bin/bash +# iOS 构建脚本 + +set -e + +echo "🚀 开始构建 iOS SOCKS5 代理应用" +echo "========================================" + +# 检查依赖 +check_dependencies() { + echo "🔍 检查依赖..." + + # 检查 Go + if ! command -v go &> /dev/null; then + echo "❌ Go 未安装" + exit 1 + fi + echo "✅ Go $(go version)" + + # 检查 gomobile + if ! command -v gomobile &> /dev/null; then + echo "📦 安装 gomobile..." + go install golang.org/x/mobile/cmd/gomobile@latest + gomobile init + fi + echo "✅ gomobile 已安装" + + # 检查 Xcode + if [ ! -d "/Applications/Xcode.app" ]; then + echo "❌ Xcode 未安装" + exit 1 + fi + echo "✅ Xcode 已安装" +} + +# 清理工作区 +clean_workspace() { + echo "🧹 清理工作区..." + rm -rf ios/bridge/EchWorkers.xcframework + rm -rf Payload + rm -rf *.ipa +} + +# 构建 iOS 框架 +build_framework() { + echo "🛠️ 构建 iOS 框架..." + + cd ios/bridge + + # 下载依赖 + go mod download + + # 编译为 iOS 框架 + gomobile bind -target=ios \ + -ldflags="-w -s" \ + -o EchWorkers.xcframework \ + . + + echo "✅ iOS 框架构建完成" + + # 回到项目根目录 + cd ../.. +} + +# 打包 IPA +package_ipa() { + echo "📦 打包未签名 IPA..." + + # 创建应用目录结构 + mkdir -p Payload/ECHWorkers.app + + # 创建 Info.plist + cat > Payload/ECHWorkers.app/Info.plist << EOF + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ECH SOCKS5 Proxy + CFBundleExecutable + ECHWorkers + CFBundleIdentifier + com.ech.workers.ios + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ECHWorkers + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + + +EOF + + # 创建可执行文件占位符 + touch Payload/ECHWorkers.app/ECHWorkers + chmod +x Payload/ECHWorkers.app/ECHWorkers + + # 压缩为 IPA + zip -qr ech-workers-ios-unsigned.ipa Payload + + echo "✅ IPA 打包完成: ech-workers-ios-unsigned.ipa" +} + +# 创建安装说明 +create_readme() { + echo "📝 创建安装说明..." + + cat > INSTALL-iOS.md << 'EOF' +# iOS SOCKS5 代理应用安装指南 + +## 应用功能 +- ✅ SOCKS5 代理服务器 +- ✅ Cloudflare Workers 中转 +- ✅ 本地端口转发 +- ✅ 简单的配置界面 + +## 安装方法 + +### 方法一:使用 AltStore (推荐) +1. 在电脑上安装 AltServer: https://altstore.io +2. 连接 iOS 设备到电脑 +3. 使用 AltServer 安装 AltStore 到手机 +4. 通过 AltStore 安装此 IPA + +### 方法二:使用 TrollStore (需要越狱) +1. 安装 TrollStore: https://github.com/opa334/TrollStore +2. 通过 TrollStore 安装此 IPA + +### 方法三:企业签名 +1. 使用 iOS App Signer 重新签名 +2. 使用企业证书分发 + +## 使用方法 +1. 安装应用 +2. 在应用内配置: + - Server URL: 您的 Cloudflare Worker 地址 + - Token: 身份验证令牌 + - Port: 本地监听端口 (默认 1080) +3. 启动代理 +4. 在系统设置中配置 SOCKS5 代理: + - 设置 → Wi-Fi → 当前网络 → 配置代理 → 手动 + - 服务器: 127.0.0.1 + - 端口: 1080 + +## 注意事项 +- 未签名应用有7天有效期限制 +- 需要保持应用在后台运行 +- 某些网络可能限制本地回环地址 +EOF + + echo "✅ 安装说明创建完成: INSTALL-iOS.md" +} + +# 主流程 +main() { + check_dependencies + clean_workspace + build_framework + package_ipa + create_readme + + echo "" + echo "🎉 iOS SOCKS5 代理应用构建完成!" + echo "" + echo "📦 生成的文件:" + echo " - ech-workers-ios-unsigned.ipa (未签名应用包)" + echo " - ios/bridge/EchWorkers.xcframework (iOS 框架)" + echo " - INSTALL-iOS.md (安装指南)" + echo "" + echo "📱 安装方法:" + echo " 使用 AltStore 或 TrollStore 安装到 iOS 设备" +} + +# 执行主流程 +main "$@"