mirror of
https://github.com/2dust/v2rayN.git
synced 2025-11-29 03:02:53 +00:00
Cert Chain Pinning
This commit is contained in:
parent
164277aab3
commit
7ec9659d61
13 changed files with 88 additions and 19 deletions
9
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
9
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
|
@ -2797,6 +2797,15 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Fetch Certificate Chain 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbFetchCertChain {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbFetchCertChain", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Fingerprint 的本地化字符串。
|
/// 查找类似 Fingerprint 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
|
||||||
<data name="TbFetchCert" xml:space="preserve">
|
<data name="TbFetchCert" xml:space="preserve">
|
||||||
<value>Fetch Certificate</value>
|
<value>Fetch Certificate</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbFetchCertChain" xml:space="preserve">
|
||||||
|
<value>Fetch Certificate Chain</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1606,4 +1606,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
|
||||||
<data name="TbFetchCert" xml:space="preserve">
|
<data name="TbFetchCert" xml:space="preserve">
|
||||||
<value>Fetch Certificate</value>
|
<value>Fetch Certificate</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbFetchCertChain" xml:space="preserve">
|
||||||
|
<value>Fetch Certificate Chain</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
|
||||||
<data name="TbFetchCert" xml:space="preserve">
|
<data name="TbFetchCert" xml:space="preserve">
|
||||||
<value>Fetch Certificate</value>
|
<value>Fetch Certificate</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbFetchCertChain" xml:space="preserve">
|
||||||
|
<value>Fetch Certificate Chain</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
|
||||||
<data name="TbFetchCert" xml:space="preserve">
|
<data name="TbFetchCert" xml:space="preserve">
|
||||||
<value>Fetch Certificate</value>
|
<value>Fetch Certificate</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbFetchCertChain" xml:space="preserve">
|
||||||
|
<value>Fetch Certificate Chain</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1609,4 +1609,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
|
||||||
<data name="TbFetchCert" xml:space="preserve">
|
<data name="TbFetchCert" xml:space="preserve">
|
||||||
<value>Fetch Certificate</value>
|
<value>Fetch Certificate</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbFetchCertChain" xml:space="preserve">
|
||||||
|
<value>Fetch Certificate Chain</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1606,4 +1606,7 @@
|
||||||
<data name="TbFetchCert" xml:space="preserve">
|
<data name="TbFetchCert" xml:space="preserve">
|
||||||
<value>获取证书</value>
|
<value>获取证书</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbFetchCertChain" xml:space="preserve">
|
||||||
|
<value>获取证书链</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1606,4 +1606,7 @@ Do not use the "Fetch Certificate" button when "Allow Insecure" is enabled.</val
|
||||||
<data name="TbFetchCert" xml:space="preserve">
|
<data name="TbFetchCert" xml:space="preserve">
|
||||||
<value>Fetch Certificate</value>
|
<value>Fetch Certificate</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbFetchCertChain" xml:space="preserve">
|
||||||
|
<value>Fetch Certificate Chain</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -12,6 +12,7 @@ public class AddServerViewModel : MyReactiveObject
|
||||||
public string Cert { get; set; }
|
public string Cert { get; set; }
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> FetchCertCmd { get; }
|
public ReactiveCommand<Unit, Unit> FetchCertCmd { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> FetchCertChainCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
|
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
|
||||||
|
|
||||||
public AddServerViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)
|
public AddServerViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)
|
||||||
|
|
@ -23,6 +24,10 @@ public class AddServerViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
await FetchCert();
|
await FetchCert();
|
||||||
});
|
});
|
||||||
|
FetchCertChainCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
|
{
|
||||||
|
await FetchCertChain();
|
||||||
|
});
|
||||||
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
|
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
await SaveServerAsync();
|
await SaveServerAsync();
|
||||||
|
|
@ -117,4 +122,24 @@ public class AddServerViewModel : MyReactiveObject
|
||||||
}
|
}
|
||||||
Cert = await Utils.GetCertPem(domain, serverName);
|
Cert = await Utils.GetCertPem(domain, serverName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task FetchCertChain()
|
||||||
|
{
|
||||||
|
if (SelectedSource.StreamSecurity != Global.StreamSecurity)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var domain = SelectedSource.Address;
|
||||||
|
var serverName = SelectedSource.Sni.IsNullOrEmpty() ? SelectedSource.Address : SelectedSource.Sni;
|
||||||
|
if (!Utils.IsDomain(serverName))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (SelectedSource.Port > 0)
|
||||||
|
{
|
||||||
|
domain += $":{SelectedSource.Port}";
|
||||||
|
}
|
||||||
|
var certs = await Utils.GetCertChainPem(domain, serverName);
|
||||||
|
Cert = string.Join("\n", certs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -607,10 +607,10 @@
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
x:Name="btnExtra"
|
x:Name="btnExtra"
|
||||||
Classes="IconButton"
|
Margin="{StaticResource MarginLr8}"
|
||||||
Margin="{StaticResource MarginLr8}">
|
Classes="IconButton">
|
||||||
<Button.Content>
|
<Button.Content>
|
||||||
<PathIcon Data="{StaticResource SemiIconMore}" >
|
<PathIcon Data="{StaticResource SemiIconMore}">
|
||||||
<PathIcon.RenderTransform>
|
<PathIcon.RenderTransform>
|
||||||
<RotateTransform Angle="90" />
|
<RotateTransform Angle="90" />
|
||||||
</PathIcon.RenderTransform>
|
</PathIcon.RenderTransform>
|
||||||
|
|
@ -778,11 +778,11 @@
|
||||||
<Button
|
<Button
|
||||||
Grid.Row="5"
|
Grid.Row="5"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Classes="IconButton"
|
Margin="{StaticResource MarginLr8}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Margin="{StaticResource MarginLr8}">
|
Classes="IconButton">
|
||||||
<Button.Content>
|
<Button.Content>
|
||||||
<PathIcon Data="{StaticResource SemiIconMore}" >
|
<PathIcon Data="{StaticResource SemiIconMore}">
|
||||||
<PathIcon.RenderTransform>
|
<PathIcon.RenderTransform>
|
||||||
<RotateTransform Angle="90" />
|
<RotateTransform Angle="90" />
|
||||||
</PathIcon.RenderTransform>
|
</PathIcon.RenderTransform>
|
||||||
|
|
@ -795,11 +795,16 @@
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{x:Static resx:ResUI.TbCertPinningTips}" />
|
Text="{x:Static resx:ResUI.TbCertPinningTips}" />
|
||||||
<Button
|
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
||||||
x:Name="btnFetchCert"
|
<Button
|
||||||
HorizontalAlignment="Left"
|
x:Name="btnFetchCert"
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
Content="{x:Static resx:ResUI.TbFetchCert}" />
|
Content="{x:Static resx:ResUI.TbFetchCert}" />
|
||||||
|
<Button
|
||||||
|
x:Name="btnFetchCertChain"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
Content="{x:Static resx:ResUI.TbFetchCertChain}" />
|
||||||
|
</StackPanel>
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="txtCert"
|
x:Name="txtCert"
|
||||||
Width="400"
|
Width="400"
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1018,13 +1018,20 @@
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbCertPinningTips}"
|
Text="{x:Static resx:ResUI.TbCertPinningTips}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
<Button
|
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
||||||
x:Name="btnFetchCert"
|
<Button
|
||||||
Width="100"
|
x:Name="btnFetchCert"
|
||||||
Margin="{StaticResource MarginLeftRight4}"
|
Width="100"
|
||||||
HorizontalAlignment="Left"
|
Margin="{StaticResource MarginLeftRight4}"
|
||||||
Content="{x:Static resx:ResUI.TbFetchCert}"
|
Content="{x:Static resx:ResUI.TbFetchCert}"
|
||||||
Style="{StaticResource DefButton}" />
|
Style="{StaticResource DefButton}" />
|
||||||
|
<Button
|
||||||
|
x:Name="btnFetchCertChain"
|
||||||
|
Width="100"
|
||||||
|
Margin="{StaticResource MarginLeftRight4}"
|
||||||
|
Content="{x:Static resx:ResUI.TbFetchCertChain}"
|
||||||
|
Style="{StaticResource DefButton}" />
|
||||||
|
</StackPanel>
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="txtCert"
|
x:Name="txtCert"
|
||||||
Width="400"
|
Width="400"
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,7 @@ public partial class AddServerWindow
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue