Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a871e9f
feat: add cipherSuites option and "unsafe" fingerprint to TLS UI sett…
Copilot Jul 10, 2026
b2a341e
fix: initialize CipherSuites to string.Empty for null safety
Copilot Jul 10, 2026
cde1880
fix: cipherSuites should be string (not list) per xray-core spec; add…
Copilot Jul 10, 2026
1db8611
feat: add TbCipherSuites to all locale resource files
Copilot Jul 10, 2026
d3ebb74
fix: disable txtCipherSuites for Hysteria2 and Naive protocols
Copilot Jul 10, 2026
f465632
Merge pull request #1 from patterniha/copilot/add-ciphersuites-and-un…
patterniha Jul 10, 2026
e12646d
fix: sing-box "unsafe" fingerprint guard and CipherSuites resets (fol…
patterniha Jul 10, 2026
483cb45
Merge pull request #2 from patterniha/fix/cipher-suites-unsafe-followup
patterniha Jul 10, 2026
1349455
feat: round-trip CipherSuites in share links and VMess QR code
patterniha Jul 10, 2026
02c9808
Merge pull request #3 from patterniha/feat/cipher-suites-share-link
patterniha Jul 10, 2026
763236d
feat: apply CipherSuites to sing-box TLS outbounds
patterniha Jul 10, 2026
5a8ec29
Merge pull request #4 from patterniha/feat/cipher-suites-share-link
patterniha Jul 10, 2026
de4339e
Merge upstream 2dust/master, resolve conflicts with cipherSuites/unsa…
patterniha Jul 16, 2026
c9650d7
Merge remote-tracking branch 'upstream/master'
patterniha Jul 17, 2026
30d1f76
Merge remote-tracking branch 'upstream/master'
patterniha Jul 18, 2026
d5dbe73
Merge remote-tracking branch 'upstream/master'
patterniha Jul 19, 2026
26c7fc0
Merge remote-tracking branch 'upstream/master'
patterniha Jul 21, 2026
ecb597f
Merge remote-tracking branch 'upstream/master'
patterniha Jul 27, 2026
1a66b40
Merge remote-tracking branch 'upstream/master'
patterniha Jul 30, 2026
793f5e9
Merge remote-tracking branch 'upstream/master'
patterniha Aug 1, 2026
252a225
Merge upstream 2dust/master, keep cipherSuites export alongside upstr…
patterniha Aug 6, 2026
c46d2b7
Merge branch '2dust:master' into master
patterniha Aug 6, 2026
1bd06a0
Merge branch '2dust:master' into master
patterniha Aug 7, 2026
e4ccd96
Merge branch '2dust:master' into master
patterniha Aug 8, 2026
e4d4142
Merge branch '2dust:master' into master
patterniha Aug 9, 2026
ea82408
Merge branch '2dust:master' into master
patterniha Aug 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions v2rayN/ServiceLib/Global.cs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ public class Global
"qq",
"random",
"randomized",
"unsafe",
""
];

Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Handler/ConfigHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ public static async Task<int> AddServer(Config config, ProfileItem profileItem)
item.AllowInsecure = profileItem.AllowInsecure;
item.Fingerprint = profileItem.Fingerprint;
item.Alpn = profileItem.Alpn;
item.CipherSuites = profileItem.CipherSuites;

item.PublicKey = profileItem.PublicKey;
item.ShortId = profileItem.ShortId;
Expand Down Expand Up @@ -777,6 +778,7 @@ public static async Task<int> AddHysteria2Server(Config config, ProfileItem prof
profileItem.Fingerprint = string.Empty;
profileItem.Alpn = string.Empty;
//profileItem.Alpn = "h3";
profileItem.CipherSuites = string.Empty;
profileItem.Network = string.Empty;

if (profileItem.StreamSecurity.IsNullOrEmpty())
Expand Down Expand Up @@ -979,6 +981,7 @@ public static async Task<int> AddNaiveServer(Config config, ProfileItem profileI
profileItem.Password = profileItem.Password.TrimEx();
profileItem.Fingerprint = string.Empty;
profileItem.Alpn = string.Empty;
profileItem.CipherSuites = string.Empty;
profileItem.Network = string.Empty;
profileItem.AllowInsecure = string.Empty;
if (profileItem.StreamSecurity.IsNullOrEmpty())
Expand Down
5 changes: 5 additions & 0 deletions v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ protected static int ToUriQuery(ProfileItem item, string? securityDef, ref Dicti
{
dicQuery.Add("alpn", Utils.UrlEncode(item.Alpn));
}
if (item.CipherSuites.IsNotEmpty())
{
dicQuery.Add("cs", Utils.UrlEncode(item.CipherSuites));
}
}
if (item.EchConfigList.IsNotEmpty())
{
Expand Down Expand Up @@ -203,6 +207,7 @@ protected static int ResolveUriQuery(NameValueCollection query, ref ProfileItem
item.StreamSecurity = GetQueryValue(query, "security");
item.Sni = GetQueryValue(query, "sni");
item.Alpn = GetQueryDecoded(query, "alpn");
item.CipherSuites = GetQueryDecoded(query, "cs");
item.Fingerprint = GetQueryDecoded(query, "fp");
item.PublicKey = GetQueryDecoded(query, "pbk");
item.ShortId = GetQueryDecoded(query, "sid");
Expand Down
2 changes: 2 additions & 0 deletions v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class VmessFmt : BaseFmt
sni = item.Sni,
alpn = item.Alpn,
fp = item.Fingerprint,
cs = item.CipherSuites,
insecure = item.GetAllowInsecure() ? "1" : "0",
vcn = item.VerifyPeerCertByName,
pcs = item.CertSha
Expand Down Expand Up @@ -142,6 +143,7 @@ public class VmessFmt : BaseFmt
item.Sni = Utils.ToString(vmessQRCode.sni);
item.Alpn = Utils.ToString(vmessQRCode.alpn);
item.Fingerprint = Utils.ToString(vmessQRCode.fp);
item.CipherSuites = Utils.ToString(vmessQRCode.cs);
item.AllowInsecure = vmessQRCode.insecure == "1" ? Global.StringTrue : string.Empty;
item.VerifyPeerCertByName = Utils.ToString(vmessQRCode.vcn);
item.CertSha = Utils.ToString(vmessQRCode.pcs);
Expand Down
1 change: 1 addition & 0 deletions v2rayN/ServiceLib/Models/CoreConfigs/SingboxConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ public class Tls4Sbox
public string? server_name { get; set; }
public bool? insecure { get; set; }
public List<string>? alpn { get; set; }
public List<string>? cipher_suites { get; set; }
public Utls4Sbox? utls { get; set; }
public Reality4Sbox? reality { get; set; }
public bool? fragment { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions v2rayN/ServiceLib/Models/CoreConfigs/V2rayConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ public class TlsSettings4Ray

public List<string>? alpn { get; set; }

public string? cipherSuites { get; set; }

public string? fingerprint { get; set; }

public bool? show { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions v2rayN/ServiceLib/Models/Dto/VmessQRCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public class VmessQRCode

public string fp { get; set; } = string.Empty;

public string cs { get; set; } = string.Empty;

public string insecure { get; set; } = string.Empty;

public string vcn { get; set; } = string.Empty;
Expand Down
1 change: 1 addition & 0 deletions v2rayN/ServiceLib/Models/Entities/ProfileItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ public bool GetAllowInsecure()
public string AllowInsecure { get; set; }
public string Sni { get; set; }
public string Alpn { get; set; } = string.Empty;
public string CipherSuites { get; set; } = string.Empty;
public string Fingerprint { get; set; }
public string PublicKey { get; set; }
public string ShortId { get; set; }
Expand Down
9 changes: 9 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.fa.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>AlterId</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>اثرانگشت</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.fr.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>ID supplémentaire (alterId)</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Empreinte</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.hu.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>Alter ID</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Ujjlenyomat</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.id.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>Alter ID</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Sidik jari</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>Alter ID</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Fingerprint</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.ru.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>AlterId</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Отпечаток</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>额外 ID (alterId)</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Fingerprint</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@
<data name="TbAlterId" xml:space="preserve">
<value>額外 ID (alterid)</value>
</data>
<data name="TbCipherSuites" xml:space="preserve">
<value>Cipher Suites</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Fingerprint</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,8 @@ private void FillOutboundTls(Outbound4Sbox outbound)
tls.fragment = true;
tls.record_fragment = true;
}
if (_node.Fingerprint.IsNotEmpty())
// "unsafe" is an Xray-only fingerprint; sing-box's uTLS rejects it, so fall back to plain TLS
if (_node.Fingerprint.IsNotEmpty() && _node.Fingerprint != "unsafe")
{
tls.utls = new Utls4Sbox()
{
Expand All @@ -454,6 +455,15 @@ private void FillOutboundTls(Outbound4Sbox outbound)
}
if (_node.StreamSecurity == Global.StreamSecurity)
{
if (_node.CipherSuites.IsNotEmpty())
{
// Xray stores cipher suites as a colon-separated string; sing-box wants a list of the same Go TLS names
tls.cipher_suites = _node.CipherSuites
.Split([':', ','], StringSplitOptions.RemoveEmptyEntries)
.Select(c => c.Trim())
.Where(c => c.IsNotEmpty())
.ToList();
}
var certs = CertPemManager.ParsePemChain(_node.Cert);
if (certs.Count > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ private void FillBoundStreamSettings(Outbounds4Ray outbound)
TlsSettings4Ray tlsSettings = new()
{
alpn = _node.GetAlpn(),
cipherSuites = _node.CipherSuites.IsNullOrEmpty() ? null : _node.CipherSuites,
fingerprint = _node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : _node.Fingerprint,
echConfigList = _node.EchConfigList.NullIfEmpty(),
verifyPeerCertByName = _node.VerifyPeerCertByName.NullIfEmpty(),
Expand Down
30 changes: 22 additions & 8 deletions v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -1132,7 +1132,7 @@
Grid.Row="8"
ColumnDefinitions="300,Auto"
IsVisible="False"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">

<TextBlock
Grid.Row="1"
Expand Down Expand Up @@ -1179,50 +1179,64 @@
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbCipherSuites}" />
<TextBox
x:Name="txtCipherSuites"
Grid.Row="4"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />

<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbAllowInsecure}" />
<ToggleSwitch
x:Name="togAllowInsecure"
Grid.Row="4"
Grid.Row="5"
Grid.Column="1"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />

<TextBlock
Grid.Row="5"
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbEchConfigList}" />
<TextBox
x:Name="txtEchConfigList"
Grid.Row="5"
Grid.Row="6"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />

<TextBlock
Grid.Row="6"
Grid.Row="7"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbVerifyPeerCertByName}" />
<TextBox
x:Name="txtVerifyPeerCertByName"
Grid.Row="6"
Grid.Row="7"
Grid.Column="1"
Width="400"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />

<TextBlock
Grid.Row="7"
Grid.Row="8"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbCertPinning}" />
<StackPanel
Grid.Row="7"
Grid.Row="8"
Grid.Column="1"
VerticalAlignment="Center"
Orientation="Horizontal">
Expand Down
3 changes: 3 additions & 0 deletions v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ public AddServerWindow()
this.Bind(ViewModel, vm => vm.AllowInsecure, v => v.togAllowInsecure.IsChecked).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.CipherSuites, v => v.txtCipherSuites.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CertSha, v => v.txtCertSha256Pinning.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CertTip, v => v.labCertPinning.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Cert, v => v.txtCert.Text).DisposeWith(disposables);
Expand Down Expand Up @@ -241,6 +242,7 @@ private void InitializeData(ProfileItem profileItem)
gridTransport.IsVisible = false;
cmbFingerprint.IsEnabled = false;
cmbAlpn.IsEnabled = false;
txtCipherSuites.IsEnabled = false;
break;

case EConfigType.TUIC:
Expand Down Expand Up @@ -280,6 +282,7 @@ private void InitializeData(ProfileItem profileItem)
gridFinalmask.IsVisible = false;
cmbFingerprint.IsEnabled = false;
cmbAlpn.IsEnabled = false;
txtCipherSuites.IsEnabled = false;
togAllowInsecure.IsEnabled = false;

cmbCongestionControl12.ItemsSource = Global.NaiveCongestionControls;
Expand Down
Loading