mirror of https://github.com/2dust/v2rayN
Use tun mode without running with sudo in linux
parent
f921ff7d77
commit
9d638968a9
|
@ -68,6 +68,7 @@ namespace ServiceLib.Handler
|
|||
{
|
||||
ShowMsg(true, $"{node.GetSummary()}");
|
||||
await CoreStop();
|
||||
await Task.Delay(100);
|
||||
await CoreStart(node);
|
||||
|
||||
//In tun mode, do a delay check and restart the core
|
||||
|
@ -169,21 +170,12 @@ namespace ServiceLib.Handler
|
|||
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
||||
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
||||
|
||||
//ECoreType coreType;
|
||||
//if (node.configType != EConfigType.Custom && _config.tunModeItem.enableTun)
|
||||
//{
|
||||
// coreType = ECoreType.sing_box;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
|
||||
//}
|
||||
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||
_config.RunningCoreType = coreType;
|
||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||
|
||||
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;
|
||||
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog);
|
||||
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);
|
||||
if (proc is null)
|
||||
{
|
||||
return;
|
||||
|
@ -225,7 +217,7 @@ namespace ServiceLib.Handler
|
|||
if (result.Success)
|
||||
{
|
||||
var coreInfo2 = CoreInfoHandler.Instance.GetCoreInfo(preCoreType);
|
||||
var proc2 = await RunProcess(coreInfo2, Global.CorePreConfigFileName, true);
|
||||
var proc2 = await RunProcess(coreInfo2, Global.CorePreConfigFileName, true, true);
|
||||
if (proc2 is not null)
|
||||
{
|
||||
_processPre = proc2;
|
||||
|
@ -243,7 +235,7 @@ namespace ServiceLib.Handler
|
|||
try
|
||||
{
|
||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true);
|
||||
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
|
||||
if (proc is null)
|
||||
{
|
||||
return -1;
|
||||
|
@ -264,17 +256,28 @@ namespace ServiceLib.Handler
|
|||
_updateFunc?.Invoke(notify, msg);
|
||||
}
|
||||
|
||||
private bool IsNeedSudo(ECoreType eCoreType)
|
||||
{
|
||||
return _config.TunModeItem.EnableTun
|
||||
&& eCoreType == ECoreType.sing_box
|
||||
&& Utils.IsLinux()
|
||||
&& _config.TunModeItem.LinuxSudoPassword.IsNotEmpty()
|
||||
;
|
||||
}
|
||||
|
||||
#endregion Private
|
||||
|
||||
#region Process
|
||||
|
||||
private async Task<Process?> RunProcess(CoreInfo coreInfo, string configPath, bool displayLog)
|
||||
private async Task<Process?> RunProcess(CoreInfo coreInfo, string configPath, bool displayLog, bool mayNeedSudo)
|
||||
{
|
||||
var fileName = CoreFindExe(coreInfo);
|
||||
if (Utils.IsNullOrEmpty(fileName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
|
||||
try
|
||||
{
|
||||
Process proc = new()
|
||||
|
@ -292,6 +295,15 @@ namespace ServiceLib.Handler
|
|||
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
|
||||
}
|
||||
};
|
||||
|
||||
if (isNeedSudo)
|
||||
{
|
||||
proc.StartInfo.FileName = $"/bin/sudo";
|
||||
proc.StartInfo.Arguments = $"-S {fileName} {string.Format(coreInfo.Arguments, configPath)}";
|
||||
proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
|
||||
proc.StartInfo.RedirectStandardInput = true;
|
||||
}
|
||||
|
||||
var startUpErrorMessage = new StringBuilder();
|
||||
var startUpSuccessful = false;
|
||||
if (displayLog)
|
||||
|
@ -313,6 +325,15 @@ namespace ServiceLib.Handler
|
|||
};
|
||||
}
|
||||
proc.Start();
|
||||
|
||||
if (isNeedSudo)
|
||||
{
|
||||
await Task.Delay(10);
|
||||
await proc.StandardInput.WriteLineAsync(_config.TunModeItem.LinuxSudoPassword);
|
||||
await Task.Delay(10);
|
||||
await proc.StandardInput.WriteLineAsync(_config.TunModeItem.LinuxSudoPassword);
|
||||
}
|
||||
|
||||
if (displayLog)
|
||||
{
|
||||
proc.BeginOutputReadLine();
|
||||
|
|
|
@ -161,6 +161,7 @@
|
|||
public int Mtu { get; set; }
|
||||
public bool EnableExInbound { get; set; }
|
||||
public bool EnableIPv6Address { get; set; }
|
||||
public string? LinuxSudoPassword { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
|
|
@ -3148,6 +3148,42 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Linux system sudo password 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPassword {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPassword", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please set the sudo password in Tun mode settings first 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPasswordIsEmpty {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordIsEmpty", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please do not run this app with sudo 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPasswordNotSudoRunApp {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordNotSudoRunApp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The password will only be stored in the local file. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPasswordTip {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable Log 的本地化字符串。
|
||||
/// </summary>
|
||||
|
|
|
@ -1369,4 +1369,16 @@
|
|||
<data name="TbRuleMatchingTips" xml:space="preserve">
|
||||
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux system sudo password</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>The password will only be stored in the local file.</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>Please set the sudo password in Tun mode settings first</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>Please do not run this app with sudo</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1369,4 +1369,16 @@
|
|||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>Remarks Memo</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux system sudo password</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>The password will only be stored in the local file.</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>Please set the sudo password in Tun mode settings first</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>Please do not run this app with sudo</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1369,4 +1369,16 @@
|
|||
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
|
||||
<value>Remote (WebDAV)</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux system sudo password</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>The password will only be stored in the local file.</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>Please set the sudo password in Tun mode settings first</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>Please do not run this app with sudo</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1366,4 +1366,16 @@
|
|||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>备注备忘</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux系统的sudo密码</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>密码只会存储在本地文件中,没有密码无法开启Tun</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>请先在Tun模式设置中设置sudo密码</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>请不要用sudo运行本app</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1366,4 +1366,16 @@
|
|||
<data name="TbPath7" xml:space="preserve">
|
||||
<value>混淆密碼(obfs password)</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux系統的sudo密碼</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>密碼只會儲存在本機檔案中,沒有密碼無法開啟Tun</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>請先在Tun模式設定中設定sudo密碼</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>請不要用sudo來運行本app</value>
|
||||
</data>
|
||||
</root>
|
|
@ -14,7 +14,7 @@
|
|||
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
||||
<PackageReference Include="Splat.NLog" Version="15.2.22" />
|
||||
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="16.1.3" />
|
||||
<PackageReference Include="YamlDotNet" Version="16.2.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.7" />
|
||||
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
||||
|
|
|
@ -85,6 +85,7 @@ namespace ServiceLib.ViewModels
|
|||
[Reactive] public int TunMtu { get; set; }
|
||||
[Reactive] public bool TunEnableExInbound { get; set; }
|
||||
[Reactive] public bool TunEnableIPv6Address { get; set; }
|
||||
[Reactive] public string TunLinuxSudoPassword { get; set; }
|
||||
|
||||
#endregion Tun mode
|
||||
|
||||
|
@ -197,6 +198,7 @@ namespace ServiceLib.ViewModels
|
|||
TunMtu = _config.TunModeItem.Mtu;
|
||||
TunEnableExInbound = _config.TunModeItem.EnableExInbound;
|
||||
TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;
|
||||
TunLinuxSudoPassword = _config.TunModeItem.LinuxSudoPassword;
|
||||
|
||||
#endregion Tun mode
|
||||
|
||||
|
@ -340,6 +342,7 @@ namespace ServiceLib.ViewModels
|
|||
_config.TunModeItem.Mtu = TunMtu;
|
||||
_config.TunModeItem.EnableExInbound = TunEnableExInbound;
|
||||
_config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;
|
||||
_config.TunModeItem.LinuxSudoPassword = TunLinuxSudoPassword;
|
||||
|
||||
//coreType
|
||||
await SaveCoreType();
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace ServiceLib.ViewModels
|
|||
SelectedServer = new();
|
||||
RunningServerToolTipText = "-";
|
||||
|
||||
if (_config.TunModeItem.EnableTun && AppHandler.Instance.IsAdministrator)
|
||||
if (_config.TunModeItem.EnableTun && AllowEnableTun())
|
||||
{
|
||||
EnableTun = true;
|
||||
}
|
||||
|
@ -414,10 +414,17 @@ namespace ServiceLib.ViewModels
|
|||
{
|
||||
_config.TunModeItem.EnableTun = EnableTun;
|
||||
// When running as a non-administrator, reboot to administrator mode
|
||||
if (EnableTun && !AppHandler.Instance.IsAdministrator)
|
||||
if (EnableTun && AllowEnableTun() == false)
|
||||
{
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||
}
|
||||
else if (Utils.IsLinux())
|
||||
{
|
||||
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
|
||||
}
|
||||
return;
|
||||
}
|
||||
await ConfigHandler.SaveConfig(_config);
|
||||
|
@ -425,6 +432,19 @@ namespace ServiceLib.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
private bool AllowEnableTun()
|
||||
{
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
return AppHandler.Instance.IsAdministrator;
|
||||
}
|
||||
else if (Utils.IsLinux())
|
||||
{
|
||||
return _config.TunModeItem.LinuxSudoPassword.IsNotEmpty();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion System proxy and Routings
|
||||
|
||||
#region UI
|
||||
|
|
|
@ -117,6 +117,11 @@ namespace v2rayN.Desktop.Views
|
|||
}
|
||||
else
|
||||
{
|
||||
if (AppHandler.Instance.IsAdministrator)
|
||||
{
|
||||
this.Title = $"{Utils.GetVersion()} - {ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp}";
|
||||
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp);
|
||||
}
|
||||
menuRebootAsAdmin.IsVisible = false;
|
||||
menuSettingsSetUWP.IsVisible = false;
|
||||
menuGlobalHotkeySetting.IsVisible = false;
|
||||
|
@ -282,6 +287,7 @@ namespace v2rayN.Desktop.Views
|
|||
e.Cancel = true;
|
||||
ShowHideWindow(false);
|
||||
break;
|
||||
|
||||
case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown:
|
||||
await ViewModel?.MyAppExitAsync(true);
|
||||
break;
|
||||
|
|
|
@ -489,7 +489,7 @@
|
|||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
|
||||
|
||||
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="11"
|
||||
|
@ -721,6 +721,7 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
|
@ -794,6 +795,28 @@
|
|||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}" />
|
||||
<TextBox
|
||||
x:Name="txtLinuxSudoPassword"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8"
|
||||
PasswordChar="*" />
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
|
|
|
@ -152,6 +152,7 @@ namespace v2rayN.Desktop.Views
|
|||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunEnableExInbound, v => v.togEnableExInbound.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunLinuxSudoPassword, v => v.txtLinuxSudoPassword.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace v2rayN.Desktop.Views
|
|||
this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
spEnableTun.IsVisible = (Utils.IsWindows() || AppHandler.Instance.IsAdministrator);
|
||||
//spEnableTun.IsVisible = (Utils.IsWindows() || AppHandler.Instance.IsAdministrator);
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
|
|
Loading…
Reference in New Issue