Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bec6c8392d |
@@ -248,7 +248,8 @@ https://evilfox.win/
|
|||||||
- безопасный lifecycle Connect/Disconnect (ожидание Stop, mutex Windows sysproxy);
|
- безопасный lifecycle Connect/Disconnect (ожидание Stop, mutex Windows sysproxy);
|
||||||
- SHA-256 проверка при установке cores (naive / hy2 / xray);
|
- SHA-256 проверка при установке cores (naive / hy2 / xray);
|
||||||
- snapshot конфига в UI (`Config().Clone`);
|
- snapshot конфига в UI (`Config().Clone`);
|
||||||
- 3.8.0+2: обновление Navis.app через zip+SHA; Start вне mutex; getState без секретов; подпись/notarize scripts; UI CSS/JS split.
|
- 3.8.0+2: обновление Navis.app через zip+SHA; Start вне mutex; getState без секретов; подпись/notarize scripts; UI CSS/JS split;
|
||||||
|
- 3.8.0+3: пинг Hy2/AWG по UDP — soft-ok при тишине (без ложных «недоступен»).
|
||||||
|
|
||||||
В 2.7.3:
|
В 2.7.3:
|
||||||
- восстановление системного прокси после аварийного завершения;
|
- восстановление системного прокси после аварийного завершения;
|
||||||
|
|||||||
+3
-3
@@ -34,11 +34,11 @@ if errorlevel 1 exit /b 1
|
|||||||
go build -o "tools\packmac\packmac.exe" .\tools\packmac
|
go build -o "tools\packmac\packmac.exe" .\tools\packmac
|
||||||
if errorlevel 1 exit /b 1
|
if errorlevel 1 exit /b 1
|
||||||
|
|
||||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-arm64\Navis" -out "dist\navis-release\darwin-arm64" -version 3.8.0 -build 3.8.0.2 -arch arm64
|
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-arm64\Navis" -out "dist\navis-release\darwin-arm64" -version 3.8.0 -build 3.8.0.3 -arch arm64
|
||||||
if errorlevel 1 exit /b 1
|
if errorlevel 1 exit /b 1
|
||||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-amd64\Navis" -out "dist\navis-release\darwin-amd64" -version 3.8.0 -build 3.8.0.2 -arch amd64
|
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-amd64\Navis" -out "dist\navis-release\darwin-amd64" -version 3.8.0 -build 3.8.0.3 -arch amd64
|
||||||
if errorlevel 1 exit /b 1
|
if errorlevel 1 exit /b 1
|
||||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-universal\Navis" -out "dist\navis-release\darwin-universal" -version 3.8.0 -build 3.8.0.2 -arch universal
|
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-universal\Navis" -out "dist\navis-release\darwin-universal" -version 3.8.0 -build 3.8.0.3 -arch universal
|
||||||
if errorlevel 1 exit /b 1
|
if errorlevel 1 exit /b 1
|
||||||
|
|
||||||
echo Built Mac GUI + CLI:
|
echo Built Mac GUI + CLI:
|
||||||
|
|||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
|||||||
3.8.0+2
|
3.8.0+3
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
3.8.0.2
|
3.8.0.3
|
||||||
|
|||||||
Vendored
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "3.8.0",
|
"version": "3.8.0",
|
||||||
"notes": "Navis 3.8.0+2: Mac .app zip update; EnsureCore lock; getState без секретов; подпись/notarize pipeline; UI split.",
|
"notes": "Navis 3.8.0+3: UDP ping Hy2/AWG (soft-ok без ложных «недоступен»); Mac .app zip update; EnsureCore lock; getState без секретов.",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
@@ -16,13 +16,13 @@
|
|||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "6e15ad79e5ec1a1f74c48bc8f189ab8694b8f3f67f4be204420a12cf0fd622fd",
|
"sha256": "bd507de6f434f53f95954c8e411cc1f8bb526d5b5353b1242de5bc9fb673670f",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64",
|
"arch": "arm64",
|
||||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip",
|
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip",
|
||||||
"zip_sha256": "65041e154356a33525b9769f851bcccfc79d0c2a1200fb9a47bc22dd95cdf2ef",
|
"zip_sha256": "2aaac597f7246c67fc825cd11f49d2b4fc0fa6bd9b89a1b1e4290e6a96c01de4",
|
||||||
"dmg_sha256": "46617b7cbf22e92a5ef85740ed9473cd1bc9219c9de5841ce0ac46b8eb946912"
|
"dmg_sha256": "26ddacc3b3bc372aa4833336e60fb32862fb30ee555a8a6e460811f45f9f5cee"
|
||||||
},
|
},
|
||||||
"darwin-amd64": {
|
"darwin-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||||
|
|||||||
Vendored
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "3.8.0",
|
"version": "3.8.0",
|
||||||
"notes": "Navis 3.8.0+2: Mac .app zip update; EnsureCore lock; getState без секретов; подпись/notarize pipeline; UI split.",
|
"notes": "Navis 3.8.0+3: UDP ping Hy2/AWG (soft-ok без ложных «недоступен»); Mac .app zip update; EnsureCore lock; getState без секретов.",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
@@ -16,13 +16,13 @@
|
|||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "6e15ad79e5ec1a1f74c48bc8f189ab8694b8f3f67f4be204420a12cf0fd622fd",
|
"sha256": "bd507de6f434f53f95954c8e411cc1f8bb526d5b5353b1242de5bc9fb673670f",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64",
|
"arch": "arm64",
|
||||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip",
|
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip",
|
||||||
"zip_sha256": "65041e154356a33525b9769f851bcccfc79d0c2a1200fb9a47bc22dd95cdf2ef",
|
"zip_sha256": "2aaac597f7246c67fc825cd11f49d2b4fc0fa6bd9b89a1b1e4290e6a96c01de4",
|
||||||
"dmg_sha256": "46617b7cbf22e92a5ef85740ed9473cd1bc9219c9de5841ce0ac46b8eb946912"
|
"dmg_sha256": "26ddacc3b3bc372aa4833336e60fb32862fb30ee555a8a6e460811f45f9f5cee"
|
||||||
},
|
},
|
||||||
"darwin-amd64": {
|
"darwin-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||||
|
|||||||
+37
-18
@@ -163,67 +163,86 @@ func PingProfile(ctx context.Context, name string, proto config.Protocol, proxyU
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
var (
|
||||||
var err error
|
rtt time.Duration
|
||||||
|
err error
|
||||||
|
)
|
||||||
if hy2 || isAWG {
|
if hy2 || isAWG {
|
||||||
err = probeUDP(ctx, host, port)
|
rtt, err = probeUDP(ctx, host, port)
|
||||||
} else {
|
} else {
|
||||||
err = probeTCP(ctx, host, port)
|
rtt, err = probeTCP(ctx, host, port)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res.Error = friendlyDialError(err, hy2 || isAWG)
|
res.Error = friendlyDialError(err, hy2 || isAWG)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
res.Ms = time.Since(start).Milliseconds()
|
ms := rtt.Milliseconds()
|
||||||
|
if ms < 1 {
|
||||||
|
ms = 1
|
||||||
|
}
|
||||||
|
res.Ms = ms
|
||||||
res.OK = true
|
res.OK = true
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func probeTCP(ctx context.Context, host, port string) error {
|
func probeTCP(ctx context.Context, host, port string) (time.Duration, error) {
|
||||||
|
start := time.Now()
|
||||||
d := net.Dialer{Timeout: 3 * time.Second}
|
d := net.Dialer{Timeout: 3 * time.Second}
|
||||||
conn, err := d.DialContext(ctx, "tcp", net.JoinHostPort(host, port))
|
conn, err := d.DialContext(ctx, "tcp", net.JoinHostPort(host, port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
return nil
|
return time.Since(start), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func probeUDP(ctx context.Context, host, port string) error {
|
// probeUDP checks Hy2/AWG endpoints.
|
||||||
|
//
|
||||||
|
// UDP VPN ports usually ignore a probe datagram (no reply). Treating read-timeout
|
||||||
|
// as failure marked live nodes as down. Semantics:
|
||||||
|
// - ICMP / connection refused → down
|
||||||
|
// - any reply → up (RTT to reply)
|
||||||
|
// - short read-timeout after a successful write → soft-up (RTT ≈ DNS+dial+write)
|
||||||
|
func probeUDP(ctx context.Context, host, port string) (time.Duration, error) {
|
||||||
|
start := time.Now()
|
||||||
d := net.Dialer{Timeout: 3 * time.Second}
|
d := net.Dialer{Timeout: 3 * time.Second}
|
||||||
conn, err := d.DialContext(ctx, "udp", net.JoinHostPort(host, port))
|
conn, err := d.DialContext(ctx, "udp", net.JoinHostPort(host, port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
deadline := time.Now().Add(1200 * time.Millisecond)
|
// Brief window only to catch ICMP port-unreachable; do not wait for an app reply.
|
||||||
|
icmpWait := 350 * time.Millisecond
|
||||||
|
deadline := time.Now().Add(icmpWait)
|
||||||
if dl, ok := ctx.Deadline(); ok && dl.Before(deadline) {
|
if dl, ok := ctx.Deadline(); ok && dl.Before(deadline) {
|
||||||
deadline = dl
|
deadline = dl
|
||||||
}
|
}
|
||||||
_ = conn.SetDeadline(deadline)
|
_ = conn.SetDeadline(deadline)
|
||||||
|
|
||||||
if _, err := conn.Write([]byte{0}); err != nil {
|
if _, err := conn.Write([]byte{0}); err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
afterWrite := time.Now()
|
||||||
|
|
||||||
buf := make([]byte, 64)
|
buf := make([]byte, 64)
|
||||||
_, err = conn.Read(buf)
|
_, err = conn.Read(buf)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return time.Since(start), nil
|
||||||
}
|
}
|
||||||
if ne, ok := err.(net.Error); ok && ne.Timeout() {
|
if ne, ok := err.(net.Error); ok && ne.Timeout() {
|
||||||
// UDP is connectionless: no reply does NOT mean the port is open.
|
// No ICMP refuse → endpoint is plausible; latency without the wait pad.
|
||||||
return fmt.Errorf("udp timeout")
|
return afterWrite.Sub(start), nil
|
||||||
}
|
}
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func friendlyDialError(err error, hy2 bool) string {
|
func friendlyDialError(err error, udp bool) string {
|
||||||
msg := err.Error()
|
msg := err.Error()
|
||||||
lower := strings.ToLower(msg)
|
lower := strings.ToLower(msg)
|
||||||
switch {
|
switch {
|
||||||
case strings.Contains(lower, "refused"):
|
case strings.Contains(lower, "refused"):
|
||||||
if hy2 {
|
if udp {
|
||||||
return "UDP порт недоступен (connection refused)"
|
return "UDP порт недоступен (connection refused)"
|
||||||
}
|
}
|
||||||
return "порт закрыт (connection refused)"
|
return "порт закрыт (connection refused)"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package netcheck
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
func TestFriendlyDialError(t *testing.T) {
|
func TestFriendlyDialError(t *testing.T) {
|
||||||
err := &netError{s: "dial tcp 1.2.3.4:22514: connectex: No connection could be made because the target machine actively refused it."}
|
err := &netError{s: "dial tcp 1.2.3.4:22514: connectex: No connection could be made because the target machine actively refused it."}
|
||||||
got := friendlyDialError(err, true)
|
got := friendlyDialError(err, true)
|
||||||
if !strings.Contains(got, "UDP") {
|
if got == "" || got == err.Error() {
|
||||||
t.Fatalf("got %q", got)
|
t.Fatalf("got %q", got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,3 +31,67 @@ func TestPingProfileEmpty(t *testing.T) {
|
|||||||
t.Fatalf("%+v", r)
|
t.Fatalf("%+v", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProbeUDPSoftOKWhenSilent(t *testing.T) {
|
||||||
|
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer pc.Close()
|
||||||
|
// Intentionally do not Read — mimics Hy2/AWG ignoring garbage probes.
|
||||||
|
_, port, err := net.SplitHostPort(pc.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
start := time.Now()
|
||||||
|
rtt, err := probeUDP(ctx, "127.0.0.1", port)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected soft-ok, got err=%v", err)
|
||||||
|
}
|
||||||
|
if rtt <= 0 {
|
||||||
|
t.Fatalf("rtt=%v", rtt)
|
||||||
|
}
|
||||||
|
if time.Since(start) > 900*time.Millisecond {
|
||||||
|
t.Fatalf("soft-ok waited too long: %v (should not use long timeout)", time.Since(start))
|
||||||
|
}
|
||||||
|
|
||||||
|
res := PingProfile(ctx, "silent", config.ProtocolHysteria2, "hysteria2://x@127.0.0.1:"+port+"/")
|
||||||
|
if !res.OK {
|
||||||
|
t.Fatalf("PingProfile soft-ok failed: %+v", res)
|
||||||
|
}
|
||||||
|
if res.Ms < 1 {
|
||||||
|
t.Fatalf("ms=%d", res.Ms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProbeUDPReplyOK(t *testing.T) {
|
||||||
|
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer pc.Close()
|
||||||
|
go func() {
|
||||||
|
buf := make([]byte, 64)
|
||||||
|
n, addr, err := pc.ReadFrom(buf)
|
||||||
|
if err != nil || n == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _ = pc.WriteTo([]byte{1}, addr)
|
||||||
|
}()
|
||||||
|
_, port, err := net.SplitHostPort(pc.LocalAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
rtt, err := probeUDP(ctx, "127.0.0.1", port)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if rtt <= 0 {
|
||||||
|
t.Fatalf("rtt=%v", rtt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const CurrentVersion = "3.8.0"
|
|||||||
|
|
||||||
// BuildNumber is the monotonic build within CurrentVersion (Windows FileVersion 4th part,
|
// BuildNumber is the monotonic build within CurrentVersion (Windows FileVersion 4th part,
|
||||||
// macOS CFBundleVersion suffix, Android versionCode low digits). Bump on every release build.
|
// macOS CFBundleVersion suffix, Android versionCode low digits). Bump on every release build.
|
||||||
const BuildNumber = 2
|
const BuildNumber = 3
|
||||||
|
|
||||||
// DefaultManifestURL is the update feed (hosted in the project git repo).
|
// DefaultManifestURL is the update feed (hosted in the project git repo).
|
||||||
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
|
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ h = hashlib.sha256(binp.read_bytes()).hexdigest()
|
|||||||
zh = hashlib.sha256(zipp.read_bytes()).hexdigest() if zipp.exists() else ""
|
zh = hashlib.sha256(zipp.read_bytes()).hexdigest() if zipp.exists() else ""
|
||||||
dh = hashlib.sha256(dmgp.read_bytes()).hexdigest() if dmgp.exists() else ""
|
dh = hashlib.sha256(dmgp.read_bytes()).hexdigest() if dmgp.exists() else ""
|
||||||
notes = (
|
notes = (
|
||||||
f"Navis {ver}+{build}: Mac .app zip update; EnsureCore lock; "
|
f"Navis {ver}+{build}: UDP ping Hy2/AWG (soft-ok без ложных «недоступен»); "
|
||||||
f"getState без секретов; подпись/notarize pipeline; UI split."
|
f"Mac .app zip update; EnsureCore lock; getState без секретов."
|
||||||
)
|
)
|
||||||
paths = [
|
paths = [
|
||||||
Path('dist/update.json'),
|
Path('dist/update.json'),
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "3.8.0",
|
"version": "3.8.0",
|
||||||
"notes": "Navis 3.8.0+2: Mac .app zip update; EnsureCore lock; getState без секретов; подпись/notarize pipeline; UI split.",
|
"notes": "Navis 3.8.0+3: UDP ping Hy2/AWG (soft-ok без ложных «недоступен»); Mac .app zip update; EnsureCore lock; getState без секретов.",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
@@ -16,13 +16,13 @@
|
|||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "6e15ad79e5ec1a1f74c48bc8f189ab8694b8f3f67f4be204420a12cf0fd622fd",
|
"sha256": "bd507de6f434f53f95954c8e411cc1f8bb526d5b5353b1242de5bc9fb673670f",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64",
|
"arch": "arm64",
|
||||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip",
|
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip",
|
||||||
"zip_sha256": "65041e154356a33525b9769f851bcccfc79d0c2a1200fb9a47bc22dd95cdf2ef",
|
"zip_sha256": "2aaac597f7246c67fc825cd11f49d2b4fc0fa6bd9b89a1b1e4290e6a96c01de4",
|
||||||
"dmg_sha256": "46617b7cbf22e92a5ef85740ed9473cd1bc9219c9de5841ce0ac46b8eb946912"
|
"dmg_sha256": "26ddacc3b3bc372aa4833336e60fb32862fb30ee555a8a6e460811f45f9f5cee"
|
||||||
},
|
},
|
||||||
"darwin-amd64": {
|
"darwin-amd64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||||
|
|||||||
+4
-4
@@ -4,13 +4,13 @@
|
|||||||
"Major": 3,
|
"Major": 3,
|
||||||
"Minor": 8,
|
"Minor": 8,
|
||||||
"Patch": 0,
|
"Patch": 0,
|
||||||
"Build": 2
|
"Build": 3
|
||||||
},
|
},
|
||||||
"ProductVersion": {
|
"ProductVersion": {
|
||||||
"Major": 3,
|
"Major": 3,
|
||||||
"Minor": 8,
|
"Minor": 8,
|
||||||
"Patch": 0,
|
"Patch": 0,
|
||||||
"Build": 2
|
"Build": 3
|
||||||
},
|
},
|
||||||
"FileFlagsMask": "3f",
|
"FileFlagsMask": "3f",
|
||||||
"FileFlags": "00",
|
"FileFlags": "00",
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
"StringFileInfo": {
|
"StringFileInfo": {
|
||||||
"CompanyName": "EvilFox",
|
"CompanyName": "EvilFox",
|
||||||
"FileDescription": "Navis — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
|
"FileDescription": "Navis — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
|
||||||
"FileVersion": "3.8.0.2",
|
"FileVersion": "3.8.0.3",
|
||||||
"InternalName": "Navis",
|
"InternalName": "Navis",
|
||||||
"LegalCopyright": "Copyright (c) EvilFox",
|
"LegalCopyright": "Copyright (c) EvilFox",
|
||||||
"OriginalFilename": "Navis.exe",
|
"OriginalFilename": "Navis.exe",
|
||||||
"ProductName": "Navis",
|
"ProductName": "Navis",
|
||||||
"ProductVersion": "3.8.0.2",
|
"ProductVersion": "3.8.0.3",
|
||||||
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
||||||
},
|
},
|
||||||
"VarFileInfo": {
|
"VarFileInfo": {
|
||||||
|
|||||||
Reference in New Issue
Block a user