diff --git a/go.mod b/go.mod
index e94db57f..58904358 100644
--- a/go.mod
+++ b/go.mod
@@ -40,7 +40,7 @@ require (
github.com/go-playground/validator/v10 v10.22.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/btree v1.1.3 // indirect
- github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
+ github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect
github.com/gorilla/context v1.1.2 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
github.com/gorilla/sessions v1.4.0 // indirect
@@ -57,7 +57,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
- github.com/onsi/ginkgo/v2 v2.20.1 // indirect
+ github.com/onsi/ginkgo/v2 v2.20.2 // indirect
github.com/pires/go-proxyproto v0.7.0 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
diff --git a/go.sum b/go.sum
index 797d1ef0..1a20f004 100644
--- a/go.sum
+++ b/go.sum
@@ -98,8 +98,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
+github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA=
+github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -164,8 +164,8 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
-github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo=
-github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
+github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
+github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
diff --git a/sub/sub.go b/sub/sub.go
index 47b6158c..a8a20868 100644
--- a/sub/sub.go
+++ b/sub/sub.go
@@ -92,6 +92,11 @@ func (s *Server) initRouter() (*gin.Engine, error) {
SubJsonFragment = ""
}
+ SubJsonNoise, err := s.settingService.GetSubJsonNoise()
+ if err != nil {
+ SubJsonNoise = ""
+ }
+
SubJsonMux, err := s.settingService.GetSubJsonMux()
if err != nil {
SubJsonMux = ""
@@ -106,7 +111,7 @@ func (s *Server) initRouter() (*gin.Engine, error) {
s.sub = NewSUBController(
g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates,
- SubJsonFragment, SubJsonMux, SubJsonRules)
+ SubJsonFragment, SubJsonNoise, SubJsonMux, SubJsonRules)
return engine, nil
}
diff --git a/sub/subController.go b/sub/subController.go
index 4f23c424..9afbc8da 100644
--- a/sub/subController.go
+++ b/sub/subController.go
@@ -27,6 +27,7 @@ func NewSUBController(
rModel string,
update string,
jsonFragment string,
+ jsonNoise string,
jsonMux string,
jsonRules string,
) *SUBController {
@@ -38,7 +39,7 @@ func NewSUBController(
updateInterval: update,
subService: sub,
- subJsonService: NewSubJsonService(jsonFragment, jsonMux, jsonRules, sub),
+ subJsonService: NewSubJsonService(jsonFragment, jsonNoise, jsonMux, jsonRules, sub),
}
a.initRouter(g)
return a
diff --git a/sub/subJsonService.go b/sub/subJsonService.go
index 8d90876f..cbda594a 100644
--- a/sub/subJsonService.go
+++ b/sub/subJsonService.go
@@ -21,13 +21,14 @@ type SubJsonService struct {
configJson map[string]interface{}
defaultOutbounds []json_util.RawMessage
fragment string
+ noise string
mux string
inboundService service.InboundService
SubService *SubService
}
-func NewSubJsonService(fragment string, mux string, rules string, subService *SubService) *SubJsonService {
+func NewSubJsonService(fragment string, noise string, mux string, rules string, subService *SubService) *SubJsonService {
var configJson map[string]interface{}
var defaultOutbounds []json_util.RawMessage
json.Unmarshal([]byte(defaultJson), &configJson)
@@ -52,10 +53,15 @@ func NewSubJsonService(fragment string, mux string, rules string, subService *Su
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment))
}
+ if noise != "" {
+ defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(noise))
+ }
+
return &SubJsonService{
configJson: configJson,
defaultOutbounds: defaultOutbounds,
fragment: fragment,
+ noise: noise,
mux: mux,
SubService: subService,
}
diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js
index f1909552..59da542a 100644
--- a/web/assets/js/model/outbound.js
+++ b/web/assets/js/model/outbound.js
@@ -861,23 +861,34 @@ Outbound.Settings = class extends CommonClass {
}
};
Outbound.FreedomSettings = class extends CommonClass {
- constructor(domainStrategy = '', fragment = {}) {
+ constructor(
+ domainStrategy = '',
+ timeout = '',
+ fragment = {},
+ noise = {}
+ ) {
super();
this.domainStrategy = domainStrategy;
+ this.timeout = timeout;
this.fragment = fragment;
+ this.noise = noise;
}
static fromJson(json = {}) {
return new Outbound.FreedomSettings(
json.domainStrategy,
+ json.timeout,
json.fragment ? Outbound.FreedomSettings.Fragment.fromJson(json.fragment) : undefined,
+ json.noise ? Outbound.FreedomSettings.Noise.fromJson(json.noise) : undefined,
);
}
toJson() {
return {
domainStrategy: ObjectUtil.isEmpty(this.domainStrategy) ? undefined : this.domainStrategy,
+ timeout: this.timeout,
fragment: Object.keys(this.fragment).length === 0 ? undefined : this.fragment,
+ noise: Object.keys(this.noise).length === 0 ? undefined : this.noise,
};
}
};
@@ -897,6 +908,21 @@ Outbound.FreedomSettings.Fragment = class extends CommonClass {
);
}
};
+Outbound.FreedomSettings.Noise = class extends CommonClass {
+ constructor(packets = '', delay = '') {
+ super();
+ this.packets = packets;
+ this.delay = delay;
+ }
+
+ static fromJson(json = {}) {
+ return new Outbound.FreedomSettings.Noise(
+ json.packets,
+ json.delay,
+ );
+ }
+};
+
Outbound.BlackholeSettings = class extends CommonClass {
constructor(type) {
super();
diff --git a/web/assets/js/model/setting.js b/web/assets/js/model/setting.js
index 607fd069..2dea875b 100644
--- a/web/assets/js/model/setting.js
+++ b/web/assets/js/model/setting.js
@@ -38,6 +38,7 @@ class AllSetting {
this.subURI = "";
this.subJsonURI = "";
this.subJsonFragment = "";
+ this.subJsonNoise = "";
this.subJsonMux = "";
this.subJsonRules = "";
diff --git a/web/entity/entity.go b/web/entity/entity.go
index 533fe973..ae11d614 100644
--- a/web/entity/entity.go
+++ b/web/entity/entity.go
@@ -52,6 +52,7 @@ type AllSetting struct {
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"`
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"`
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"`
+ SubJsonNoise string `json:"subJsonNoise" form:"subJsonNoise"`
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"`
SubJsonRules string `json:"subJsonRules" form:"subJsonRules"`
Datepicker string `json:"datepicker" form:"datepicker"`
diff --git a/web/html/xui/form/outbound.html b/web/html/xui/form/outbound.html
index 61af06e0..a579b7a6 100644
--- a/web/html/xui/form/outbound.html
+++ b/web/html/xui/form/outbound.html
@@ -22,6 +22,9 @@
[[ s ]]
+
+
+
outbound.settings.fragment = checked ? new Outbound.FreedomSettings.Fragment() : {}">
@@ -38,6 +41,17 @@
+
+ outbound.settings.noise = checked ? new Outbound.FreedomSettings.Noise() : {}">
+
+
+
+
+
+
+
+
+
@@ -95,10 +109,10 @@
-
+
-
+
@@ -257,25 +271,25 @@
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/web/html/xui/settings.html b/web/html/xui/settings.html
index f2379078..beab4df1 100644
--- a/web/html/xui/settings.html
+++ b/web/html/xui/settings.html
@@ -313,6 +313,24 @@
+
+
+
+
+ {{ i18n "pages.settings.noiseDesc"}}
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -412,6 +430,17 @@
}
}
},
+ defaultNoise: {
+ tag: "noise",
+ protocol: "freedom",
+ settings: {
+ domainStrategy: "AsIs",
+ noise: {
+ packets: "rand:5-10",
+ delay: "5-10",
+ }
+ },
+ },
defaultMux: {
enabled: true,
concurrency: 8,
@@ -611,6 +640,32 @@
}
}
},
+ noise: {
+ get: function () { return this.allSetting?.subJsonNoise != ""; },
+ set: function (v) {
+ this.allSetting.subJsonNoise = v ? JSON.stringify(this.defaultNoise) : "";
+ }
+ },
+ noisePackets: {
+ get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.packets : ""; },
+ set: function (v) {
+ if (v != "") {
+ newNoise = JSON.parse(this.allSetting.subJsonNoise);
+ newNoise.settings.noise.packets = v;
+ this.allSetting.subJsonNoise = JSON.stringify(newNoise);
+ }
+ }
+ },
+ noiseDelay: {
+ get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.delay : ""; },
+ set: function (v) {
+ if (v != "") {
+ newNoise = JSON.parse(this.allSetting.subJsonNoise);
+ newNoise.settings.noise.delay = v;
+ this.allSetting.subJsonNoise = JSON.stringify(newNoise);
+ }
+ }
+ },
enableMux: {
get: function () { return this.allSetting?.subJsonMux != ""; },
set: function (v) {
diff --git a/web/service/setting.go b/web/service/setting.go
index ec69f9c8..bddcacce 100644
--- a/web/service/setting.go
+++ b/web/service/setting.go
@@ -62,6 +62,7 @@ var defaultValueMap = map[string]string{
"subJsonPath": "/json/",
"subJsonURI": "",
"subJsonFragment": "",
+ "subJsonNoise": "",
"subJsonMux": "",
"subJsonRules": "",
"datepicker": "gregorian",
@@ -458,6 +459,10 @@ func (s *SettingService) GetSubJsonFragment() (string, error) {
return s.getString("subJsonFragment")
}
+func (s *SettingService) GetSubJsonNoise() (string, error) {
+ return s.getString("subJsonNoise")
+}
+
func (s *SettingService) GetSubJsonMux() (string, error) {
return s.getString("subJsonMux")
}
diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml
index 6b232727..290feae4 100644
--- a/web/translation/translate.en_US.toml
+++ b/web/translation/translate.en_US.toml
@@ -312,6 +312,8 @@
"fragment" = "Fragmentation"
"fragmentDesc" = "Enable fragmentation for TLS hello packet."
"fragmentSett" = "Fragmentation Settings"
+"noiseDesc" = "Enable Noise."
+"noiseSett" = "Noise Settings"
"mux" = "Mux"
"muxDesc" = "Transmit multiple independent data streams within an established data stream."
"muxSett" = "Mux Settings"
diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml
index 8fef6dca..adb52271 100644
--- a/web/translation/translate.es_ES.toml
+++ b/web/translation/translate.es_ES.toml
@@ -312,6 +312,8 @@
"fragment" = "Fragmentación"
"fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS"
"fragmentSett" = "Configuración de Fragmentación"
+"noiseDesc" = "Activar Noise."
+"noiseSett" = "Configuración de Noise"
"mux" = "Mux"
"muxDesc" = "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido."
"muxSett" = "Configuración Mux"
diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml
index d967acf6..1258ba41 100644
--- a/web/translation/translate.fa_IR.toml
+++ b/web/translation/translate.fa_IR.toml
@@ -312,6 +312,8 @@
"fragment" = "فرگمنت"
"fragmentDesc" = "فعال کردن فرگمنت برای بستهی نخست تیالاس"
"fragmentSett" = "تنظیمات فرگمنت"
+"noiseDesc" = "فعال کردن Noise."
+"noiseSett" = "تنظیمات Noise"
"mux" = "ماکس"
"muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند"
"muxSett" = "تنظیمات ماکس"
diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml
index 51b84edc..f88610c1 100644
--- a/web/translation/translate.id_ID.toml
+++ b/web/translation/translate.id_ID.toml
@@ -312,6 +312,8 @@
"fragment" = "Fragmentasi"
"fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS"
"fragmentSett" = "Pengaturan Fragmentasi"
+"noiseDesc" = "Aktifkan Noise."
+"noiseSett" = "Pengaturan Noise"
"mux" = "Mux"
"muxDesc" = "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada."
"muxSett" = "Pengaturan Mux"
diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml
index c3606c4e..93d8b3fe 100644
--- a/web/translation/translate.ru_RU.toml
+++ b/web/translation/translate.ru_RU.toml
@@ -312,6 +312,8 @@
"fragment" = "Фрагментация"
"fragmentDesc" = "Включить фрагментацию для пакета приветствия TLS"
"fragmentSett" = "Настройки фрагментации"
+"noiseDesc" = "Включить Noise."
+"noiseSett" = "Настройки Noise"
"mux" = "Mux"
"muxDesc" = "Передача нескольких независимых потоков данных в рамках установленного потока данных."
"muxSett" = "Mux Настройки"
diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml
index 910714a3..7006462f 100644
--- a/web/translation/translate.tr_TR.toml
+++ b/web/translation/translate.tr_TR.toml
@@ -312,6 +312,8 @@
"fragment" = "Parçalama"
"fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir."
"fragmentSett" = "Parçalama Ayarları"
+"noiseDesc" = "Noise'i Etkinleştir."
+"noiseSett" = "Noise Ayarları"
"mux" = "Mux"
"muxDesc" = "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir."
"muxSett" = "Mux Ayarları"
diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml
index a346c099..f15a36bb 100644
--- a/web/translation/translate.uk_UA.toml
+++ b/web/translation/translate.uk_UA.toml
@@ -312,6 +312,8 @@
"fragment" = "Фрагментація"
"fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS"
"fragmentSett" = "Параметри фрагментації"
+"noiseDesc" = "Увімкнути Noise."
+"noiseSett" = "Налаштування Noise"
"mux" = "Mux"
"muxDesc" = "Передавати кілька незалежних потоків даних у межах встановленого потоку даних."
"muxSett" = "Налаштування Mux"
diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml
index 19d90bba..6024fe2b 100644
--- a/web/translation/translate.vi_VN.toml
+++ b/web/translation/translate.vi_VN.toml
@@ -312,6 +312,8 @@
"fragment" = "Sự phân mảnh"
"fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello"
"fragmentSett" = "Cài đặt phân mảnh"
+"noiseDesc" = "Bật Noise."
+"noiseSett" = "Cài đặt Noise"
"mux" = "Mux"
"muxDesc" = "Truyền nhiều luồng dữ liệu độc lập trong luồng dữ liệu đã thiết lập."
"muxSett" = "Mux Cài đặt"
diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml
index 7a28891f..480dec95 100644
--- a/web/translation/translate.zh_CN.toml
+++ b/web/translation/translate.zh_CN.toml
@@ -312,6 +312,8 @@
"fragment" = "分片"
"fragmentDesc" = "启用 TLS hello 数据包分片"
"fragmentSett" = "设置"
+"noiseDesc" = "启用 Noise."
+"noiseSett" = "Noise 设置"
"mux" = "多路复用器"
"muxDesc" = "在已建立的数据流内传输多个独立的数据流"
"muxSett" = "复用器设置"