Added socks auth

This commit is contained in:
be-not-afraid 2026-04-15 14:08:17 +04:00
parent 43dcb90632
commit 41bc08abc2
19 changed files with 284 additions and 1 deletions

View file

@ -46,6 +46,7 @@ public static class ConnectionHandler
{
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{port}");
ApplyMixedPortAuth(webProxy);
var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
for (var i = 0; i < 2; i++)
@ -95,4 +96,20 @@ public static class ConnectionHandler
}
return responseTime;
}
private static void ApplyMixedPortAuth(WebProxy webProxy)
{
var inbound = AppManager.Instance.Config?.Inbound?.FirstOrDefault();
if (inbound?.MixedPortAuthEnabled != true)
{
return;
}
if (inbound.MixedPortAuthUser.IsNullOrEmpty() || inbound.MixedPortAuthPass.IsNullOrEmpty())
{
return;
}
// Use credential object instead of URI userinfo to avoid leaking secrets.
webProxy.Credentials = new NetworkCredential(inbound.MixedPortAuthUser, inbound.MixedPortAuthPass);
}
}

View file

@ -35,6 +35,9 @@ public class InItem
public bool NewPort4LAN { get; set; }
public string User { get; set; }
public string Pass { get; set; }
public bool MixedPortAuthEnabled { get; set; }
public string MixedPortAuthUser { get; set; }
public string MixedPortAuthPass { get; set; }
public bool SecondLocalPortEnabled { get; set; }
}

View file

@ -4068,6 +4068,33 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Enable Mixed Port Auth 的本地化字符串。
/// </summary>
public static string TbSettingsMixedPortAuthEnabled {
get {
return ResourceManager.GetString("TbSettingsMixedPortAuthEnabled", resourceCulture);
}
}
/// <summary>
/// 查找类似 Mixed Port Auth Pass 的本地化字符串。
/// </summary>
public static string TbSettingsMixedPortAuthPass {
get {
return ResourceManager.GetString("TbSettingsMixedPortAuthPass", resourceCulture);
}
}
/// <summary>
/// 查找类似 Mixed Port Auth User 的本地化字符串。
/// </summary>
public static string TbSettingsMixedPortAuthUser {
get {
return ResourceManager.GetString("TbSettingsMixedPortAuthUser", resourceCulture);
}
}
/// <summary>
/// 查找类似 sing-box Mux Protocol 的本地化字符串。
/// </summary>

View file

@ -1338,6 +1338,15 @@
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>نوع Sniffing</value>
</data>
<data name="TbSettingsMixedPortAuthEnabled" xml:space="preserve">
<value>فعال‌سازی احراز هویت پورت ترکیبی</value>
</data>
<data name="TbSettingsMixedPortAuthPass" xml:space="preserve">
<value>رمز عبور احراز هویت پورت ترکیبی</value>
</data>
<data name="TbSettingsMixedPortAuthUser" xml:space="preserve">
<value>نام کاربری احراز هویت پورت ترکیبی</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>فعال کردن دومین پورت ترکیبی</value>
</data>

View file

@ -1335,6 +1335,15 @@
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Type de détection de trafic</value>
</data>
<data name="TbSettingsMixedPortAuthEnabled" xml:space="preserve">
<value>Activer l'authentification du port mixte</value>
</data>
<data name="TbSettingsMixedPortAuthPass" xml:space="preserve">
<value>Mot de passe d'authentification du port mixte</value>
</data>
<data name="TbSettingsMixedPortAuthUser" xml:space="preserve">
<value>Utilisateur d'authentification du port mixte</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Activer un second port découte local</value>
</data>

View file

@ -1338,6 +1338,15 @@
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Sniffing típus</value>
</data>
<data name="TbSettingsMixedPortAuthEnabled" xml:space="preserve">
<value>Vegyes port hitelesítés engedélyezése</value>
</data>
<data name="TbSettingsMixedPortAuthPass" xml:space="preserve">
<value>Vegyes port hitelesítési jelszó</value>
</data>
<data name="TbSettingsMixedPortAuthUser" xml:space="preserve">
<value>Vegyes port hitelesítési felhasználó</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Második vegyes port engedélyezése</value>
</data>

View file

@ -1347,6 +1347,15 @@
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Sniffing type</value>
</data>
<data name="TbSettingsMixedPortAuthEnabled" xml:space="preserve">
<value>Enable Mixed Port Auth</value>
</data>
<data name="TbSettingsMixedPortAuthPass" xml:space="preserve">
<value>Mixed Port Auth Pass</value>
</data>
<data name="TbSettingsMixedPortAuthUser" xml:space="preserve">
<value>Mixed Port Auth User</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Enable second mixed port</value>
</data>

View file

@ -1338,6 +1338,15 @@
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Тип сниффинга</value>
</data>
<data name="TbSettingsMixedPortAuthEnabled" xml:space="preserve">
<value>Включить авторизацию смешанного порта</value>
</data>
<data name="TbSettingsMixedPortAuthPass" xml:space="preserve">
<value>Пароль авторизации смешанного порта</value>
</data>
<data name="TbSettingsMixedPortAuthUser" xml:space="preserve">
<value>Пользователь авторизации смешанного порта</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Включить второй смешанный порт</value>
</data>

View file

@ -1344,6 +1344,15 @@
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>流量探测类型</value>
</data>
<data name="TbSettingsMixedPortAuthEnabled" xml:space="preserve">
<value>启用混合端口认证</value>
</data>
<data name="TbSettingsMixedPortAuthPass" xml:space="preserve">
<value>混合端口认证密码</value>
</data>
<data name="TbSettingsMixedPortAuthUser" xml:space="preserve">
<value>混合端口认证用户名</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>开启第二个本地监听端口</value>
</data>

View file

@ -1335,6 +1335,15 @@
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>流量探測類型</value>
</data>
<data name="TbSettingsMixedPortAuthEnabled" xml:space="preserve">
<value>啟用混合連接埠驗證</value>
</data>
<data name="TbSettingsMixedPortAuthPass" xml:space="preserve">
<value>混合連接埠驗證密碼</value>
</data>
<data name="TbSettingsMixedPortAuthUser" xml:space="preserve">
<value>混合連接埠驗證使用者</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>開啟第二個本機監聽埠</value>
</data>

View file

@ -22,6 +22,21 @@ public partial class CoreConfigSingboxService
_coreConfig.inbounds.Add(inbound);
inbound.listen_port = listenPort;
if (_config.Inbound.First().MixedPortAuthEnabled)
{
inbound.users = new()
{
new()
{
username = _config.Inbound.First().MixedPortAuthUser,
password = _config.Inbound.First().MixedPortAuthPass
}
};
}
else
{
inbound.users = null;
}
if (_config.Inbound.First().SecondLocalPortEnabled)
{

View file

@ -65,6 +65,23 @@ public partial class CoreConfigV2rayService
inbound.sniffing.enabled = inItem.SniffingEnabled;
inbound.sniffing.destOverride = inItem.DestOverride;
inbound.sniffing.routeOnly = inItem.RouteOnly;
if (inItem.MixedPortAuthEnabled)
{
inbound.settings.auth = "password";
inbound.settings.accounts = new List<AccountsItem4Ray>
{
new()
{
user = inItem.MixedPortAuthUser,
pass = inItem.MixedPortAuthPass
}
};
}
else
{
inbound.settings.auth = "noauth";
inbound.settings.accounts = null;
}
return inbound;
}

View file

@ -212,7 +212,24 @@ public class DownloadService
return null;
}
return new WebProxy($"socks5://{Global.Loopback}:{port}");
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{port}");
ApplyMixedPortAuth(webProxy);
return webProxy;
}
private void ApplyMixedPortAuth(WebProxy webProxy)
{
var inbound = AppManager.Instance.Config?.Inbound?.FirstOrDefault();
if (inbound?.MixedPortAuthEnabled != true)
{
return;
}
if (inbound.MixedPortAuthUser.IsNullOrEmpty() || inbound.MixedPortAuthPass.IsNullOrEmpty())
{
return;
}
webProxy.Credentials = new NetworkCredential(inbound.MixedPortAuthUser, inbound.MixedPortAuthPass);
}
private async Task<bool> SocketCheck(string ip, int port)

View file

@ -305,6 +305,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
private async Task<int> DoRealPing(ServerTestItem it)
{
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
ApplyMixedPortAuth(webProxy);
var responseTime = await ConnectionHandler.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
@ -317,6 +318,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
await UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
ApplyMixedPortAuth(webProxy);
var url = _config.SpeedTestItem.SpeedTestUrl;
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (success, msg) =>
@ -378,6 +380,22 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
return lstTest;
}
private void ApplyMixedPortAuth(WebProxy webProxy)
{
var inbound = _config?.Inbound?.FirstOrDefault();
if (inbound?.MixedPortAuthEnabled != true)
{
return;
}
if (inbound.MixedPortAuthUser.IsNullOrEmpty() || inbound.MixedPortAuthPass.IsNullOrEmpty())
{
return;
}
// Keep credentials out of URLs/logs and pass them via proxy credentials only.
webProxy.Credentials = new NetworkCredential(inbound.MixedPortAuthUser, inbound.MixedPortAuthPass);
}
private async Task UpdateFunc(string indexId, string delay, string speed = "")
{
await _updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });

View file

@ -14,6 +14,9 @@ public class OptionSettingViewModel : MyReactiveObject
[Reactive] public bool newPort4LAN { get; set; }
[Reactive] public string user { get; set; }
[Reactive] public string pass { get; set; }
[Reactive] public bool mixedPortAuthEnabled { get; set; }
[Reactive] public string mixedPortAuthUser { get; set; }
[Reactive] public string mixedPortAuthPass { get; set; }
[Reactive] public bool muxEnabled { get; set; }
[Reactive] public bool logEnabled { get; set; }
[Reactive] public string loglevel { get; set; }
@ -149,6 +152,9 @@ public class OptionSettingViewModel : MyReactiveObject
newPort4LAN = inbound.NewPort4LAN;
user = inbound.User;
pass = inbound.Pass;
mixedPortAuthEnabled = inbound.MixedPortAuthEnabled;
mixedPortAuthUser = inbound.MixedPortAuthUser;
mixedPortAuthPass = inbound.MixedPortAuthPass;
muxEnabled = _config.CoreBasicItem.MuxEnabled;
logEnabled = _config.CoreBasicItem.LogEnabled;
loglevel = _config.CoreBasicItem.Loglevel;
@ -334,6 +340,9 @@ public class OptionSettingViewModel : MyReactiveObject
_config.Inbound.First().NewPort4LAN = newPort4LAN;
_config.Inbound.First().User = user;
_config.Inbound.First().Pass = pass;
_config.Inbound.First().MixedPortAuthEnabled = mixedPortAuthEnabled;
_config.Inbound.First().MixedPortAuthUser = mixedPortAuthUser;
_config.Inbound.First().MixedPortAuthPass = mixedPortAuthPass;
if (_config.Inbound.Count > 1)
{
_config.Inbound.RemoveAt(1);

View file

@ -59,6 +59,47 @@
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsSocksPortTip}"
TextWrapping="Wrap" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
Text="{x:Static resx:ResUI.TbSettingsMixedPortAuthEnabled}" />
<StackPanel
Grid.Row="1"
Grid.Column="1"
Orientation="Vertical">
<ToggleSwitch
x:Name="togMixedPortAuthEnabled"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
</StackPanel>
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="4,40,4,4"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsMixedPortAuthUser}" />
<TextBox
x:Name="txtMixedPortAuthUser"
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="4,40,4,4"
VerticalAlignment="Center" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="4,76,4,4"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbSettingsMixedPortAuthPass}" />
<TextBox
x:Name="txtMixedPortAuthPass"
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="4,76,4,4"
VerticalAlignment="Center" />
<TextBlock
Grid.Row="2"

View file

@ -70,6 +70,11 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.user, v => v.txtuser.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.pass, v => v.txtpass.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthEnabled, v => v.togMixedPortAuthEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthEnabled, v => v.txtMixedPortAuthUser.IsEnabled).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthEnabled, v => v.txtMixedPortAuthPass.IsEnabled).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthUser, v => v.txtMixedPortAuthUser.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthPass, v => v.txtMixedPortAuthPass.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.muxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.logEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.loglevel, v => v.cmbloglevel.SelectedValue).DisposeWith(disposables);

View file

@ -94,6 +94,52 @@
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsSocksPortTip}"
TextWrapping="Wrap" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Top"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsMixedPortAuthEnabled}" />
<StackPanel
Grid.Row="1"
Grid.Column="1"
Orientation="Vertical">
<ToggleButton
x:Name="togMixedPortAuthEnabled"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
</StackPanel>
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsMixedPortAuthUser}" />
<TextBox
x:Name="txtMixedPortAuthUser"
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="8,96,8,8"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsMixedPortAuthPass}" />
<TextBox
x:Name="txtMixedPortAuthPass"
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="8,96,8,8"
VerticalAlignment="Center"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"

View file

@ -67,6 +67,11 @@ public partial class OptionSettingWindow
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.user, v => v.txtuser.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.pass, v => v.txtpass.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthEnabled, v => v.togMixedPortAuthEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthEnabled, v => v.txtMixedPortAuthUser.IsEnabled).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthEnabled, v => v.txtMixedPortAuthPass.IsEnabled).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthUser, v => v.txtMixedPortAuthUser.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.mixedPortAuthPass, v => v.txtMixedPortAuthPass.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.muxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.logEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.loglevel, v => v.cmbloglevel.Text).DisposeWith(disposables);