mirror of
				https://github.com/2dust/v2rayN.git
				synced 2025-10-27 02:34:41 +00:00 
			
		
		
		
	Compare commits
	
		
			6 commits
		
	
	
		
			14b8938d24
			...
			1d54f88e79
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1d54f88e79 | ||
|   | c2c13ad318 | ||
|   | 3a21596d95 | ||
|   | 18ccabd193 | ||
|   | 942335db61 | ||
|   | 12b46e7c43 | 
					 22 changed files with 200 additions and 26 deletions
				
			
		|  | @ -8,6 +8,7 @@ using System.Runtime.InteropServices; | ||||||
| using System.Security.Cryptography; | using System.Security.Cryptography; | ||||||
| using System.Security.Principal; | using System.Security.Principal; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using System.Text.RegularExpressions; | ||||||
| using CliWrap; | using CliWrap; | ||||||
| using CliWrap.Buffered; | using CliWrap.Buffered; | ||||||
| 
 | 
 | ||||||
|  | @ -357,6 +358,14 @@ public class Utils | ||||||
|         return userHostsMap; |         return userHostsMap; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public static List<string> ParseCertSha256ToList(string certSha256Content) | ||||||
|  |     { | ||||||
|  |         return String2List(certSha256Content) | ||||||
|  |                 .Select(s => s.Replace(":", "").Replace(" ", "")) | ||||||
|  |                 .Where(s => s.Length == 64 && Regex.IsMatch(s, @"\A\b[0-9a-fA-F]+\b\Z")) | ||||||
|  |                 .ToList(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     #endregion 转换函数 |     #endregion 转换函数 | ||||||
| 
 | 
 | ||||||
|     #region 数据检查 |     #region 数据检查 | ||||||
|  |  | ||||||
|  | @ -598,6 +598,7 @@ public class Global | ||||||
|             { "cloudflare-dns.com", new List<string> { "104.16.249.249", "104.16.248.249", "2606:4700::6810:f8f9", "2606:4700::6810:f9f9" } }, |             { "cloudflare-dns.com", new List<string> { "104.16.249.249", "104.16.248.249", "2606:4700::6810:f8f9", "2606:4700::6810:f9f9" } }, | ||||||
|             { "dns.cloudflare.com", new List<string> { "104.16.132.229", "104.16.133.229", "2606:4700::6810:84e5", "2606:4700::6810:85e5" } }, |             { "dns.cloudflare.com", new List<string> { "104.16.132.229", "104.16.133.229", "2606:4700::6810:84e5", "2606:4700::6810:85e5" } }, | ||||||
|             { "dot.pub", new List<string> { "1.12.12.12", "120.53.53.53" } }, |             { "dot.pub", new List<string> { "1.12.12.12", "120.53.53.53" } }, | ||||||
|  |             { "doh.pub", new List<string> { "1.12.12.12", "120.53.53.53" } }, | ||||||
|             { "dns.quad9.net", new List<string> { "9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9" } }, |             { "dns.quad9.net", new List<string> { "9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9" } }, | ||||||
|             { "dns.yandex.net", new List<string> { "77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff" } }, |             { "dns.yandex.net", new List<string> { "77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff" } }, | ||||||
|             { "dns.sb", new List<string> { "185.222.222.222", "2a09::" } }, |             { "dns.sb", new List<string> { "185.222.222.222", "2a09::" } }, | ||||||
|  |  | ||||||
|  | @ -253,6 +253,7 @@ public static class ConfigHandler | ||||||
|             item.ShortId = profileItem.ShortId; |             item.ShortId = profileItem.ShortId; | ||||||
|             item.SpiderX = profileItem.SpiderX; |             item.SpiderX = profileItem.SpiderX; | ||||||
|             item.Mldsa65Verify = profileItem.Mldsa65Verify; |             item.Mldsa65Verify = profileItem.Mldsa65Verify; | ||||||
|  |             item.CertSha256 = profileItem.CertSha256; | ||||||
|             item.Extra = profileItem.Extra; |             item.Extra = profileItem.Extra; | ||||||
|             item.MuxEnabled = profileItem.MuxEnabled; |             item.MuxEnabled = profileItem.MuxEnabled; | ||||||
|         } |         } | ||||||
|  | @ -1214,11 +1215,11 @@ public static class ConfigHandler | ||||||
|                 CoreType = ECoreType.sing_box, |                 CoreType = ECoreType.sing_box, | ||||||
|                 ConfigType = EConfigType.SOCKS, |                 ConfigType = EConfigType.SOCKS, | ||||||
|                 Address = Global.Loopback, |                 Address = Global.Loopback, | ||||||
|                 Sni = node.Address, //Tun2SocksAddress |                 SpiderX = node.Address, // Tun2SocksAddress | ||||||
|                 Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks) |                 Port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks) | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|         else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0)) |         else if (node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0) | ||||||
|         { |         { | ||||||
|             var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray; |             var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray; | ||||||
|             itemSocks = new ProfileItem() |             itemSocks = new ProfileItem() | ||||||
|  |  | ||||||
|  | @ -94,6 +94,7 @@ public class ProfileItem : ReactiveObject | ||||||
|     public string ShortId { get; set; } |     public string ShortId { get; set; } | ||||||
|     public string SpiderX { get; set; } |     public string SpiderX { get; set; } | ||||||
|     public string Mldsa65Verify { get; set; } |     public string Mldsa65Verify { get; set; } | ||||||
|  |     public string CertSha256 { get; set; } | ||||||
|     public string Extra { get; set; } |     public string Extra { get; set; } | ||||||
|     public bool? MuxEnabled { get; set; } |     public bool? MuxEnabled { get; set; } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -182,6 +182,7 @@ public class Tls4Sbox | ||||||
|     public bool? fragment { get; set; } |     public bool? fragment { get; set; } | ||||||
|     public string? fragment_fallback_delay { get; set; } |     public string? fragment_fallback_delay { get; set; } | ||||||
|     public bool? record_fragment { get; set; } |     public bool? record_fragment { get; set; } | ||||||
|  |     public List<string>? certificate_sha256 { get; set; } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| public class Multiplex4Sbox | public class Multiplex4Sbox | ||||||
|  |  | ||||||
|  | @ -355,6 +355,7 @@ public class TlsSettings4Ray | ||||||
|     public string? shortId { get; set; } |     public string? shortId { get; set; } | ||||||
|     public string? spiderX { get; set; } |     public string? spiderX { get; set; } | ||||||
|     public string? mldsa65Verify { get; set; } |     public string? mldsa65Verify { get; set; } | ||||||
|  |     public List<string>? pinnedPeerCertificateSha256 { get; set; } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| public class TcpSettings4Ray | public class TcpSettings4Ray | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								v2rayN/ServiceLib/Resx/ResUI.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										18
									
								
								v2rayN/ServiceLib/Resx/ResUI.Designer.cs
									
									
									
										generated
									
									
									
								
							|  | @ -2364,6 +2364,24 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Server Certificate Fingerprint (SHA-256) 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbCertSha256 { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbCertSha256", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Hex SHA-256, comma-separated for certificate chain 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbCertSha256Tips { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbCertSha256Tips", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Clear system proxy 的本地化字符串。 |         ///   查找类似 Clear system proxy 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  |  | ||||||
|  | @ -1515,4 +1515,10 @@ | ||||||
|   <data name="TbFakeIPTips" xml:space="preserve"> |   <data name="TbFakeIPTips" xml:space="preserve"> | ||||||
|     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> |     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="TbCertSha256" xml:space="preserve"> | ||||||
|  |     <value>Server Certificate Fingerprint (SHA-256)</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCertSha256Tips" xml:space="preserve"> | ||||||
|  |     <value>Hex SHA-256, comma-separated for certificate chain</value> | ||||||
|  |   </data> | ||||||
| </root> | </root> | ||||||
|  | @ -1515,4 +1515,10 @@ | ||||||
|   <data name="TbFakeIPTips" xml:space="preserve"> |   <data name="TbFakeIPTips" xml:space="preserve"> | ||||||
|     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> |     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="TbCertSha256" xml:space="preserve"> | ||||||
|  |     <value>Server Certificate Fingerprint (SHA-256)</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCertSha256Tips" xml:space="preserve"> | ||||||
|  |     <value>Hex SHA-256, comma-separated for certificate chain</value> | ||||||
|  |   </data> | ||||||
| </root> | </root> | ||||||
|  | @ -1515,4 +1515,10 @@ | ||||||
|   <data name="TbFakeIPTips" xml:space="preserve"> |   <data name="TbFakeIPTips" xml:space="preserve"> | ||||||
|     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> |     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="TbCertSha256" xml:space="preserve"> | ||||||
|  |     <value>Server Certificate Fingerprint (SHA-256)</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCertSha256Tips" xml:space="preserve"> | ||||||
|  |     <value>Hex SHA-256, comma-separated for certificate chain</value> | ||||||
|  |   </data> | ||||||
| </root> | </root> | ||||||
|  | @ -1515,4 +1515,10 @@ | ||||||
|   <data name="TbFakeIPTips" xml:space="preserve"> |   <data name="TbFakeIPTips" xml:space="preserve"> | ||||||
|     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> |     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="TbCertSha256" xml:space="preserve"> | ||||||
|  |     <value>Server Certificate Fingerprint (SHA-256)</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCertSha256Tips" xml:space="preserve"> | ||||||
|  |     <value>Hex SHA-256, comma-separated for certificate chain</value> | ||||||
|  |   </data> | ||||||
| </root> | </root> | ||||||
|  | @ -1512,4 +1512,10 @@ | ||||||
|   <data name="TbFakeIPTips" xml:space="preserve"> |   <data name="TbFakeIPTips" xml:space="preserve"> | ||||||
|     <value>默认全局生效,内置 FakeIP 过滤,仅在 sing-box 中生效</value> |     <value>默认全局生效,内置 FakeIP 过滤,仅在 sing-box 中生效</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="TbCertSha256" xml:space="preserve"> | ||||||
|  |     <value>服务器证书指纹 (SHA-256)</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCertSha256Tips" xml:space="preserve"> | ||||||
|  |     <value>十六进制 SHA-256,证书链用逗号分隔</value> | ||||||
|  |   </data> | ||||||
| </root> | </root> | ||||||
|  | @ -1512,4 +1512,10 @@ | ||||||
|   <data name="TbFakeIPTips" xml:space="preserve"> |   <data name="TbFakeIPTips" xml:space="preserve"> | ||||||
|     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> |     <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="TbCertSha256" xml:space="preserve"> | ||||||
|  |     <value>Server Certificate Fingerprint (SHA-256)</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCertSha256Tips" xml:space="preserve"> | ||||||
|  |     <value>Hex SHA-256, comma-separated for certificate chain</value> | ||||||
|  |   </data> | ||||||
| </root> | </root> | ||||||
|  | @ -43,16 +43,7 @@ public partial class CoreConfigSingboxService | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Tun2SocksAddress |             await GenOutboundDnsRule(node, singboxConfig, Global.SingboxOutboundResolverTag); | ||||||
|             if (node != null && Utils.IsDomain(node.Address)) |  | ||||||
|             { |  | ||||||
|                 singboxConfig.dns.rules ??= new List<Rule4Sbox>(); |  | ||||||
|                 singboxConfig.dns.rules.Insert(0, new Rule4Sbox |  | ||||||
|                 { |  | ||||||
|                     server = Global.SingboxOutboundResolverTag, |  | ||||||
|                     domain = [node.Address], |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|  | @ -346,16 +337,7 @@ public partial class CoreConfigSingboxService | ||||||
|                 await GenDnsDomainsLegacyCompatible(singboxConfig, item); |                 await GenDnsDomainsLegacyCompatible(singboxConfig, item); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Tun2SocksAddress |             await GenOutboundDnsRule(node, singboxConfig, Global.SingboxFinalResolverTag); | ||||||
|             if (node != null && Utils.IsDomain(node.Address)) |  | ||||||
|             { |  | ||||||
|                 singboxConfig.dns.rules ??= new List<Rule4Sbox>(); |  | ||||||
|                 singboxConfig.dns.rules.Insert(0, new Rule4Sbox |  | ||||||
|                 { |  | ||||||
|                     server = Global.SingboxFinalResolverTag, |  | ||||||
|                     domain = [node.Address], |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|  | @ -425,6 +407,37 @@ public partial class CoreConfigSingboxService | ||||||
|         return await Task.FromResult(0); |         return await Task.FromResult(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private async Task<int> GenOutboundDnsRule(ProfileItem? node, SingboxConfig singboxConfig, string? server) | ||||||
|  |     { | ||||||
|  |         if (node == null) | ||||||
|  |         { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var domain = string.Empty; | ||||||
|  |         if (Utils.IsDomain(node.Address)) // normal outbound | ||||||
|  |         { | ||||||
|  |             domain = node.Address; | ||||||
|  |         } | ||||||
|  |         else if (node.Address == Global.Loopback && node.SpiderX.IsNotEmpty() && Utils.IsDomain(node.SpiderX)) // Tun2SocksAddress | ||||||
|  |         { | ||||||
|  |             domain = node.SpiderX; | ||||||
|  |         } | ||||||
|  |         if (domain.IsNullOrEmpty()) | ||||||
|  |         { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         singboxConfig.dns.rules ??= new List<Rule4Sbox>(); | ||||||
|  |         singboxConfig.dns.rules.Insert(0, new Rule4Sbox | ||||||
|  |         { | ||||||
|  |             server = server, | ||||||
|  |             domain = [domain], | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         return await Task.FromResult(0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private static Server4Sbox? ParseDnsAddress(string address) |     private static Server4Sbox? ParseDnsAddress(string address) | ||||||
|     { |     { | ||||||
|         var addressFirst = address?.Split(address.Contains(',') ? ',' : ';').FirstOrDefault()?.Trim(); |         var addressFirst = address?.Split(address.Contains(',') ? ',' : ';').FirstOrDefault()?.Trim(); | ||||||
|  |  | ||||||
|  | @ -251,6 +251,20 @@ public partial class CoreConfigSingboxService | ||||||
|                         fingerprint = node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : node.Fingerprint |                         fingerprint = node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : node.Fingerprint | ||||||
|                     }; |                     }; | ||||||
|                 } |                 } | ||||||
|  |                 if (node.CertSha256.IsNotEmpty()) | ||||||
|  |                 { | ||||||
|  |                     // hex to raw to base64 | ||||||
|  |                     var certSha256List = Utils.ParseCertSha256ToList(node.CertSha256) | ||||||
|  |                         .Select(s => Convert.ToBase64String( | ||||||
|  |                             Enumerable.Range(0, 32) | ||||||
|  |                                       .Select(i => Convert.ToByte(s.Substring(i * 2, 2), 16)) | ||||||
|  |                                       .ToArray())) | ||||||
|  |                         .ToList(); | ||||||
|  |                     if (certSha256List.Count > 0) | ||||||
|  |                     { | ||||||
|  |                         tls.certificate_sha256 = certSha256List; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|                 if (node.StreamSecurity == Global.StreamSecurityReality) |                 if (node.StreamSecurity == Global.StreamSecurityReality) | ||||||
|                 { |                 { | ||||||
|                     tls.reality = new Reality4Sbox() |                     tls.reality = new Reality4Sbox() | ||||||
|  |  | ||||||
|  | @ -277,6 +277,14 @@ public partial class CoreConfigV2rayService | ||||||
|                 { |                 { | ||||||
|                     tlsSettings.serverName = Utils.String2List(host)?.First(); |                     tlsSettings.serverName = Utils.String2List(host)?.First(); | ||||||
|                 } |                 } | ||||||
|  |                 if (node.CertSha256.IsNotEmpty()) | ||||||
|  |                 { | ||||||
|  |                     var certSha256List = Utils.ParseCertSha256ToList(node.CertSha256); | ||||||
|  |                     if (certSha256List.Count > 0) | ||||||
|  |                     { | ||||||
|  |                         tlsSettings.pinnedPeerCertificateSha256 = certSha256List; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|                 streamSettings.tlsSettings = tlsSettings; |                 streamSettings.tlsSettings = tlsSettings; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -709,9 +709,9 @@ | ||||||
|                 <Grid |                 <Grid | ||||||
|                     x:Name="gridTlsMore" |                     x:Name="gridTlsMore" | ||||||
|                     Grid.Row="7" |                     Grid.Row="7" | ||||||
|                     ColumnDefinitions="180,Auto" |                     ColumnDefinitions="180,Auto,Auto" | ||||||
|                     IsVisible="False" |                     IsVisible="False" | ||||||
|                     RowDefinitions="Auto,Auto,Auto,Auto,Auto"> |                     RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto"> | ||||||
| 
 | 
 | ||||||
|                     <TextBlock |                     <TextBlock | ||||||
|                         Grid.Row="1" |                         Grid.Row="1" | ||||||
|  | @ -765,6 +765,26 @@ | ||||||
|                         Grid.Column="1" |                         Grid.Column="1" | ||||||
|                         Width="200" |                         Width="200" | ||||||
|                         Margin="{StaticResource Margin4}" /> |                         Margin="{StaticResource Margin4}" /> | ||||||
|  | 
 | ||||||
|  |                     <TextBlock | ||||||
|  |                         Grid.Row="5" | ||||||
|  |                         Grid.Column="0" | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         VerticalAlignment="Center" | ||||||
|  |                         Text="{x:Static resx:ResUI.TbCertSha256}" /> | ||||||
|  |                     <TextBox | ||||||
|  |                         x:Name="txtCertSha256" | ||||||
|  |                         Grid.Row="5" | ||||||
|  |                         Grid.Column="1" | ||||||
|  |                         Width="400" | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         HorizontalAlignment="Left" /> | ||||||
|  |                     <TextBlock | ||||||
|  |                         Grid.Row="5" | ||||||
|  |                         Grid.Column="2" | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         VerticalAlignment="Center" | ||||||
|  |                         Text="{x:Static resx:ResUI.TbCertSha256Tips}" /> | ||||||
|                 </Grid> |                 </Grid> | ||||||
|                 <Grid |                 <Grid | ||||||
|                     x:Name="gridRealityMore" |                     x:Name="gridRealityMore" | ||||||
|  |  | ||||||
|  | @ -189,6 +189,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel> | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.SelectedValue).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.SelectedValue).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.SelectedValue).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.SelectedValue).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.SelectedValue).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.SelectedValue).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.SelectedSource.CertSha256, v => v.txtCertSha256.Text).DisposeWith(disposables); | ||||||
|             //reality |             //reality | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint2.SelectedValue).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint2.SelectedValue).DisposeWith(disposables); | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								v2rayN/v2rayN.slnx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								v2rayN/v2rayN.slnx
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | <Solution> | ||||||
|  |   <Folder Name="/GitHub Action/"> | ||||||
|  |     <File Path="../.github/workflows/build-all.yml" /> | ||||||
|  |     <File Path="../.github/workflows/build-linux.yml" /> | ||||||
|  |     <File Path="../.github/workflows/build-osx.yml" /> | ||||||
|  |     <File Path="../.github/workflows/build-windows-desktop.yml" /> | ||||||
|  |     <File Path="../.github/workflows/build-windows.yml" /> | ||||||
|  |     <File Path="../.github/workflows/winget-publish.yml" /> | ||||||
|  |     <File Path="../package-appimage.sh" /> | ||||||
|  |     <File Path="../package-debian.sh" /> | ||||||
|  |     <File Path="../package-osx.sh" /> | ||||||
|  |     <File Path="../package-release-zip.sh" /> | ||||||
|  |     <File Path="../pkg2appimage.yml" /> | ||||||
|  |   </Folder> | ||||||
|  |   <Folder Name="/Solution Files/"> | ||||||
|  |     <File Path="Directory.Build.props" /> | ||||||
|  |     <File Path="Directory.Packages.props" /> | ||||||
|  |   </Folder> | ||||||
|  |   <Project Path="AmazTool/AmazTool.csproj" /> | ||||||
|  |   <Project Path="GlobalHotKeys/src/GlobalHotKeys/GlobalHotKeys.csproj" /> | ||||||
|  |   <Project Path="ServiceLib/ServiceLib.csproj" /> | ||||||
|  |   <Project Path="v2rayN.Desktop/v2rayN.Desktop.csproj" /> | ||||||
|  |   <Project Path="v2rayN/v2rayN.csproj" /> | ||||||
|  | </Solution> | ||||||
|  | @ -32,8 +32,8 @@ public class QRCodeUtils | ||||||
|         { |         { | ||||||
|             GetDpi(window, out var dpiX, out var dpiY); |             GetDpi(window, out var dpiX, out var dpiY); | ||||||
| 
 | 
 | ||||||
|             var left = (int)(SystemParameters.WorkArea.Left); |             var left = (int)SystemParameters.WorkArea.Left; | ||||||
|             var top = (int)(SystemParameters.WorkArea.Top); |             var top = (int)SystemParameters.WorkArea.Top; | ||||||
|             var width = (int)(SystemParameters.WorkArea.Width / dpiX); |             var width = (int)(SystemParameters.WorkArea.Width / dpiX); | ||||||
|             var height = (int)(SystemParameters.WorkArea.Height / dpiY); |             var height = (int)(SystemParameters.WorkArea.Height / dpiY); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -928,10 +928,12 @@ | ||||||
|                         <RowDefinition Height="Auto" /> |                         <RowDefinition Height="Auto" /> | ||||||
|                         <RowDefinition Height="Auto" /> |                         <RowDefinition Height="Auto" /> | ||||||
|                         <RowDefinition Height="Auto" /> |                         <RowDefinition Height="Auto" /> | ||||||
|  |                         <RowDefinition Height="Auto" /> | ||||||
|                     </Grid.RowDefinitions> |                     </Grid.RowDefinitions> | ||||||
|                     <Grid.ColumnDefinitions> |                     <Grid.ColumnDefinitions> | ||||||
|                         <ColumnDefinition Width="180" /> |                         <ColumnDefinition Width="180" /> | ||||||
|                         <ColumnDefinition Width="Auto" /> |                         <ColumnDefinition Width="Auto" /> | ||||||
|  |                         <ColumnDefinition Width="Auto" /> | ||||||
|                     </Grid.ColumnDefinitions> |                     </Grid.ColumnDefinitions> | ||||||
| 
 | 
 | ||||||
|                     <TextBlock |                     <TextBlock | ||||||
|  | @ -995,6 +997,29 @@ | ||||||
|                         Width="200" |                         Width="200" | ||||||
|                         Margin="{StaticResource Margin4}" |                         Margin="{StaticResource Margin4}" | ||||||
|                         Style="{StaticResource DefComboBox}" /> |                         Style="{StaticResource DefComboBox}" /> | ||||||
|  | 
 | ||||||
|  |                     <TextBlock | ||||||
|  |                         Grid.Row="5" | ||||||
|  |                         Grid.Column="0" | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         VerticalAlignment="Center" | ||||||
|  |                         Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                         Text="{x:Static resx:ResUI.TbCertSha256}" /> | ||||||
|  |                     <TextBox | ||||||
|  |                         x:Name="txtCertSha256" | ||||||
|  |                         Grid.Row="5" | ||||||
|  |                         Grid.Column="1" | ||||||
|  |                         Width="400" | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         HorizontalAlignment="Left" | ||||||
|  |                         Style="{StaticResource DefTextBox}" /> | ||||||
|  |                     <TextBlock | ||||||
|  |                         Grid.Row="5" | ||||||
|  |                         Grid.Column="2" | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         VerticalAlignment="Center" | ||||||
|  |                         Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                         Text="{x:Static resx:ResUI.TbCertSha256Tips}" /> | ||||||
|                 </Grid> |                 </Grid> | ||||||
|                 <Grid |                 <Grid | ||||||
|                     x:Name="gridRealityMore" |                     x:Name="gridRealityMore" | ||||||
|  |  | ||||||
|  | @ -183,6 +183,7 @@ public partial class AddServerWindow | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.SelectedSource.CertSha256, v => v.txtCertSha256.Text).DisposeWith(disposables); | ||||||
|             //reality |             //reality | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint2.Text).DisposeWith(disposables); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue