Add TLS trick config options
This commit is contained in:
45
lib/core/model/range.dart
Normal file
45
lib/core/model/range.dart
Normal file
@@ -0,0 +1,45 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'range.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class RangeWithOptionalCeil with _$RangeWithOptionalCeil {
|
||||
const RangeWithOptionalCeil._();
|
||||
|
||||
const factory RangeWithOptionalCeil({
|
||||
required int min,
|
||||
int? max,
|
||||
}) = _RangeWithOptionalCeil;
|
||||
|
||||
String format() => "$min${max != null ? "-$max" : ""}";
|
||||
|
||||
factory RangeWithOptionalCeil.fromString(String input) =>
|
||||
switch (input.split("-")) {
|
||||
[final String min] => RangeWithOptionalCeil(min: int.parse(min)),
|
||||
[final String min, final String max] => RangeWithOptionalCeil(
|
||||
min: int.parse(min),
|
||||
max: int.parse(max),
|
||||
),
|
||||
_ => throw Exception("Invalid range: $input"),
|
||||
};
|
||||
|
||||
static RangeWithOptionalCeil? tryParse(String input) {
|
||||
try {
|
||||
return RangeWithOptionalCeil.fromString(input);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RangeWithOptionalCeilJsonConverter
|
||||
implements JsonConverter<RangeWithOptionalCeil, String> {
|
||||
const RangeWithOptionalCeilJsonConverter();
|
||||
|
||||
@override
|
||||
RangeWithOptionalCeil fromJson(String json) =>
|
||||
RangeWithOptionalCeil.fromString(json);
|
||||
|
||||
@override
|
||||
String toJson(RangeWithOptionalCeil object) => object.format();
|
||||
}
|
||||
@@ -96,6 +96,12 @@ class ConfigOptionRepositoryImpl
|
||||
bypassLan: persisted.bypassLan,
|
||||
enableFakeDns: persisted.enableFakeDns,
|
||||
independentDnsCache: persisted.independentDnsCache,
|
||||
enableTlsFragment: persisted.enableTlsFragment,
|
||||
tlsFragmentSize: persisted.tlsFragmentSize,
|
||||
tlsFragmentSleep: persisted.tlsFragmentSleep,
|
||||
enableTlsMixedSniCase: persisted.enableTlsMixedSniCase,
|
||||
enableTlsPadding: persisted.enableTlsPadding,
|
||||
tlsPaddingSize: persisted.tlsPaddingSize,
|
||||
geoipPath: geoAssetPathResolver.relativePath(
|
||||
geoAssets.geoip.providerName,
|
||||
geoAssets.geoip.fileName,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hiddify/core/model/range.dart';
|
||||
import 'package:hiddify/core/utils/json_converters.dart';
|
||||
import 'package:hiddify/features/config_option/model/config_option_patch.dart';
|
||||
import 'package:hiddify/features/log/model/log_level.dart';
|
||||
@@ -37,6 +38,18 @@ class ConfigOptionEntity with _$ConfigOptionEntity {
|
||||
@Default(false) bool bypassLan,
|
||||
@Default(false) bool enableFakeDns,
|
||||
@Default(true) bool independentDnsCache,
|
||||
@Default(false) bool enableTlsFragment,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
@Default(RangeWithOptionalCeil(min: 10, max: 100))
|
||||
RangeWithOptionalCeil tlsFragmentSize,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
@Default(RangeWithOptionalCeil(min: 50, max: 200))
|
||||
RangeWithOptionalCeil tlsFragmentSleep,
|
||||
@Default(false) bool enableTlsMixedSniCase,
|
||||
@Default(false) bool enableTlsPadding,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
@Default(RangeWithOptionalCeil(min: 100, max: 200))
|
||||
RangeWithOptionalCeil tlsPaddingSize,
|
||||
}) = _ConfigOptionEntity;
|
||||
|
||||
static ConfigOptionEntity initial = ConfigOptionEntity(
|
||||
@@ -72,6 +85,13 @@ class ConfigOptionEntity with _$ConfigOptionEntity {
|
||||
bypassLan: patch.bypassLan ?? bypassLan,
|
||||
enableFakeDns: patch.enableFakeDns ?? enableFakeDns,
|
||||
independentDnsCache: patch.independentDnsCache ?? independentDnsCache,
|
||||
enableTlsFragment: patch.enableTlsFragment ?? enableTlsFragment,
|
||||
tlsFragmentSize: patch.tlsFragmentSize ?? tlsFragmentSize,
|
||||
tlsFragmentSleep: patch.tlsFragmentSleep ?? tlsFragmentSleep,
|
||||
enableTlsMixedSniCase:
|
||||
patch.enableTlsMixedSniCase ?? enableTlsMixedSniCase,
|
||||
enableTlsPadding: patch.enableTlsPadding ?? enableTlsPadding,
|
||||
tlsPaddingSize: patch.tlsPaddingSize ?? tlsPaddingSize,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hiddify/core/model/range.dart';
|
||||
import 'package:hiddify/core/utils/json_converters.dart';
|
||||
import 'package:hiddify/features/log/model/log_level.dart';
|
||||
import 'package:hiddify/singbox/model/singbox_config_enum.dart';
|
||||
@@ -32,6 +33,14 @@ class ConfigOptionPatch with _$ConfigOptionPatch {
|
||||
bool? bypassLan,
|
||||
bool? enableFakeDns,
|
||||
bool? independentDnsCache,
|
||||
bool? enableTlsFragment,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
RangeWithOptionalCeil? tlsFragmentSize,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
RangeWithOptionalCeil? tlsFragmentSleep,
|
||||
bool? enableTlsMixedSniCase,
|
||||
bool? enableTlsPadding,
|
||||
@RangeWithOptionalCeilJsonConverter() RangeWithOptionalCeil? tlsPaddingSize,
|
||||
}) = _ConfigOptionPatch;
|
||||
|
||||
factory ConfigOptionPatch.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hiddify/core/localization/translations.dart';
|
||||
import 'package:hiddify/core/model/range.dart';
|
||||
import 'package:hiddify/features/config_option/model/config_option_entity.dart';
|
||||
import 'package:hiddify/features/config_option/model/config_option_patch.dart';
|
||||
import 'package:hiddify/features/config_option/notifier/config_option_notifier.dart';
|
||||
@@ -164,18 +165,6 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
// ),
|
||||
const SettingsDivider(),
|
||||
SettingsSection(t.settings.config.section.inbound),
|
||||
// if (PlatformUtils.isDesktop) ...[
|
||||
// SwitchListTile(
|
||||
// title: Text(t.settings.config.enableTun),
|
||||
// value: options.enableTun,
|
||||
// onChanged: ref.read(enableTunStore.notifier).update,
|
||||
// ),
|
||||
// SwitchListTile(
|
||||
// title: Text(t.settings.config.setSystemProxy),
|
||||
// value: options.setSystemProxy,
|
||||
// onChanged: ref.read(setSystemProxyStore.notifier).update,
|
||||
// ),
|
||||
// ],
|
||||
ListTile(
|
||||
title: Text(t.settings.config.serviceMode),
|
||||
subtitle: Text(options.serviceMode.present(t)),
|
||||
@@ -251,6 +240,79 @@ class ConfigOptionsPage extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
const SettingsDivider(),
|
||||
SettingsSection(t.settings.config.section.outbound),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.config.enableTlsFragment),
|
||||
value: options.enableTlsFragment,
|
||||
onChanged: (value) async =>
|
||||
changeOption(ConfigOptionPatch(enableTlsFragment: value)),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(t.settings.config.tlsFragmentSize),
|
||||
subtitle: Text(options.tlsFragmentSize.format()),
|
||||
onTap: () async {
|
||||
final range = await SettingsInputDialog(
|
||||
title: t.settings.config.tlsFragmentSize,
|
||||
initialValue: options.tlsFragmentSize.format(),
|
||||
resetValue: defaultOptions.tlsFragmentSize.format(),
|
||||
).show(context);
|
||||
if (range == null) return;
|
||||
await changeOption(
|
||||
ConfigOptionPatch(
|
||||
tlsFragmentSize: RangeWithOptionalCeil.tryParse(range),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(t.settings.config.tlsFragmentSleep),
|
||||
subtitle: Text(options.tlsFragmentSleep.format()),
|
||||
onTap: () async {
|
||||
final range = await SettingsInputDialog(
|
||||
title: t.settings.config.tlsFragmentSleep,
|
||||
initialValue: options.tlsFragmentSleep.format(),
|
||||
resetValue: defaultOptions.tlsFragmentSleep.format(),
|
||||
).show(context);
|
||||
if (range == null) return;
|
||||
await changeOption(
|
||||
ConfigOptionPatch(
|
||||
tlsFragmentSleep: RangeWithOptionalCeil.tryParse(range),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.config.enableTlsMixedSniCase),
|
||||
value: options.enableTlsMixedSniCase,
|
||||
onChanged: (value) async => changeOption(
|
||||
ConfigOptionPatch(enableTlsMixedSniCase: value),
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.config.enableTlsPadding),
|
||||
value: options.enableTlsPadding,
|
||||
onChanged: (value) async => changeOption(
|
||||
ConfigOptionPatch(enableTlsPadding: value),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(t.settings.config.tlsPaddingSize),
|
||||
subtitle: Text(options.tlsPaddingSize.format()),
|
||||
onTap: () async {
|
||||
final range = await SettingsInputDialog(
|
||||
title: t.settings.config.tlsPaddingSize,
|
||||
initialValue: options.tlsPaddingSize.format(),
|
||||
resetValue: defaultOptions.tlsPaddingSize.format(),
|
||||
).show(context);
|
||||
if (range == null) return;
|
||||
await changeOption(
|
||||
ConfigOptionPatch(
|
||||
tlsPaddingSize: RangeWithOptionalCeil.tryParse(range),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SettingsDivider(),
|
||||
SettingsSection(t.settings.config.section.misc),
|
||||
ListTile(
|
||||
title: Text(t.settings.config.connectionTestUrl),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hiddify/core/model/range.dart';
|
||||
import 'package:hiddify/features/log/model/log_level.dart';
|
||||
import 'package:hiddify/singbox/model/singbox_config_enum.dart';
|
||||
import 'package:hiddify/singbox/model/singbox_rule.dart';
|
||||
@@ -36,6 +37,15 @@ class SingboxConfigOption with _$SingboxConfigOption {
|
||||
required bool bypassLan,
|
||||
required bool enableFakeDns,
|
||||
required bool independentDnsCache,
|
||||
required bool enableTlsFragment,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
required RangeWithOptionalCeil tlsFragmentSize,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
required RangeWithOptionalCeil tlsFragmentSleep,
|
||||
required bool enableTlsMixedSniCase,
|
||||
required bool enableTlsPadding,
|
||||
@RangeWithOptionalCeilJsonConverter()
|
||||
required RangeWithOptionalCeil tlsPaddingSize,
|
||||
required String geoipPath,
|
||||
required String geositePath,
|
||||
required List<SingboxRule> rules,
|
||||
|
||||
Reference in New Issue
Block a user