Release 2.6.2: disconnect AWG without freezing the UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Navis
2026-07-29 15:50:14 +03:00
co-authored by Cursor
parent 4ecfb9bed7
commit 6255a0d39b
22 changed files with 109 additions and 55 deletions
+3
View File
@@ -243,6 +243,9 @@ https://evilfox.win/
Некоторые AV (Bkav, Microsoft Wacapew/Wacatac, Ikarus Trojan.WinGo.Agent, Google, Trapmine) часто помечают **любые** неподписанные Go-бинарники с сетью и сменой системного прокси. Некоторые AV (Bkav, Microsoft Wacapew/Wacatac, Ikarus Trojan.WinGo.Agent, Google, Trapmine) часто помечают **любые** неподписанные Go-бинарники с сетью и сменой системного прокси.
В 2.6.2:
- быстрое отключение AWG: принудительно закрываются прокси-соединения, UI больше не зависает.
В 2.6.1: В 2.6.1:
- AmneziaWG: перед подключением Endpoint-хост резолвится в IP (предпочтительно IPv4) — обход сбоя IpcSet на Windows («No such host is known»). - AmneziaWG: перед подключением Endpoint-хост резолвится в IP (предпочтительно IPv4) — обход сбоя IpcSet на Windows («No such host is known»).
+3 -3
View File
@@ -28,11 +28,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 2.6.1 -arch arm64 tools\packmac\packmac.exe -bin "dist\navis-release\darwin-arm64\Navis" -out "dist\navis-release\darwin-arm64" -version 2.6.2 -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 2.6.1 -arch amd64 tools\packmac\packmac.exe -bin "dist\navis-release\darwin-amd64\Navis" -out "dist\navis-release\darwin-amd64" -version 2.6.2 -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 2.6.1 -arch universal tools\packmac\packmac.exe -bin "dist\navis-release\darwin-universal\Navis" -out "dist\navis-release\darwin-universal" -version 2.6.2 -arch universal
if errorlevel 1 exit /b 1 if errorlevel 1 exit /b 1
echo Built: echo Built:
+1 -2
View File
@@ -296,8 +296,7 @@ func (a *app) connectProfile(name string) error {
} }
func (a *app) disconnect() error { func (a *app) disconnect() error {
a.mu.Lock() // Do not hold a.mu across engine teardown — getState polling would freeze the UI.
defer a.mu.Unlock()
return a.mgr.Disconnect() return a.mgr.Disconnect()
} }
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+7 -7
View File
@@ -1,22 +1,22 @@
{ {
"version": "2.6.1", "version": "2.6.2",
"notes": "AWG: любой hostname Endpoint резолвится в IP до подключения (фикс No such host is known)", "notes": "Быстрое отключение AWG без зависания UI («приложение не отвечает»)",
"platform": "windows-amd64", "platform": "windows-amd64",
"os": "windows", "os": "windows",
"arch": "amd64", "arch": "amd64",
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
"sha256": "08f001a3850ca5bd4f73b7ba4d21e8664ee9fc8120a87877f35d8f20a5ed6993", "sha256": "14fe9afb7978433a811662175ed21e9f65e66420c105ef943ca6f11aeeada072",
"mandatory": false, "mandatory": false,
"platforms": { "platforms": {
"windows-amd64": { "windows-amd64": {
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
"sha256": "08f001a3850ca5bd4f73b7ba4d21e8664ee9fc8120a87877f35d8f20a5ed6993", "sha256": "14fe9afb7978433a811662175ed21e9f65e66420c105ef943ca6f11aeeada072",
"os": "windows", "os": "windows",
"arch": "amd64" "arch": "amd64"
}, },
"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": "b67e8b3fb5db8b97f85dba4c0d307c137c67fb6b56b36f8b2a7adf327ff226d4", "sha256": "497cdf66b74e28061622debbbc6fa922ae64ae532e867dec876188af15e85278",
"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",
@@ -24,7 +24,7 @@
}, },
"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",
"sha256": "37385c52cb397f60acc699adecb0ffc1843106d50288b1304393daf63083b4b7", "sha256": "95ccb649116bd15cbcdddccdd57df77651bf5f41ec19a4c6a0e91f8139621df7",
"os": "darwin", "os": "darwin",
"arch": "amd64", "arch": "amd64",
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg", "dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg",
@@ -32,7 +32,7 @@
}, },
"darwin-universal": { "darwin-universal": {
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis",
"sha256": "ce250733cc7f5ed50b42f5cc106be9872b057966e7a73bcee78974d85748c2fb", "sha256": "abdb4d5807145dfab7afa1fc9fd4d0382a4f5d9b4ce7621128b2b393c7f0c928",
"os": "darwin", "os": "darwin",
"arch": "universal", "arch": "universal",
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg", "dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg",
+7 -7
View File
@@ -1,22 +1,22 @@
{ {
"version": "2.6.1", "version": "2.6.2",
"notes": "AWG: любой hostname Endpoint резолвится в IP до подключения (фикс No such host is known)", "notes": "Быстрое отключение AWG без зависания UI («приложение не отвечает»)",
"platform": "windows-amd64", "platform": "windows-amd64",
"os": "windows", "os": "windows",
"arch": "amd64", "arch": "amd64",
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
"sha256": "08f001a3850ca5bd4f73b7ba4d21e8664ee9fc8120a87877f35d8f20a5ed6993", "sha256": "14fe9afb7978433a811662175ed21e9f65e66420c105ef943ca6f11aeeada072",
"mandatory": false, "mandatory": false,
"platforms": { "platforms": {
"windows-amd64": { "windows-amd64": {
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
"sha256": "08f001a3850ca5bd4f73b7ba4d21e8664ee9fc8120a87877f35d8f20a5ed6993", "sha256": "14fe9afb7978433a811662175ed21e9f65e66420c105ef943ca6f11aeeada072",
"os": "windows", "os": "windows",
"arch": "amd64" "arch": "amd64"
}, },
"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": "b67e8b3fb5db8b97f85dba4c0d307c137c67fb6b56b36f8b2a7adf327ff226d4", "sha256": "497cdf66b74e28061622debbbc6fa922ae64ae532e867dec876188af15e85278",
"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",
@@ -24,7 +24,7 @@
}, },
"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",
"sha256": "37385c52cb397f60acc699adecb0ffc1843106d50288b1304393daf63083b4b7", "sha256": "95ccb649116bd15cbcdddccdd57df77651bf5f41ec19a4c6a0e91f8139621df7",
"os": "darwin", "os": "darwin",
"arch": "amd64", "arch": "amd64",
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg", "dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg",
@@ -32,7 +32,7 @@
}, },
"darwin-universal": { "darwin-universal": {
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis",
"sha256": "ce250733cc7f5ed50b42f5cc106be9872b057966e7a73bcee78974d85748c2fb", "sha256": "abdb4d5807145dfab7afa1fc9fd4d0382a4f5d9b4ce7621128b2b393c7f0c928",
"os": "darwin", "os": "darwin",
"arch": "universal", "arch": "universal",
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg", "dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg",
+1 -1
View File
@@ -725,7 +725,7 @@
<div class="brand-wrap"> <div class="brand-wrap">
<div class="brand-row"> <div class="brand-row">
<h1 class="brand">Navis</h1> <h1 class="brand">Navis</h1>
<span class="badge-ver">2.6.1</span> <span class="badge-ver">2.6.2</span>
</div> </div>
<p class="tagline">Быстрый клиент · Naive · Hy2 · AWG · Xray</p> <p class="tagline">Быстрый клиент · Naive · Hy2 · AWG · Xray</p>
</div> </div>
+20 -8
View File
@@ -100,21 +100,33 @@ func (m *Manager) Connect(ctx context.Context, profileName string) error {
func (m *Manager) Disconnect() error { func (m *Manager) Disconnect() error {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() sys := m.sys
engine := m.engine
m.engine = nil
m.profile = nil
m.mu.Unlock()
var first error var first error
if m.sys.Enabled() { if sys != nil && sys.Enabled() {
if err := m.sys.Disable(); err != nil && first == nil { if err := sys.Disable(); err != nil && first == nil {
first = err first = err
} }
} }
if m.engine != nil { if engine != nil {
if err := m.engine.Stop(); err != nil && first == nil { done := make(chan error, 1)
first = err go func() { done <- engine.Stop() }()
select {
case err := <-done:
if err != nil && first == nil {
first = err
}
case <-time.After(3 * time.Second):
// Engine Stop can block on userspace relays; don't freeze the UI.
if first == nil {
first = fmt.Errorf("отключение заняло слишком много времени")
}
} }
m.engine = nil
} }
m.profile = nil
return first return first
} }
+5 -4
View File
@@ -120,15 +120,16 @@ func (e *Engine) stopLocked() error {
if !e.running { if !e.running {
return nil return nil
} }
if e.proxies != nil { // Close device first so tun/netstack dials fail and relays exit promptly.
_ = e.proxies.Close()
e.proxies = nil
}
if e.dev != nil { if e.dev != nil {
e.dev.Close() e.dev.Close()
e.dev = nil e.dev = nil
} }
e.tnet = nil e.tnet = nil
if e.proxies != nil {
_ = e.proxies.Close()
e.proxies = nil
}
e.running = false e.running = false
return nil return nil
} }
+50 -11
View File
@@ -17,18 +17,22 @@ import (
type DialFunc func(ctx context.Context, network, address string) (net.Conn, error) type DialFunc func(ctx context.Context, network, address string) (net.Conn, error)
type proxyServer struct { type proxyServer struct {
mu sync.Mutex mu sync.Mutex
socksLn net.Listener socksLn net.Listener
httpLn net.Listener httpLn net.Listener
dial DialFunc dial DialFunc
wg sync.WaitGroup wg sync.WaitGroup
closed bool closed bool
socksAddr string socksAddr string
httpAddr string httpAddr string
conns map[net.Conn]struct{}
} }
func startProxies(socksHostPort, httpHostPort string, dial DialFunc) (*proxyServer, error) { func startProxies(socksHostPort, httpHostPort string, dial DialFunc) (*proxyServer, error) {
s := &proxyServer{dial: dial} s := &proxyServer{
dial: dial,
conns: make(map[net.Conn]struct{}),
}
if socksHostPort != "" { if socksHostPort != "" {
ln, err := net.Listen("tcp", socksHostPort) ln, err := net.Listen("tcp", socksHostPort)
if err != nil { if err != nil {
@@ -53,6 +57,22 @@ func startProxies(socksHostPort, httpHostPort string, dial DialFunc) (*proxyServ
return s, nil return s, nil
} }
func (s *proxyServer) track(c net.Conn) {
s.mu.Lock()
defer s.mu.Unlock()
if s.closed {
_ = c.Close()
return
}
s.conns[c] = struct{}{}
}
func (s *proxyServer) untrack(c net.Conn) {
s.mu.Lock()
defer s.mu.Unlock()
delete(s.conns, c)
}
func (s *proxyServer) Close() error { func (s *proxyServer) Close() error {
s.mu.Lock() s.mu.Lock()
if s.closed { if s.closed {
@@ -66,8 +86,23 @@ func (s *proxyServer) Close() error {
if s.httpLn != nil { if s.httpLn != nil {
_ = s.httpLn.Close() _ = s.httpLn.Close()
} }
// Force-close active relays so io.Copy / dial wake up immediately.
for c := range s.conns {
_ = c.Close()
}
s.conns = nil
s.mu.Unlock() s.mu.Unlock()
s.wg.Wait()
done := make(chan struct{})
go func() {
s.wg.Wait()
close(done)
}()
select {
case <-done:
case <-time.After(1500 * time.Millisecond):
// Don't hang UI / Disconnect on stuck netstack copies.
}
return nil return nil
} }
@@ -81,6 +116,8 @@ func (s *proxyServer) serveSOCKS() {
s.wg.Add(1) s.wg.Add(1)
go func(conn net.Conn) { go func(conn net.Conn) {
defer s.wg.Done() defer s.wg.Done()
s.track(conn)
defer s.untrack(conn)
_ = handleSOCKS(conn, s.dial) _ = handleSOCKS(conn, s.dial)
}(c) }(c)
} }
@@ -96,6 +133,8 @@ func (s *proxyServer) serveHTTP() {
s.wg.Add(1) s.wg.Add(1)
go func(conn net.Conn) { go func(conn net.Conn) {
defer s.wg.Done() defer s.wg.Done()
s.track(conn)
defer s.untrack(conn)
_ = handleHTTPProxy(conn, s.dial) _ = handleHTTPProxy(conn, s.dial)
}(c) }(c)
} }
@@ -156,7 +195,7 @@ func handleSOCKS(client net.Conn, dial DialFunc) error {
port := binary.BigEndian.Uint16(buf[:2]) port := binary.BigEndian.Uint16(buf[:2])
_ = client.SetDeadline(time.Time{}) _ = client.SetDeadline(time.Time{})
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
remote, err := dial(ctx, "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port))) remote, err := dial(ctx, "tcp", net.JoinHostPort(host, fmt.Sprintf("%d", port)))
if err != nil { if err != nil {
@@ -185,7 +224,7 @@ func handleHTTPProxy(client net.Conn, dial DialFunc) error {
if !strings.Contains(host, ":") { if !strings.Contains(host, ":") {
host += ":443" host += ":443"
} }
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
remote, err := dial(ctx, "tcp", host) remote, err := dial(ctx, "tcp", host)
if err != nil { if err != nil {
@@ -212,7 +251,7 @@ func handleHTTPProxy(client net.Conn, dial DialFunc) error {
if !strings.Contains(host, ":") { if !strings.Contains(host, ":") {
host += ":80" host += ":80"
} }
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
remote, err := dial(ctx, "tcp", host) remote, err := dial(ctx, "tcp", host)
if err != nil { if err != nil {
+1 -1
View File
@@ -17,7 +17,7 @@ import (
) )
// CurrentVersion is the shipped client version. // CurrentVersion is the shipped client version.
const CurrentVersion = "2.6.1" const CurrentVersion = "2.6.2"
// 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"
+7 -7
View File
@@ -1,22 +1,22 @@
{ {
"version": "2.6.1", "version": "2.6.2",
"notes": "AWG: любой hostname Endpoint резолвится в IP до подключения (фикс No such host is known)", "notes": "Быстрое отключение AWG без зависания UI («приложение не отвечает»)",
"platform": "windows-amd64", "platform": "windows-amd64",
"os": "windows", "os": "windows",
"arch": "amd64", "arch": "amd64",
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
"sha256": "08f001a3850ca5bd4f73b7ba4d21e8664ee9fc8120a87877f35d8f20a5ed6993", "sha256": "14fe9afb7978433a811662175ed21e9f65e66420c105ef943ca6f11aeeada072",
"mandatory": false, "mandatory": false,
"platforms": { "platforms": {
"windows-amd64": { "windows-amd64": {
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
"sha256": "08f001a3850ca5bd4f73b7ba4d21e8664ee9fc8120a87877f35d8f20a5ed6993", "sha256": "14fe9afb7978433a811662175ed21e9f65e66420c105ef943ca6f11aeeada072",
"os": "windows", "os": "windows",
"arch": "amd64" "arch": "amd64"
}, },
"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": "b67e8b3fb5db8b97f85dba4c0d307c137c67fb6b56b36f8b2a7adf327ff226d4", "sha256": "497cdf66b74e28061622debbbc6fa922ae64ae532e867dec876188af15e85278",
"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",
@@ -24,7 +24,7 @@
}, },
"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",
"sha256": "37385c52cb397f60acc699adecb0ffc1843106d50288b1304393daf63083b4b7", "sha256": "95ccb649116bd15cbcdddccdd57df77651bf5f41ec19a4c6a0e91f8139621df7",
"os": "darwin", "os": "darwin",
"arch": "amd64", "arch": "amd64",
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg", "dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg",
@@ -32,7 +32,7 @@
}, },
"darwin-universal": { "darwin-universal": {
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis", "url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis",
"sha256": "ce250733cc7f5ed50b42f5cc106be9872b057966e7a73bcee78974d85748c2fb", "sha256": "abdb4d5807145dfab7afa1fc9fd4d0382a4f5d9b4ce7621128b2b393c7f0c928",
"os": "darwin", "os": "darwin",
"arch": "universal", "arch": "universal",
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg", "dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg",
+4 -4
View File
@@ -1,7 +1,7 @@
{ {
"FixedFileInfo": { "FixedFileInfo": {
"FileVersion": { "Major": 2, "Minor": 6, "Patch": 1, "Build": 0 }, "FileVersion": { "Major": 2, "Minor": 6, "Patch": 2, "Build": 0 },
"ProductVersion": { "Major": 2, "Minor": 6, "Patch": 1, "Build": 0 }, "ProductVersion": { "Major": 2, "Minor": 6, "Patch": 2, "Build": 0 },
"FileFlagsMask": "3f", "FileFlagsMask": "3f",
"FileFlags": "00", "FileFlags": "00",
"FileOS": "40004", "FileOS": "40004",
@@ -11,12 +11,12 @@
"StringFileInfo": { "StringFileInfo": {
"CompanyName": "EvilFox", "CompanyName": "EvilFox",
"FileDescription": "Navis 2 — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)", "FileDescription": "Navis 2 — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
"FileVersion": "2.6.1.0", "FileVersion": "2.6.2.0",
"InternalName": "Navis", "InternalName": "Navis",
"LegalCopyright": "Copyright (c) EvilFox", "LegalCopyright": "Copyright (c) EvilFox",
"OriginalFilename": "Navis.exe", "OriginalFilename": "Navis.exe",
"ProductName": "Navis", "ProductName": "Navis",
"ProductVersion": "2.6.1.0", "ProductVersion": "2.6.2.0",
"Comments": "Open-source VPN/proxy client. https://evilfox.win/" "Comments": "Open-source VPN/proxy client. https://evilfox.win/"
}, },
"VarFileInfo": { "VarFileInfo": {