diff --git a/v2rayN/ServiceLib/Handler/CoreHandler.cs b/v2rayN/ServiceLib/Handler/CoreHandler.cs
index e181eb30..57e94557 100644
--- a/v2rayN/ServiceLib/Handler/CoreHandler.cs
+++ b/v2rayN/ServiceLib/Handler/CoreHandler.cs
@@ -259,7 +259,7 @@ namespace ServiceLib.Handler
             return _config.TunModeItem.EnableTun
                    && eCoreType == ECoreType.sing_box
                    && Utils.IsLinux()
-                   && _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
+                //&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
                 ;
         }
 
@@ -275,7 +275,6 @@ namespace ServiceLib.Handler
                 return null;
             }
 
-            var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
             try
             {
                 Process proc = new()
@@ -294,14 +293,10 @@ namespace ServiceLib.Handler
                     }
                 };
 
+                var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
                 if (isNeedSudo)
                 {
-                    proc.StartInfo.FileName = $"/bin/sudo";
-                    proc.StartInfo.Arguments = $"-S {fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}";
-                    proc.StartInfo.WorkingDirectory = null;
-                    proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
-                    proc.StartInfo.RedirectStandardInput = true;
-                    Logging.SaveLog(proc.StartInfo.Arguments);
+                    await RunProcessAsLinuxRoot(proc, fileName, coreInfo, configPath);
                 }
 
                 var startUpErrorMessage = new StringBuilder();
@@ -326,7 +321,7 @@ namespace ServiceLib.Handler
                 }
                 proc.Start();
 
-                if (isNeedSudo)
+                if (isNeedSudo && _config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
                 {
                     var pwd = DesUtils.Decrypt(_config.TunModeItem.LinuxSudoPwd);
                     await Task.Delay(10);
@@ -362,6 +357,37 @@ namespace ServiceLib.Handler
             }
         }
 
+        private async Task RunProcessAsLinuxRoot(Process proc, string fileName, CoreInfo coreInfo, string configPath)
+        {
+            var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}";
+
+            //Prefer shell scripts
+            var shFilePath = Utils.GetBinPath("run_as_root.sh");
+            File.Delete(shFilePath);
+            var sb = new StringBuilder();
+            sb.AppendLine("#!/bin/sh");
+            sb.AppendLine(cmdLine);
+            await File.WriteAllTextAsync(shFilePath, sb.ToString());
+            await Utils.SetLinuxChmod(shFilePath);
+
+            //Replace command
+            var args = File.Exists(shFilePath) ? shFilePath : cmdLine;
+            if (_config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
+            {
+                proc.StartInfo.FileName = $"/bin/sudo";
+                proc.StartInfo.Arguments = $"-S {args}";
+            }
+            else
+            {
+                proc.StartInfo.FileName = $"/bin/pkexec";
+                proc.StartInfo.Arguments = $"{args}";
+            }
+            proc.StartInfo.WorkingDirectory = null;
+            proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
+            proc.StartInfo.RedirectStandardInput = true;
+            Logging.SaveLog(proc.StartInfo.Arguments);
+        }
+
         private async Task KillProcess(Process? proc)
         {
             if (proc is null)
diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
index 9fd66a6e..c281a4ad 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
@@ -1370,7 +1370,7 @@
     <value>Linux系统的sudo密码</value>
   </data>
   <data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
-    <value>密码已加密且只存储在本地文件中,无密码无法开启Tun</value>
+    <value>密码已加密且只存储在本地文件中,无密码则每次都要输入</value>
   </data>
   <data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
     <value>请先在Tun模式设置中设置sudo密码</value>
diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
index 0243c1f3..2d18ce2e 100644
--- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
+++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
@@ -1370,7 +1370,7 @@
     <value>Linux系統的sudo密碼</value>
   </data>
   <data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
-    <value>密碼已加密且只儲存在本機檔案中,無密碼無法開啟Tun</value>
+    <value>密碼已加密且只儲存在本機檔案中,無密碼則每次都要輸入</value>
   </data>
   <data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
     <value>請先在Tun模式設定中設定sudo密碼</value>
diff --git a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs
index 3298f636..89fbefc5 100644
--- a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs
+++ b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs
@@ -416,16 +416,16 @@ namespace ServiceLib.ViewModels
                 // When running as a non-administrator, reboot to administrator mode
                 if (EnableTun && AllowEnableTun() == false)
                 {
-                    _config.TunModeItem.EnableTun = false;
                     if (Utils.IsWindows())
                     {
+                        _config.TunModeItem.EnableTun = false;
                         Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
+                        return;
                     }
-                    else if (Utils.IsLinux())
-                    {
-                        NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
-                    }
-                    return;
+                    //else if (Utils.IsLinux())
+                    //{
+                    //    NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
+                    //}
                 }
                 await ConfigHandler.SaveConfig(_config);
                 Locator.Current.GetService<MainWindowViewModel>()?.Reload();