Forráskód Böngészése

fix(sub): make Happ require auth on its local SOCKS/HTTP proxy (#6628)

Happ ships its local SOCKS5 (127.0.0.1:10808) and HTTP inbounds with
authorization disabled by default. Any app on the same device can then
connect to that proxy, bypassing Android's per-app VPN routing, and learn
the VPN server address - the leak publicly described in March-April 2026
for Happ, v2rayNG and other VLESS clients. Happ fixed its Xray API
exposure, but the unauthenticated local proxy remained.

Happ exposes a standard subscription header for this (no Provider ID
required): socks-auth-mode / http-auth-mode = auto|manual|from-json|
disable. A new subscription setting, subHappLocalProxyAuth (default
"auto"), sends both headers to Happ clients. Like every other Happ header
it is emitted only when Happ auto-detect is enabled and the User-Agent is
Happ, so panels that never opted into the Happ integration see no change.
An empty value sends nothing and keeps the client's own setting.

Verified on Happ Android 4.4.1 (Xray 26.7.28): a subscription carrying
socks-auth-mode manual + a test user/password switched the client's
Inbounds screen to Manual with those credentials on "refresh subscription",
and "auto" switched it to Auto with generated credentials.

Co-authored-by: Kirill Rudenko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Sanaei <[email protected]>
Kirill Rudenko 7 órája
szülő
commit
6ab718f813

+ 8 - 0
docs/public/openapi.json

@@ -288,6 +288,9 @@
           "subHappFallbackUrl": {
             "type": "string"
           },
+          "subHappLocalProxyAuth": {
+            "type": "string"
+          },
           "subHappNewUrl": {
             "type": "string"
           },
@@ -586,6 +589,7 @@
           "subHappExcludeApns",
           "subHappExcludeRoutes",
           "subHappFallbackUrl",
+          "subHappLocalProxyAuth",
           "subHappNewUrl",
           "subHappNoLimit",
           "subHappNotificationExpire",
@@ -943,6 +947,9 @@
           "subHappFallbackUrl": {
             "type": "string"
           },
+          "subHappLocalProxyAuth": {
+            "type": "string"
+          },
           "subHappNewUrl": {
             "type": "string"
           },
@@ -1249,6 +1256,7 @@
           "subHappExcludeApns",
           "subHappExcludeRoutes",
           "subHappFallbackUrl",
+          "subHappLocalProxyAuth",
           "subHappNewUrl",
           "subHappNoLimit",
           "subHappNotificationExpire",

+ 8 - 0
frontend/public/openapi.json

@@ -288,6 +288,9 @@
           "subHappFallbackUrl": {
             "type": "string"
           },
+          "subHappLocalProxyAuth": {
+            "type": "string"
+          },
           "subHappNewUrl": {
             "type": "string"
           },
@@ -586,6 +589,7 @@
           "subHappExcludeApns",
           "subHappExcludeRoutes",
           "subHappFallbackUrl",
+          "subHappLocalProxyAuth",
           "subHappNewUrl",
           "subHappNoLimit",
           "subHappNotificationExpire",
@@ -943,6 +947,9 @@
           "subHappFallbackUrl": {
             "type": "string"
           },
+          "subHappLocalProxyAuth": {
+            "type": "string"
+          },
           "subHappNewUrl": {
             "type": "string"
           },
@@ -1249,6 +1256,7 @@
           "subHappExcludeApns",
           "subHappExcludeRoutes",
           "subHappFallbackUrl",
+          "subHappLocalProxyAuth",
           "subHappNewUrl",
           "subHappNoLimit",
           "subHappNotificationExpire",

+ 2 - 0
frontend/src/generated/examples.ts

@@ -80,6 +80,7 @@ export const EXAMPLES: Record<string, unknown> = {
     "subHappExcludeApns": false,
     "subHappExcludeRoutes": "",
     "subHappFallbackUrl": "",
+    "subHappLocalProxyAuth": "",
     "subHappNewUrl": "",
     "subHappNoLimit": false,
     "subHappNotificationExpire": false,
@@ -237,6 +238,7 @@ export const EXAMPLES: Record<string, unknown> = {
     "subHappExcludeApns": false,
     "subHappExcludeRoutes": "",
     "subHappFallbackUrl": "",
+    "subHappLocalProxyAuth": "",
     "subHappNewUrl": "",
     "subHappNoLimit": false,
     "subHappNotificationExpire": false,

+ 8 - 0
frontend/src/generated/schemas.ts

@@ -262,6 +262,9 @@ export const SCHEMAS: Record<string, unknown> = {
       "subHappFallbackUrl": {
         "type": "string"
       },
+      "subHappLocalProxyAuth": {
+        "type": "string"
+      },
       "subHappNewUrl": {
         "type": "string"
       },
@@ -560,6 +563,7 @@ export const SCHEMAS: Record<string, unknown> = {
       "subHappExcludeApns",
       "subHappExcludeRoutes",
       "subHappFallbackUrl",
+      "subHappLocalProxyAuth",
       "subHappNewUrl",
       "subHappNoLimit",
       "subHappNotificationExpire",
@@ -917,6 +921,9 @@ export const SCHEMAS: Record<string, unknown> = {
       "subHappFallbackUrl": {
         "type": "string"
       },
+      "subHappLocalProxyAuth": {
+        "type": "string"
+      },
       "subHappNewUrl": {
         "type": "string"
       },
@@ -1223,6 +1230,7 @@ export const SCHEMAS: Record<string, unknown> = {
       "subHappExcludeApns",
       "subHappExcludeRoutes",
       "subHappFallbackUrl",
+      "subHappLocalProxyAuth",
       "subHappNewUrl",
       "subHappNoLimit",
       "subHappNotificationExpire",

+ 2 - 0
frontend/src/generated/types.ts

@@ -87,6 +87,7 @@ export interface AllSetting {
   subHappExcludeApns: boolean;
   subHappExcludeRoutes: string;
   subHappFallbackUrl: string;
+  subHappLocalProxyAuth: string;
   subHappNewUrl: string;
   subHappNoLimit: boolean;
   subHappNotificationExpire: boolean;
@@ -245,6 +246,7 @@ export interface AllSettingView {
   subHappExcludeApns: boolean;
   subHappExcludeRoutes: string;
   subHappFallbackUrl: string;
+  subHappLocalProxyAuth: string;
   subHappNewUrl: string;
   subHappNoLimit: boolean;
   subHappNotificationExpire: boolean;

+ 2 - 0
frontend/src/generated/zod.ts

@@ -101,6 +101,7 @@ export const AllSettingSchema = z.object({
   subHappExcludeApns: z.boolean(),
   subHappExcludeRoutes: z.string(),
   subHappFallbackUrl: z.string(),
+  subHappLocalProxyAuth: z.string(),
   subHappNewUrl: z.string(),
   subHappNoLimit: z.boolean(),
   subHappNotificationExpire: z.boolean(),
@@ -260,6 +261,7 @@ export const AllSettingViewSchema = z.object({
   subHappExcludeApns: z.boolean(),
   subHappExcludeRoutes: z.string(),
   subHappFallbackUrl: z.string(),
+  subHappLocalProxyAuth: z.string(),
   subHappNewUrl: z.string(),
   subHappNoLimit: z.boolean(),
   subHappNotificationExpire: z.boolean(),

+ 1 - 0
frontend/src/models/setting.ts

@@ -104,6 +104,7 @@ export class AllSetting {
   subHappAutoConnectType = 'lowestdelay';
   subHappPerAppMode = 'off';
   subHappPerAppList = '';
+  subHappLocalProxyAuth = 'auto';
 
   timeLocation = 'Local';
 

+ 17 - 0
frontend/src/pages/settings/HappSettingsContent.tsx

@@ -382,6 +382,23 @@ export default function HappSettingsContent({
                   />
                 </SettingListItem>
 
+                <SettingListItem
+                  paddings="small"
+                  title={t('pages.settings.subHappLocalProxyAuth')}
+                  description={t('pages.settings.subHappLocalProxyAuthDesc')}
+                >
+                  <Select
+                    value={allSetting.subHappLocalProxyAuth ?? 'auto'}
+                    style={{ width: '100%' }}
+                    onChange={(v) => updateSetting({ subHappLocalProxyAuth: v })}
+                    options={[
+                      { value: 'auto', label: t('pages.settings.subHappLocalProxyAuthAuto') },
+                      { value: 'disable', label: t('pages.settings.subHappLocalProxyAuthDisable') },
+                      { value: '', label: t('pages.settings.subHappLocalProxyAuthUnset') },
+                    ]}
+                  />
+                </SettingListItem>
+
                 <SettingListItem
                   paddings="small"
                   title={t('pages.settings.subHappAutoConnect')}

+ 1 - 0
frontend/src/schemas/setting.ts

@@ -109,6 +109,7 @@ export const AllSettingSchema = z
     subHappAutoConnectType: z.string().optional(),
     subHappPerAppMode: z.string().optional(),
     subHappPerAppList: z.string().optional(),
+    subHappLocalProxyAuth: z.string().optional(),
     timeLocation: z.string().optional(),
     ldapEnable: z.boolean().optional(),
     ldapHost: z.string().optional(),

+ 7 - 0
internal/sub/happ.go

@@ -34,6 +34,7 @@ type HappConfig struct {
 	AutoConnectType     string
 	PerAppMode          string
 	PerAppList          string
+	LocalProxyAuth      string
 }
 
 // IsHappClient checks if the client user-agent identifies as Happ.
@@ -129,6 +130,12 @@ func ApplyHappHeaders(c *gin.Context, cfg HappConfig, isHapp bool) {
 			c.Writer.Header().Set("Subscription-Autoconnect-Type", autoType)
 		}
 	}
+	// Happ's local SOCKS/HTTP inbounds default to no auth, so any app on the device can use them
+	// to reach the tunnel and learn the server address; these are standard headers (no ProviderID).
+	if mode := strings.TrimSpace(cfg.LocalProxyAuth); mode != "" {
+		c.Writer.Header().Set("Socks-Auth-Mode", mode)
+		c.Writer.Header().Set("Http-Auth-Mode", mode)
+	}
 	if mode := strings.TrimSpace(cfg.PerAppMode); mode != "" && mode != "off" {
 		switch strings.ToLower(mode) {
 		case "include":

+ 34 - 0
internal/sub/happ_test.go

@@ -348,3 +348,37 @@ func TestIsHappClient(t *testing.T) {
 		}
 	}
 }
+
+func TestApplyHappHeaders_LocalProxyAuth(t *testing.T) {
+	gin.SetMode(gin.TestMode)
+	cases := []struct {
+		name       string
+		autoDetect bool
+		userAgent  string
+		mode       string
+		want       string
+	}{
+		{"Happ gets auto for both inbounds", true, "Happ/4.4.1 (Android)", "auto", "auto"},
+		{"explicit disable is forwarded", true, "Happ/4.4.1 (Android)", "disable", "disable"},
+		{"empty mode sends nothing", true, "Happ/4.4.1 (Android)", "", ""},
+		{"non-Happ client gets nothing", true, "v2rayNG/1.8.5", "auto", ""},
+		{"AutoDetect off sends nothing", false, "Happ/4.4.1 (Android)", "auto", ""},
+	}
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			recorder := httptest.NewRecorder()
+			ctx, _ := gin.CreateTestContext(recorder)
+			ctx.Request = httptest.NewRequest(http.MethodGet, "/sub/test", nil)
+			ctx.Request.Header.Set("User-Agent", tc.userAgent)
+
+			controller := &SUBController{happConfig: HappConfig{AutoDetect: tc.autoDetect, LocalProxyAuth: tc.mode}}
+			controller.ApplyCommonHeaders(ctx, "", "", "Title", "", "", "", false, "", false)
+
+			for _, h := range []string{"Socks-Auth-Mode", "Http-Auth-Mode"} {
+				if got := recorder.Header().Get(h); got != tc.want {
+					t.Fatalf("%s = %q, want %q", h, got, tc.want)
+				}
+			}
+		})
+	}
+}

+ 1 - 0
internal/sub/sub.go

@@ -253,6 +253,7 @@ func (s *Server) initRouter() (*gin.Engine, error) {
 	happCfg.AutoConnectType, _ = s.settingService.GetSubHappAutoConnectType()
 	happCfg.PerAppMode, _ = s.settingService.GetSubHappPerAppMode()
 	happCfg.PerAppList, _ = s.settingService.GetSubHappPerAppList()
+	happCfg.LocalProxyAuth, _ = s.settingService.GetSubHappLocalProxyAuth()
 
 	// set per-request localizer from headers/cookies
 	engine.Use(locale.LocalizerMiddleware())

+ 1 - 0
internal/web/entity/entity.go

@@ -153,6 +153,7 @@ type AllSetting struct {
 	SubHappAutoConnectType     string `json:"subHappAutoConnectType" form:"subHappAutoConnectType"`
 	SubHappPerAppMode          string `json:"subHappPerAppMode" form:"subHappPerAppMode"`
 	SubHappPerAppList          string `json:"subHappPerAppList" form:"subHappPerAppList"`
+	SubHappLocalProxyAuth      string `json:"subHappLocalProxyAuth" form:"subHappLocalProxyAuth"`
 
 	LdapEnable             bool   `json:"ldapEnable" form:"ldapEnable"`
 	LdapHost               string `json:"ldapHost" form:"ldapHost"`

+ 5 - 0
internal/web/service/setting.go

@@ -137,6 +137,7 @@ var defaultValueMap = map[string]string{
 	"subHappAutoConnectType":      "lowestdelay",
 	"subHappPerAppMode":           "off",
 	"subHappPerAppList":           "",
+	"subHappLocalProxyAuth":       "auto",
 	"subIncyEnableRouting":        "false",
 	"subIncyRoutingRules":         "",
 	"subListen":                   "",
@@ -999,6 +1000,10 @@ func (s *SettingService) GetSubHappPerAppList() (string, error) {
 	return s.getString("subHappPerAppList")
 }
 
+func (s *SettingService) GetSubHappLocalProxyAuth() (string, error) {
+	return s.getString("subHappLocalProxyAuth")
+}
+
 func (s *SettingService) GetSubIncyEnableRouting() (bool, error) {
 	return s.getBool("subIncyEnableRouting")
 }

+ 5 - 0
internal/web/translation/ar-EG.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "سمة ألوان مخصصة لـ iOS كسلسلة JSON، أو resetcolors لاستعادة الألوان الافتراضية.",
       "subHappPingType": "طريقة قياس زمن الاستجابة",
       "subHappPingTypeDesc": "كيفية قياس Happ لزمن استجابة العقد: عبر البروكسي (GET أو HEAD) أو TCP أو ICMP.",
+      "subHappLocalProxyAuth": "مصادقة الوكيل المحلي",
+      "subHappLocalProxyAuthDesc": "يرسل إلى Happ الترويسات socks-auth-mode / http-auth-mode. بدون مصادقة يمكن لأي تطبيق على الجهاز استخدام وكيل SOCKS5/HTTP المحلي في Happ للوصول إلى النفق ومعرفة عنوان الخادم. \"تلقائي\" يجعل Happ ينشئ بيانات اعتماد عشوائية؛ لا يلزم Provider ID.",
+      "subHappLocalProxyAuthAuto": "تلقائي (بيانات اعتماد عشوائية)",
+      "subHappLocalProxyAuthDisable": "معطل",
+      "subHappLocalProxyAuthUnset": "عدم الإرسال (الافتراضي في العميل)",
       "subHappAutoConnect": "الاتصال التلقائي عند التشغيل",
       "subHappAutoConnectDesc": "يتصل Happ تلقائيًا بـ VPN عند بدء تشغيل التطبيق.",
       "subHappAutoConnectType": "هدف الاتصال التلقائي",

+ 5 - 0
internal/web/translation/en-US.json

@@ -1676,6 +1676,11 @@
       "subHappColorProfileDesc": "Custom iOS color theme as a JSON string, or resetcolors to restore the default colors.",
       "subHappPingType": "Latency Ping Method",
       "subHappPingTypeDesc": "How Happ measures node latency: via proxy (GET or HEAD), TCP, or ICMP.",
+      "subHappLocalProxyAuth": "Local Proxy Authorization",
+      "subHappLocalProxyAuthDesc": "Sends Happ socks-auth-mode / http-auth-mode. Without authorization, any app on the device can use Happ's local SOCKS5/HTTP proxy to reach the tunnel and learn the server address. \"Auto\" makes Happ generate random credentials; works without a Provider ID.",
+      "subHappLocalProxyAuthAuto": "Auto (random credentials)",
+      "subHappLocalProxyAuthDisable": "Disabled",
+      "subHappLocalProxyAuthUnset": "Not sent (client default)",
       "subHappAutoConnect": "Auto-Connect on Launch",
       "subHappAutoConnectDesc": "Instruct Happ to automatically connect to VPN when the application starts.",
       "subHappAutoConnectType": "Auto-Connect Target",

+ 5 - 0
internal/web/translation/es-ES.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "Tema de color personalizado para iOS como cadena JSON, o resetcolors para restaurar los colores predeterminados.",
       "subHappPingType": "Método de ping de latencia",
       "subHappPingTypeDesc": "Cómo mide Happ la latencia de los nodos: vía proxy (GET o HEAD), TCP o ICMP.",
+      "subHappLocalProxyAuth": "Autorización del proxy local",
+      "subHappLocalProxyAuthDesc": "Envía a Happ socks-auth-mode / http-auth-mode. Sin autorización, cualquier app del dispositivo puede usar el proxy SOCKS5/HTTP local de Happ para llegar al túnel y conocer la dirección del servidor. \"Auto\" hace que Happ genere credenciales aleatorias; no requiere Provider ID.",
+      "subHappLocalProxyAuthAuto": "Auto (credenciales aleatorias)",
+      "subHappLocalProxyAuthDisable": "Desactivada",
+      "subHappLocalProxyAuthUnset": "No enviar (predeterminado del cliente)",
       "subHappAutoConnect": "Conexión automática al iniciar",
       "subHappAutoConnectDesc": "Indicar a Happ que se conecte automáticamente a la VPN al iniciarse la aplicación.",
       "subHappAutoConnectType": "Destino de la conexión automática",

+ 5 - 0
internal/web/translation/fa-IR.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "تم رنگی سفارشی iOS به صورت رشته JSON، یا resetcolors برای بازگشت به رنگ‌های پیش‌فرض.",
       "subHappPingType": "روش تست پینگ",
       "subHappPingTypeDesc": "روش اندازه‌گیری تأخیر نودها در Happ: از طریق پروکسی (GET یا HEAD)، TCP یا ICMP.",
+      "subHappLocalProxyAuth": "احراز هویت پروکسی محلی",
+      "subHappLocalProxyAuthDesc": "هدرهای socks-auth-mode / http-auth-mode را به Happ می‌فرستد. بدون احراز هویت، هر برنامه‌ای روی دستگاه می‌تواند از پروکسی محلی SOCKS5/HTTP برنامه Happ به تونل برسد و نشانی سرور را بفهمد. «خودکار» باعث می‌شود Happ اعتبارنامه تصادفی بسازد؛ به Provider ID نیازی نیست.",
+      "subHappLocalProxyAuthAuto": "خودکار (اعتبارنامه تصادفی)",
+      "subHappLocalProxyAuthDisable": "غیرفعال",
+      "subHappLocalProxyAuthUnset": "ارسال نشود (پیش‌فرض کلاینت)",
       "subHappAutoConnect": "اتصال خودکار هنگام اجرا",
       "subHappAutoConnectDesc": "اتصال خودکار به وی‌پی‌ان با باز شدن برنامه Happ.",
       "subHappAutoConnectType": "راهبرد اتصال خودکار",

+ 5 - 0
internal/web/translation/id-ID.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "Tema warna iOS kustom sebagai string JSON, atau resetcolors untuk mengembalikan warna bawaan.",
       "subHappPingType": "Metode Ping Latensi",
       "subHappPingTypeDesc": "Cara Happ mengukur latensi node: melalui proxy (GET atau HEAD), TCP, atau ICMP.",
+      "subHappLocalProxyAuth": "Otorisasi Proxy Lokal",
+      "subHappLocalProxyAuthDesc": "Mengirim socks-auth-mode / http-auth-mode ke Happ. Tanpa otorisasi, aplikasi apa pun di perangkat dapat memakai proxy SOCKS5/HTTP lokal Happ untuk masuk ke terowongan dan mengetahui alamat server. \"Auto\" membuat Happ membuat kredensial acak; tidak memerlukan Provider ID.",
+      "subHappLocalProxyAuthAuto": "Auto (kredensial acak)",
+      "subHappLocalProxyAuthDisable": "Nonaktif",
+      "subHappLocalProxyAuthUnset": "Tidak dikirim (bawaan klien)",
       "subHappAutoConnect": "Hubungkan Otomatis saat Dibuka",
       "subHappAutoConnectDesc": "Minta Happ terhubung ke VPN secara otomatis saat aplikasi dimulai.",
       "subHappAutoConnectType": "Target Koneksi Otomatis",

+ 5 - 0
internal/web/translation/ja-JP.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "iOS 用のカスタムカラーテーマを JSON 文字列で指定します。デフォルトの色に戻すには resetcolors を指定します。",
       "subHappPingType": "遅延の測定方法",
       "subHappPingTypeDesc": "Happ がノードの遅延を測定する方法: プロキシ経由 (GET または HEAD)、TCP、または ICMP。",
+      "subHappLocalProxyAuth": "ローカルプロキシの認証",
+      "subHappLocalProxyAuthDesc": "Happ に socks-auth-mode / http-auth-mode を送信します。認証がないと、端末上のどのアプリも Happ のローカル SOCKS5/HTTP プロキシ経由でトンネルに入り、サーバーのアドレスを知ることができます。「自動」では Happ がランダムな認証情報を生成します。Provider ID は不要です。",
+      "subHappLocalProxyAuthAuto": "自動 (ランダムな認証情報)",
+      "subHappLocalProxyAuthDisable": "無効",
+      "subHappLocalProxyAuthUnset": "送信しない (クライアントの既定)",
       "subHappAutoConnect": "起動時に自動接続",
       "subHappAutoConnectDesc": "アプリの起動時に VPN へ自動接続するよう Happ に指示します。",
       "subHappAutoConnectType": "自動接続先",

+ 5 - 0
internal/web/translation/pt-BR.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "Tema de cores personalizado do iOS como string JSON, ou resetcolors para restaurar as cores padrão.",
       "subHappPingType": "Método de ping de latência",
       "subHappPingTypeDesc": "Como o Happ mede a latência dos nós: via proxy (GET ou HEAD), TCP ou ICMP.",
+      "subHappLocalProxyAuth": "Autorização do proxy local",
+      "subHappLocalProxyAuthDesc": "Envia ao Happ socks-auth-mode / http-auth-mode. Sem autorização, qualquer app do dispositivo pode usar o proxy SOCKS5/HTTP local do Happ para alcançar o túnel e descobrir o endereço do servidor. \"Auto\" faz o Happ gerar credenciais aleatórias; não requer Provider ID.",
+      "subHappLocalProxyAuthAuto": "Auto (credenciais aleatórias)",
+      "subHappLocalProxyAuthDisable": "Desativada",
+      "subHappLocalProxyAuthUnset": "Não enviar (padrão do cliente)",
       "subHappAutoConnect": "Conectar automaticamente ao iniciar",
       "subHappAutoConnectDesc": "Instrui o Happ a conectar automaticamente à VPN quando o aplicativo for iniciado.",
       "subHappAutoConnectType": "Destino da conexão automática",

+ 5 - 0
internal/web/translation/ru-RU.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "Своя цветовая тема для iOS в виде JSON-строки или resetcolors для сброса к стандартным цветам.",
       "subHappPingType": "Метод проверки пинга",
       "subHappPingTypeDesc": "Способ измерения задержки узлов в Happ: через прокси (GET или HEAD), TCP или ICMP.",
+      "subHappLocalProxyAuth": "Авторизация локального прокси",
+      "subHappLocalProxyAuthDesc": "Отправляет Happ заголовки socks-auth-mode / http-auth-mode. Без авторизации любое приложение на устройстве может через локальный SOCKS5/HTTP-прокси Happ попасть в туннель и узнать адрес сервера. «Авто» — Happ сам создаёт случайные учётные данные; Provider ID не нужен.",
+      "subHappLocalProxyAuthAuto": "Авто (случайные учётные данные)",
+      "subHappLocalProxyAuthDisable": "Отключена",
+      "subHappLocalProxyAuthUnset": "Не отправлять (по умолчанию клиента)",
       "subHappAutoConnect": "Автоподключение при запуске",
       "subHappAutoConnectDesc": "Автоматически подключаться к серверу при запуске приложения.",
       "subHappAutoConnectType": "Критерий автоподключения",

+ 5 - 0
internal/web/translation/tr-TR.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "JSON dizesi olarak özel iOS renk teması veya varsayılan renkleri geri yüklemek için resetcolors.",
       "subHappPingType": "Gecikme Ping Yöntemi",
       "subHappPingTypeDesc": "Happ'in düğüm gecikmesini ölçme yöntemi: proxy üzerinden (GET veya HEAD), TCP veya ICMP.",
+      "subHappLocalProxyAuth": "Yerel Proxy Yetkilendirmesi",
+      "subHappLocalProxyAuthDesc": "Happ'e socks-auth-mode / http-auth-mode gönderir. Yetkilendirme olmadan cihazdaki herhangi bir uygulama Happ'in yerel SOCKS5/HTTP proxy'sini kullanarak tünele erişebilir ve sunucu adresini öğrenebilir. \"Otomatik\" Happ'in rastgele kimlik bilgileri üretmesini sağlar; Provider ID gerekmez.",
+      "subHappLocalProxyAuthAuto": "Otomatik (rastgele kimlik bilgileri)",
+      "subHappLocalProxyAuthDisable": "Devre dışı",
+      "subHappLocalProxyAuthUnset": "Gönderilmez (istemci varsayılanı)",
       "subHappAutoConnect": "Açılışta Otomatik Bağlan",
       "subHappAutoConnectDesc": "Uygulama başladığında Happ'in VPN'e otomatik olarak bağlanmasını sağlar.",
       "subHappAutoConnectType": "Otomatik Bağlantı Hedefi",

+ 5 - 0
internal/web/translation/uk-UA.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "Власна колірна тема iOS у вигляді рядка JSON або resetcolors для відновлення стандартних кольорів.",
       "subHappPingType": "Метод вимірювання затримки",
       "subHappPingTypeDesc": "Як Happ вимірює затримку вузлів: через проксі (GET або HEAD), TCP або ICMP.",
+      "subHappLocalProxyAuth": "Авторизація локального проксі",
+      "subHappLocalProxyAuthDesc": "Надсилає Happ заголовки socks-auth-mode / http-auth-mode. Без авторизації будь-який застосунок на пристрої може через локальний SOCKS5/HTTP-проксі Happ потрапити в тунель і дізнатися адресу сервера. «Авто» — Happ сам створює випадкові облікові дані; Provider ID не потрібен.",
+      "subHappLocalProxyAuthAuto": "Авто (випадкові облікові дані)",
+      "subHappLocalProxyAuthDisable": "Вимкнена",
+      "subHappLocalProxyAuthUnset": "Не надсилати (типово для клієнта)",
       "subHappAutoConnect": "Автопідключення під час запуску",
       "subHappAutoConnectDesc": "Доручити Happ автоматично підключатися до VPN під час запуску програми.",
       "subHappAutoConnectType": "Ціль автопідключення",

+ 5 - 0
internal/web/translation/vi-VN.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "Chủ đề màu iOS tùy chỉnh dưới dạng chuỗi JSON, hoặc resetcolors để khôi phục màu mặc định.",
       "subHappPingType": "Phương thức đo độ trễ",
       "subHappPingTypeDesc": "Cách Happ đo độ trễ của nút: qua proxy (GET hoặc HEAD), TCP hoặc ICMP.",
+      "subHappLocalProxyAuth": "Xác thực proxy cục bộ",
+      "subHappLocalProxyAuthDesc": "Gửi socks-auth-mode / http-auth-mode cho Happ. Không có xác thực, bất kỳ ứng dụng nào trên thiết bị cũng có thể dùng proxy SOCKS5/HTTP cục bộ của Happ để vào đường hầm và biết địa chỉ máy chủ. \"Tự động\" khiến Happ tạo thông tin đăng nhập ngẫu nhiên; không cần Provider ID.",
+      "subHappLocalProxyAuthAuto": "Tự động (thông tin ngẫu nhiên)",
+      "subHappLocalProxyAuthDisable": "Tắt",
+      "subHappLocalProxyAuthUnset": "Không gửi (mặc định của ứng dụng)",
       "subHappAutoConnect": "Tự động kết nối khi khởi động",
       "subHappAutoConnectDesc": "Yêu cầu Happ tự động kết nối VPN khi ứng dụng khởi động.",
       "subHappAutoConnectType": "Mục tiêu tự động kết nối",

+ 5 - 0
internal/web/translation/zh-CN.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "以 JSON 字符串自定义 iOS 配色主题,或填写 resetcolors 恢复默认颜色。",
       "subHappPingType": "延迟测速协议",
       "subHappPingTypeDesc": "Happ 测量节点延迟的方式:经由代理 (GET 或 HEAD)、TCP 或 ICMP。",
+      "subHappLocalProxyAuth": "本地代理认证",
+      "subHappLocalProxyAuthDesc": "向 Happ 发送 socks-auth-mode / http-auth-mode。没有认证时,设备上的任何应用都能通过 Happ 的本地 SOCKS5/HTTP 代理进入隧道并获知服务器地址。\"自动\" 让 Happ 生成随机凭据;无需 Provider ID。",
+      "subHappLocalProxyAuthAuto": "自动(随机凭据)",
+      "subHappLocalProxyAuthDisable": "禁用",
+      "subHappLocalProxyAuthUnset": "不发送(客户端默认)",
       "subHappAutoConnect": "启动时自动连接",
       "subHappAutoConnectDesc": "Happ 客户端打开时自动连接代理节点。",
       "subHappAutoConnectType": "自动连接策略",

+ 5 - 0
internal/web/translation/zh-TW.json

@@ -1558,6 +1558,11 @@
       "subHappColorProfileDesc": "以 JSON 字串自訂 iOS 顏色主題,或填入 resetcolors 以還原預設顏色。",
       "subHappPingType": "延遲測試方式",
       "subHappPingTypeDesc": "Happ 測量節點延遲的方式:經由代理(GET 或 HEAD)、TCP 或 ICMP。",
+      "subHappLocalProxyAuth": "本機代理驗證",
+      "subHappLocalProxyAuthDesc": "向 Happ 傳送 socks-auth-mode / http-auth-mode。沒有驗證時,裝置上的任何應用程式都能透過 Happ 的本機 SOCKS5/HTTP 代理進入通道並得知伺服器位址。「自動」讓 Happ 產生隨機憑證;不需要 Provider ID。",
+      "subHappLocalProxyAuthAuto": "自動(隨機憑證)",
+      "subHappLocalProxyAuthDisable": "停用",
+      "subHappLocalProxyAuthUnset": "不傳送(用戶端預設)",
       "subHappAutoConnect": "啟動時自動連線",
       "subHappAutoConnectDesc": "指示 Happ 在應用程式啟動時自動連線至 VPN。",
       "subHappAutoConnectType": "自動連線目標",