diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b1d7ca..71a5f2a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -28,7 +28,7 @@ jobs: echo "SHA_SHORT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: check-latest: true go-version-file: "go.mod" @@ -38,16 +38,16 @@ jobs: run: go test -v ./... - name: Build - uses: goreleaser/goreleaser-action@v6 + uses: goreleaser/goreleaser-action@v7 if: "!startsWith(github.ref, 'refs/tags/')" with: - args: build --snapshot --clean + args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload Artifacts - uses: actions/upload-artifact@v4 - if: "!startsWith(github.ref, 'refs/tags/')" + uses: actions/upload-artifact@v6 + # if: "!startsWith(github.ref, 'refs/tags/')" with: name: ${{ env.APP_NAME }}-dev-${{ env.SHA_SHORT }} path: | @@ -56,48 +56,48 @@ jobs: ./dist/default_darwin_arm64/${{ env.APP_NAME }} ./dist/default_windows_amd64_v1/${{ env.APP_NAME }}.exe - - name: Release - uses: goreleaser/goreleaser-action@v6 - if: startsWith(github.ref, 'refs/tags/') - with: - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # - name: Release + # uses: goreleaser/goreleaser-action@v6 + # if: startsWith(github.ref, 'refs/tags/') + # with: + # args: release --clean + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Docker - Set up Buildx - id: buildx - uses: docker/setup-buildx-action@v3 + # - name: Docker - Set up Buildx + # id: buildx + # uses: docker/setup-buildx-action@v3 - - name: Docker - Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + # - name: Docker - Login to DockerHub + # uses: docker/login-action@v3 + # with: + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Docker - Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} + # - name: Docker - Login to GHCR + # uses: docker/login-action@v3 + # with: + # registry: ghcr.io + # username: ${{ github.repository_owner }} + # password: ${{ secrets.GITHUB_TOKEN }} - - name: Docker - Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: | - ${{ env.DOCKERHUB_REPO }} - ${{ env.GHCR_REPO }} - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} + # - name: Docker - Docker meta + # id: meta + # uses: docker/metadata-action@v5 + # with: + # images: | + # ${{ env.DOCKERHUB_REPO }} + # ${{ env.GHCR_REPO }} + # tags: | + # type=ref,event=branch + # type=semver,pattern={{version}} + # type=semver,pattern={{major}}.{{minor}} - - name: Docker - Build and push - uses: docker/build-push-action@v6 - with: - context: . - file: .Dockerfile - platforms: ${{ env.PLATFORMS }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} + # - name: Docker - Build and push + # uses: docker/build-push-action@v6 + # with: + # context: . + # file: .Dockerfile + # platforms: ${{ env.PLATFORMS }} + # push: ${{ github.event_name != 'pull_request' }} + # tags: ${{ steps.meta.outputs.tags }} diff --git a/proxy/vmess/vmess.go b/proxy/vmess/vmess.go index 60a20d6..92bfc3e 100644 --- a/proxy/vmess/vmess.go +++ b/proxy/vmess/vmess.go @@ -1,9 +1,12 @@ package vmess import ( + "encoding/base64" + "encoding/json" "net" "net/url" "strconv" + "strings" "github.com/nadoo/glider/pkg/log" "github.com/nadoo/glider/proxy" @@ -26,8 +29,87 @@ func init() { proxy.RegisterDialer("vmess", NewVMessDialer) } +// decodeVMessURL decodes BASE64-encoded vmess URL and converts it to standard format +// Input can be: vmess://base64EncodedJSON or vmess://standard-url-format +// BASE64 format typically comes from subscription services +func decodeVMessURL(s string) string { + // Extract the part after vmess:// + if !strings.HasPrefix(s, "vmess://") { + return s + } + + urlPart := s[8:] // Remove "vmess://" + + // Try to decode as BASE64 + decoded, err := base64.StdEncoding.DecodeString(urlPart) + if err != nil { + // Not BASE64, return original + return s + } + + // Try to unmarshal as JSON + var config map[string]interface{} + err = json.Unmarshal(decoded, &config) + if err != nil { + // Not valid JSON, return original + return s + } + + // Extract configuration from JSON + // Expected fields: id (uuid), add (address), port, aid (alterID), security (default ""), etc. + uuid, ok := config["id"].(string) + if !ok || uuid == "" { + return s + } + + addr, ok := config["add"].(string) + if !ok || addr == "" { + return s + } + + port, ok := config["port"].(string) + if !ok { + // Try to convert from number to string + if portNum, ok := config["port"].(float64); ok { + port = strconv.FormatFloat(portNum, 'f', 0, 64) + } else { + return s + } + } + + // Get alterID (default "0") + alterID := "0" + if aid, ok := config["aid"].(string); ok { + alterID = aid + } else if aidNum, ok := config["aid"].(float64); ok { + alterID = strconv.FormatFloat(aidNum, 'f', 0, 64) + } + + // Get security/cipher (default empty string) + security := "" + if sec, ok := config["scy"].(string); ok { + security = sec + } else if sec, ok := config["security"].(string); ok { + security = sec + } + + // Reconstruct as standard vmess URL format + // Format: vmess://[security:]uuid@host:port[?alterID=num] + var standardURL string + if security != "" { + standardURL = "vmess://" + security + ":" + uuid + "@" + addr + ":" + port + "?alterID=" + alterID + } else { + standardURL = "vmess://" + uuid + "@" + addr + ":" + port + "?alterID=" + alterID + } + + return standardURL +} + // NewVMess returns a vmess proxy. func NewVMess(s string, d proxy.Dialer) (*VMess, error) { + // Handle BASE64 encoded vmess URL + s = decodeVMessURL(s) + u, err := url.Parse(s) if err != nil { log.F("parse url err: %s", err)