From f194c3f3c627bfc7d0a9504d5d8c6c2f99fd0552 Mon Sep 17 00:00:00 2001 From: dragonbreath2000 <168475359+dragonbreath2000@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:34:04 -0700 Subject: [PATCH 1/7] added udp noise --- proxy/freedom/freedom.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 6abcc5530616..a6628d63a448 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -327,6 +327,7 @@ func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride Handler: h, Context: ctx, UDPOverride: UDPOverride, + firstWrite: true, } } return &buf.SequentialWriter{Writer: conn} @@ -338,6 +339,7 @@ type PacketWriter struct { *Handler context.Context UDPOverride net.Destination + firstWrite bool } func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { @@ -369,6 +371,18 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { } n, err = w.PacketConnWrapper.WriteTo(b.Bytes(), destAddr) } else { + if w.firstWrite { + w.firstWrite = false + //Do not send noise for DNS requests + if w.UDPOverride.Port != 53 { + noise, err := GenerateRandomBytes(randBetween(2, 8)) + if err != nil { + return err + } + _, _ = w.PacketConnWrapper.Write(noise) + } + + } n, err = w.PacketConnWrapper.Write(b.Bytes()) } b.Release() @@ -469,3 +483,13 @@ func randBetween(left int64, right int64) int64 { bigInt, _ := rand.Int(rand.Reader, big.NewInt(right-left)) return left + bigInt.Int64() } +func GenerateRandomBytes(n int64) ([]byte, error) { + b := make([]byte, n) + _, err := rand.Read(b) + // Note that err == nil only if we read len(b) bytes. + if err != nil { + return nil, err + } + + return b, nil +} From 458d18481ffe5012e06b7c101a6b007a8e24205c Mon Sep 17 00:00:00 2001 From: dragonbreath2000 <168475359+dragonbreath2000@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:39:01 -0700 Subject: [PATCH 2/7] adding protobuf settings --- proxy/freedom/config.pb.go | 192 +++++++++++++++++++++++++++++-------- proxy/freedom/config.proto | 8 ++ 2 files changed, 161 insertions(+), 39 deletions(-) diff --git a/proxy/freedom/config.pb.go b/proxy/freedom/config.pb.go index 723d4de4f1ce..749b0181a3e0 100644 --- a/proxy/freedom/config.pb.go +++ b/proxy/freedom/config.pb.go @@ -91,7 +91,7 @@ func (x Config_DomainStrategy) Number() protoreflect.EnumNumber { // Deprecated: Use Config_DomainStrategy.Descriptor instead. func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) { - return file_proxy_freedom_config_proto_rawDescGZIP(), []int{2, 0} + return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3, 0} } type DestinationOverride struct { @@ -228,6 +228,85 @@ func (x *Fragment) GetIntervalMax() uint64 { return 0 } +type Noise struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LengthMin uint64 `protobuf:"varint,1,opt,name=length_min,json=lengthMin,proto3" json:"length_min,omitempty"` + LengthMax uint64 `protobuf:"varint,2,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"` + DelayMin uint64 `protobuf:"varint,3,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"` + DelayMax uint64 `protobuf:"varint,4,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"` + StrNoise string `protobuf:"bytes,5,opt,name=str_noise,json=strNoise,proto3" json:"str_noise,omitempty"` +} + +func (x *Noise) Reset() { + *x = Noise{} + if protoimpl.UnsafeEnabled { + mi := &file_proxy_freedom_config_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Noise) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Noise) ProtoMessage() {} + +func (x *Noise) ProtoReflect() protoreflect.Message { + mi := &file_proxy_freedom_config_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Noise.ProtoReflect.Descriptor instead. +func (*Noise) Descriptor() ([]byte, []int) { + return file_proxy_freedom_config_proto_rawDescGZIP(), []int{2} +} + +func (x *Noise) GetLengthMin() uint64 { + if x != nil { + return x.LengthMin + } + return 0 +} + +func (x *Noise) GetLengthMax() uint64 { + if x != nil { + return x.LengthMax + } + return 0 +} + +func (x *Noise) GetDelayMin() uint64 { + if x != nil { + return x.DelayMin + } + return 0 +} + +func (x *Noise) GetDelayMax() uint64 { + if x != nil { + return x.DelayMax + } + return 0 +} + +func (x *Noise) GetStrNoise() string { + if x != nil { + return x.StrNoise + } + return "" +} + type Config struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -240,12 +319,13 @@ type Config struct { UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"` Fragment *Fragment `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"` ProxyProtocol uint32 `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"` + Noise *Noise `protobuf:"bytes,7,opt,name=noise,proto3" json:"noise,omitempty"` } func (x *Config) Reset() { *x = Config{} if protoimpl.UnsafeEnabled { - mi := &file_proxy_freedom_config_proto_msgTypes[2] + mi := &file_proxy_freedom_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -258,7 +338,7 @@ func (x *Config) String() string { func (*Config) ProtoMessage() {} func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_proxy_freedom_config_proto_msgTypes[2] + mi := &file_proxy_freedom_config_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -271,7 +351,7 @@ func (x *Config) ProtoReflect() protoreflect.Message { // Deprecated: Use Config.ProtoReflect.Descriptor instead. func (*Config) Descriptor() ([]byte, []int) { - return file_proxy_freedom_config_proto_rawDescGZIP(), []int{2} + return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3} } func (x *Config) GetDomainStrategy() Config_DomainStrategy { @@ -317,6 +397,13 @@ func (x *Config) GetProxyProtocol() uint32 { return 0 } +func (x *Config) GetNoise() *Noise { + if x != nil { + return x.Noise + } + return nil +} + var File_proxy_freedom_config_proto protoreflect.FileDescriptor var file_proxy_freedom_config_proto_rawDesc = []byte{ @@ -343,29 +430,42 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{ 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x22, 0x82, 0x04, 0x0a, 0x06, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, - 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1c, 0x0a, 0x07, 0x74, 0x69, - 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, - 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, - 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x22, 0x9c, 0x01, 0x0a, 0x05, + 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, + 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, + 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, + 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, + 0x09, 0x73, 0x74, 0x72, 0x5f, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x73, 0x74, 0x72, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x22, 0xb3, 0x04, 0x0a, 0x06, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, + 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, + 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, + 0x64, 0x6f, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1c, 0x0a, 0x07, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x05, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, + 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x05, 0x6e, + 0x6f, 0x69, 0x73, 0x65, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, @@ -398,24 +498,26 @@ func file_proxy_freedom_config_proto_rawDescGZIP() []byte { } var file_proxy_freedom_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proxy_freedom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_proxy_freedom_config_proto_goTypes = []any{ +var file_proxy_freedom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_proxy_freedom_config_proto_goTypes = []interface{}{ (Config_DomainStrategy)(0), // 0: xray.proxy.freedom.Config.DomainStrategy (*DestinationOverride)(nil), // 1: xray.proxy.freedom.DestinationOverride (*Fragment)(nil), // 2: xray.proxy.freedom.Fragment - (*Config)(nil), // 3: xray.proxy.freedom.Config - (*protocol.ServerEndpoint)(nil), // 4: xray.common.protocol.ServerEndpoint + (*Noise)(nil), // 3: xray.proxy.freedom.Noise + (*Config)(nil), // 4: xray.proxy.freedom.Config + (*protocol.ServerEndpoint)(nil), // 5: xray.common.protocol.ServerEndpoint } var file_proxy_freedom_config_proto_depIdxs = []int32{ - 4, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint + 5, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint 0, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.proxy.freedom.Config.DomainStrategy 1, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride 2, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 3, // 4: xray.proxy.freedom.Config.noise:type_name -> xray.proxy.freedom.Noise + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_proxy_freedom_config_proto_init() } @@ -448,7 +550,19 @@ func file_proxy_freedom_config_proto_init() { return nil } } - file_proxy_freedom_config_proto_msgTypes[2].Exporter = func(v any, i int) any { + file_proxy_freedom_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Noise); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proxy_freedom_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Config); i { case 0: return &v.state @@ -467,7 +581,7 @@ func file_proxy_freedom_config_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proxy_freedom_config_proto_rawDesc, NumEnums: 1, - NumMessages: 3, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/proxy/freedom/config.proto b/proxy/freedom/config.proto index 1eabedb7e026..85b71979c1c0 100644 --- a/proxy/freedom/config.proto +++ b/proxy/freedom/config.proto @@ -20,6 +20,13 @@ message Fragment { uint64 interval_min = 5; uint64 interval_max = 6; } +message Noise { + uint64 length_min = 1; + uint64 length_max = 2; + uint64 delay_min = 3; + uint64 delay_max = 4; + string str_noise = 5; +} message Config { enum DomainStrategy { @@ -41,4 +48,5 @@ message Config { uint32 user_level = 4; Fragment fragment = 5; uint32 proxy_protocol = 6; + Noise noise = 7; } From 001dc35d046b291956d779968aa70e37b5c38329 Mon Sep 17 00:00:00 2001 From: dragonbreath2000 <168475359+dragonbreath2000@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:28:41 -0700 Subject: [PATCH 3/7] freedom json parser and clean up --- infra/conf/freedom.go | 76 ++++++++++++++++++++++++ proxy/freedom/freedom.go | 124 ++++++++++++++++++++++++++++++++------- 2 files changed, 178 insertions(+), 22 deletions(-) diff --git a/infra/conf/freedom.go b/infra/conf/freedom.go index d90b7c2d6ee7..e172afa8b00f 100644 --- a/infra/conf/freedom.go +++ b/infra/conf/freedom.go @@ -18,6 +18,7 @@ type FreedomConfig struct { Redirect string `json:"redirect"` UserLevel uint32 `json:"userLevel"` Fragment *Fragment `json:"fragment"` + Noise *Noise `json:"noise"` ProxyProtocol uint32 `json:"proxyProtocol"` } @@ -27,6 +28,11 @@ type Fragment struct { Interval string `json:"interval"` } +type Noise struct { + Packet string `json:"packet"` + Delay string `json:"delay"` +} + // Build implements Buildable func (c *FreedomConfig) Build() (proto.Message, error) { config := new(freedom.Config) @@ -143,6 +149,76 @@ func (c *FreedomConfig) Build() (proto.Message, error) { } } } + if c.Noise != nil { + config.Noise = new(freedom.Noise) + var err, err2 error + p := strings.Split(strings.ToLower(c.Noise.Packet), ":") + if len(p) != 2 { + return nil, errors.New("invalid type for packet") + } + switch p[0] { + case "rand": + randValue := strings.Split(p[1], "-") + if len(randValue) > 2 { + return nil, errors.New("Only 2 values are allowed for rand") + } + if len(randValue) == 2 { + config.Noise.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64) + config.Noise.LengthMax, err2 = strconv.ParseUint(randValue[1], 10, 64) + } + if len(randValue) == 1 { + config.Noise.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64) + config.Noise.LengthMax = config.Noise.LengthMin + } + if err != nil { + return nil, errors.New("invalid value for rand LengthMin").Base(err) + } + if err2 != nil { + return nil, errors.New("invalid value for rand LengthMax").Base(err2) + } + if config.Noise.LengthMin > config.Noise.LengthMax { + config.Noise.LengthMin, config.Noise.LengthMax = config.Noise.LengthMax, config.Noise.LengthMin + } + if config.Noise.LengthMin == 0 { + return nil, errors.New("rand lengthMin or lengthMax cannot be 0") + } + + case "str": + //user input string + config.Noise.StrNoise = strings.TrimSpace(p[1]) + + default: + return nil, errors.New("Invalid packet,only rand and str are supported") + } + if c.Noise.Delay != "" { + d := strings.Split(strings.ToLower(c.Noise.Delay), "-") + if len(d) > 2 { + return nil, errors.New("Invalid delay value") + } + if len(d) == 2 { + config.Noise.DelayMin, err = strconv.ParseUint(d[0], 10, 64) + config.Noise.DelayMax, err2 = strconv.ParseUint(d[1], 10, 64) + + } else { + config.Noise.DelayMin, err = strconv.ParseUint(d[0], 10, 64) + config.Noise.DelayMax = config.Noise.DelayMin + } + if err != nil { + return nil, errors.New("Invalid value for DelayMin").Base(err) + } + if err2 != nil { + return nil, errors.New("Invalid value for DelayMax").Base(err2) + } + if config.Noise.DelayMin > config.Noise.DelayMax { + config.Noise.DelayMin, config.Noise.DelayMax = config.Noise.DelayMax, config.Noise.DelayMin + } + if config.Noise.DelayMin == 0 { + return nil, errors.New("DelayMin or DelayMax cannot be 0") + } + } else { + config.Noise.DelayMin = 0 + } + } if c.Timeout != nil { config.Timeout = *c.Timeout diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index a6628d63a448..1fd4453c1dcb 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -207,7 +207,13 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte writer = buf.NewWriter(conn) } } else { - writer = NewPacketWriter(conn, h, ctx, UDPOverride) + if h.config.Noise != nil { + errors.LogDebug(ctx, "NOISE", h.config.Noise.StrNoise, h.config.Noise.LengthMin, h.config.Noise.LengthMax, + h.config.Noise.DelayMin, h.config.Noise.DelayMax) + writer = NewPacketWriter(conn, h, ctx, UDPOverride, true) + } else { + writer = NewPacketWriter(conn, h, ctx, UDPOverride, false) + } } if err := buf.Copy(input, writer, buf.UpdateActivity(timer)); err != nil { @@ -310,7 +316,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { return buf.MultiBuffer{b}, nil } -func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination) buf.Writer { +func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination, hasNoise bool) buf.Writer { iConn := conn statConn, ok := iConn.(*stat.CounterConnection) if ok { @@ -321,13 +327,24 @@ func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride counter = statConn.WriteCounter } if c, ok := iConn.(*internet.PacketConnWrapper); ok { - return &PacketWriter{ - PacketConnWrapper: c, - Counter: counter, - Handler: h, - Context: ctx, - UDPOverride: UDPOverride, - firstWrite: true, + if hasNoise { + return &NoisePacketWriter{ + Writer: PacketWriter{ + PacketConnWrapper: c, + Handler: h, + Context: ctx, + UDPOverride: UDPOverride, + }, + firstWrite: hasNoise, + } + } else { + return &PacketWriter{ + PacketConnWrapper: c, + Counter: counter, + Handler: h, + Context: ctx, + UDPOverride: UDPOverride, + } } } return &buf.SequentialWriter{Writer: conn} @@ -339,7 +356,6 @@ type PacketWriter struct { *Handler context.Context UDPOverride net.Destination - firstWrite bool } func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { @@ -371,18 +387,6 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { } n, err = w.PacketConnWrapper.WriteTo(b.Bytes(), destAddr) } else { - if w.firstWrite { - w.firstWrite = false - //Do not send noise for DNS requests - if w.UDPOverride.Port != 53 { - noise, err := GenerateRandomBytes(randBetween(2, 8)) - if err != nil { - return err - } - _, _ = w.PacketConnWrapper.Write(noise) - } - - } n, err = w.PacketConnWrapper.Write(b.Bytes()) } b.Release() @@ -397,6 +401,82 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { return nil } +type NoisePacketWriter struct { + Writer PacketWriter + firstWrite bool +} + +// MultiBuffer writer with Noise in first packet +func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { + if w.firstWrite { + w.firstWrite = false + //Do not send noise for DNS requests just to be safe + if w.Writer.UDPOverride.Port != 53 { + var noise []byte + var err error + //User input string + if w.Writer.config.Noise.StrNoise != "" { + noise = []byte(w.Writer.config.Noise.StrNoise) + } else { + //Random noise + noise, err = GenerateRandomBytes(randBetween(int64(w.Writer.config.Noise.LengthMin), + int64(w.Writer.config.Noise.LengthMax))) + } + + if err != nil { + return err + } + _, _ = w.Writer.PacketConnWrapper.Write(noise) + + if w.Writer.config.Noise.DelayMin != 0 { + time.Sleep(time.Duration(randBetween(int64(w.Writer.config.Noise.DelayMin), int64(w.Writer.config.Noise.DelayMax))) * time.Millisecond) + } + } + + } + for { + mb2, b := buf.SplitFirst(mb) + mb = mb2 + if b == nil { + break + } + var n int + var err error + if b.UDP != nil { + if w.Writer.UDPOverride.Address != nil { + b.UDP.Address = w.Writer.UDPOverride.Address + } + if w.Writer.UDPOverride.Port != 0 { + b.UDP.Port = w.Writer.UDPOverride.Port + } + if w.Writer.Handler.config.hasStrategy() && b.UDP.Address.Family().IsDomain() { + ip := w.Writer.Handler.resolveIP(w.Writer.Context, b.UDP.Address.Domain(), nil) + if ip != nil { + b.UDP.Address = ip + } + } + destAddr, _ := net.ResolveUDPAddr("udp", b.UDP.NetAddr()) + if destAddr == nil { + b.Release() + continue + } + n, err = w.Writer.PacketConnWrapper.WriteTo(b.Bytes(), destAddr) + } else { + + n, err = w.Writer.PacketConnWrapper.Write(b.Bytes()) + } + b.Release() + if err != nil { + buf.ReleaseMulti(mb) + return err + } + if w.Writer.Counter != nil { + w.Writer.Counter.Add(int64(n)) + } + } + return nil +} + type FragmentWriter struct { fragment *Fragment writer io.Writer From f467c794d57abea7e343cf2f489cb9fee93abade Mon Sep 17 00:00:00 2001 From: dragonbreath2000 <168475359+dragonbreath2000@users.noreply.github.com> Date: Thu, 22 Aug 2024 18:57:58 -0700 Subject: [PATCH 4/7] resolve confict --- proxy/freedom/config.pb.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proxy/freedom/config.pb.go b/proxy/freedom/config.pb.go index 749b0181a3e0..9d8292515533 100644 --- a/proxy/freedom/config.pb.go +++ b/proxy/freedom/config.pb.go @@ -499,7 +499,7 @@ func file_proxy_freedom_config_proto_rawDescGZIP() []byte { var file_proxy_freedom_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_proxy_freedom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_proxy_freedom_config_proto_goTypes = []interface{}{ +var file_proxy_freedom_config_proto_goTypes = []any{ (Config_DomainStrategy)(0), // 0: xray.proxy.freedom.Config.DomainStrategy (*DestinationOverride)(nil), // 1: xray.proxy.freedom.DestinationOverride (*Fragment)(nil), // 2: xray.proxy.freedom.Fragment @@ -550,7 +550,7 @@ func file_proxy_freedom_config_proto_init() { return nil } } - file_proxy_freedom_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_proxy_freedom_config_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*Noise); i { case 0: return &v.state @@ -562,7 +562,7 @@ func file_proxy_freedom_config_proto_init() { return nil } } - file_proxy_freedom_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_proxy_freedom_config_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*Config); i { case 0: return &v.state From 879528e63178bd1e2c1e2904af379d2990fe05dd Mon Sep 17 00:00:00 2001 From: dragonbreath2000 <168475359+dragonbreath2000@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:43:03 -0700 Subject: [PATCH 5/7] fix and clean up --- proxy/freedom/freedom.go | 104 ++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 61 deletions(-) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 1fd4453c1dcb..fcdc1e8ed8a0 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -210,9 +210,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte if h.config.Noise != nil { errors.LogDebug(ctx, "NOISE", h.config.Noise.StrNoise, h.config.Noise.LengthMin, h.config.Noise.LengthMax, h.config.Noise.DelayMin, h.config.Noise.DelayMax) - writer = NewPacketWriter(conn, h, ctx, UDPOverride, true) + writer = NewNoisePacketWriter(conn, h, ctx, UDPOverride, h.config.Noise) + } else { - writer = NewPacketWriter(conn, h, ctx, UDPOverride, false) + writer = NewPacketWriter(conn, h, ctx, UDPOverride) } } @@ -316,7 +317,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { return buf.MultiBuffer{b}, nil } -func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination, hasNoise bool) buf.Writer { +func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination) buf.Writer { iConn := conn statConn, ok := iConn.(*stat.CounterConnection) if ok { @@ -327,25 +328,41 @@ func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride counter = statConn.WriteCounter } if c, ok := iConn.(*internet.PacketConnWrapper); ok { - if hasNoise { - return &NoisePacketWriter{ - Writer: PacketWriter{ - PacketConnWrapper: c, - Handler: h, - Context: ctx, - UDPOverride: UDPOverride, - }, - firstWrite: hasNoise, - } - } else { - return &PacketWriter{ + return &PacketWriter{ + PacketConnWrapper: c, + Counter: counter, + Handler: h, + Context: ctx, + UDPOverride: UDPOverride, + } + + } + return &buf.SequentialWriter{Writer: conn} +} + +func NewNoisePacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination, noise *Noise) buf.Writer { + iConn := conn + statConn, ok := iConn.(*stat.CounterConnection) + if ok { + iConn = statConn.Connection + } + var counter stats.Counter + if statConn != nil { + counter = statConn.WriteCounter + } + if c, ok := iConn.(*internet.PacketConnWrapper); ok { + return &NoisePacketWriter{ + Writer: PacketWriter{ PacketConnWrapper: c, Counter: counter, Handler: h, Context: ctx, UDPOverride: UDPOverride, - } + }, + firstWrite: true, + noise: noise, } + } return &buf.SequentialWriter{Writer: conn} } @@ -402,6 +419,7 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { } type NoisePacketWriter struct { + noise *Noise Writer PacketWriter firstWrite bool } @@ -415,12 +433,12 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { var noise []byte var err error //User input string - if w.Writer.config.Noise.StrNoise != "" { - noise = []byte(w.Writer.config.Noise.StrNoise) + if w.noise.StrNoise != "" { + noise = []byte(w.noise.StrNoise) } else { //Random noise - noise, err = GenerateRandomBytes(randBetween(int64(w.Writer.config.Noise.LengthMin), - int64(w.Writer.config.Noise.LengthMax))) + noise, err = GenerateRandomBytes(randBetween(int64(w.noise.LengthMin), + int64(w.noise.LengthMax))) } if err != nil { @@ -428,51 +446,15 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { } _, _ = w.Writer.PacketConnWrapper.Write(noise) - if w.Writer.config.Noise.DelayMin != 0 { - time.Sleep(time.Duration(randBetween(int64(w.Writer.config.Noise.DelayMin), int64(w.Writer.config.Noise.DelayMax))) * time.Millisecond) + if w.noise.DelayMin != 0 { + time.Sleep(time.Duration(randBetween(int64(w.noise.DelayMin), int64(w.noise.DelayMax))) * time.Millisecond) } } } - for { - mb2, b := buf.SplitFirst(mb) - mb = mb2 - if b == nil { - break - } - var n int - var err error - if b.UDP != nil { - if w.Writer.UDPOverride.Address != nil { - b.UDP.Address = w.Writer.UDPOverride.Address - } - if w.Writer.UDPOverride.Port != 0 { - b.UDP.Port = w.Writer.UDPOverride.Port - } - if w.Writer.Handler.config.hasStrategy() && b.UDP.Address.Family().IsDomain() { - ip := w.Writer.Handler.resolveIP(w.Writer.Context, b.UDP.Address.Domain(), nil) - if ip != nil { - b.UDP.Address = ip - } - } - destAddr, _ := net.ResolveUDPAddr("udp", b.UDP.NetAddr()) - if destAddr == nil { - b.Release() - continue - } - n, err = w.Writer.PacketConnWrapper.WriteTo(b.Bytes(), destAddr) - } else { - - n, err = w.Writer.PacketConnWrapper.Write(b.Bytes()) - } - b.Release() - if err != nil { - buf.ReleaseMulti(mb) - return err - } - if w.Writer.Counter != nil { - w.Writer.Counter.Add(int64(n)) - } + err := w.Writer.WriteMultiBuffer(mb) + if err != nil { + return err } return nil } From 87664d0c43f45f417a8a7168bc427b6e4482183a Mon Sep 17 00:00:00 2001 From: dragonbreath2000 <168475359+dragonbreath2000@users.noreply.github.com> Date: Sun, 25 Aug 2024 19:53:55 -0700 Subject: [PATCH 6/7] use net.conn instead of packetconnwrapper --- proxy/freedom/freedom.go | 88 +++++++++++++++------------------------- 1 file changed, 33 insertions(+), 55 deletions(-) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index fcdc1e8ed8a0..566d70824f75 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -210,7 +210,14 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte if h.config.Noise != nil { errors.LogDebug(ctx, "NOISE", h.config.Noise.StrNoise, h.config.Noise.LengthMin, h.config.Noise.LengthMax, h.config.Noise.DelayMin, h.config.Noise.DelayMax) - writer = NewNoisePacketWriter(conn, h, ctx, UDPOverride, h.config.Noise) + writer = &NoisePacketWriter{ + Writer: buf.SequentialWriter{ + Writer: conn, + }, + noise: h.config.Noise, + firstWrite: true, + UDPOverride: UDPOverride, + } } else { writer = NewPacketWriter(conn, h, ctx, UDPOverride) @@ -340,33 +347,6 @@ func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride return &buf.SequentialWriter{Writer: conn} } -func NewNoisePacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination, noise *Noise) buf.Writer { - iConn := conn - statConn, ok := iConn.(*stat.CounterConnection) - if ok { - iConn = statConn.Connection - } - var counter stats.Counter - if statConn != nil { - counter = statConn.WriteCounter - } - if c, ok := iConn.(*internet.PacketConnWrapper); ok { - return &NoisePacketWriter{ - Writer: PacketWriter{ - PacketConnWrapper: c, - Counter: counter, - Handler: h, - Context: ctx, - UDPOverride: UDPOverride, - }, - firstWrite: true, - noise: noise, - } - - } - return &buf.SequentialWriter{Writer: conn} -} - type PacketWriter struct { *internet.PacketConnWrapper stats.Counter @@ -419,44 +399,42 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { } type NoisePacketWriter struct { - noise *Noise - Writer PacketWriter - firstWrite bool + noise *Noise + Writer buf.SequentialWriter + firstWrite bool + UDPOverride net.Destination } // MultiBuffer writer with Noise in first packet func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { if w.firstWrite { w.firstWrite = false - //Do not send noise for DNS requests just to be safe - if w.Writer.UDPOverride.Port != 53 { - var noise []byte - var err error - //User input string - if w.noise.StrNoise != "" { - noise = []byte(w.noise.StrNoise) - } else { - //Random noise - noise, err = GenerateRandomBytes(randBetween(int64(w.noise.LengthMin), - int64(w.noise.LengthMax))) - } + //Do not send Noise for dns requests(just to be safe) + if w.UDPOverride.Port == 53 { + return w.Writer.WriteMultiBuffer(mb) + } + var noise []byte + var err error + //User input string + if w.noise.StrNoise != "" { + noise = []byte(w.noise.StrNoise) + } else { + //Random noise + noise, err = GenerateRandomBytes(randBetween(int64(w.noise.LengthMin), + int64(w.noise.LengthMax))) + } - if err != nil { - return err - } - _, _ = w.Writer.PacketConnWrapper.Write(noise) + if err != nil { + return err + } + _, _ = w.Writer.Write(noise) - if w.noise.DelayMin != 0 { - time.Sleep(time.Duration(randBetween(int64(w.noise.DelayMin), int64(w.noise.DelayMax))) * time.Millisecond) - } + if w.noise.DelayMin != 0 { + time.Sleep(time.Duration(randBetween(int64(w.noise.DelayMin), int64(w.noise.DelayMax))) * time.Millisecond) } } - err := w.Writer.WriteMultiBuffer(mb) - if err != nil { - return err - } - return nil + return w.Writer.WriteMultiBuffer(mb) } type FragmentWriter struct { From 41812278d3e8cf42026c944b8bac4878798439e9 Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Tue, 27 Aug 2024 21:58:43 -0500 Subject: [PATCH 7/7] avoid constructing SequentialWriter directly --- proxy/freedom/freedom.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 92c1af93f344..c387d1580117 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -207,20 +207,16 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte writer = buf.NewWriter(conn) } } else { + writer = NewPacketWriter(conn, h, ctx, UDPOverride) if h.config.Noise != nil { errors.LogDebug(ctx, "NOISE", h.config.Noise.StrNoise, h.config.Noise.LengthMin, h.config.Noise.LengthMax, h.config.Noise.DelayMin, h.config.Noise.DelayMax) writer = &NoisePacketWriter{ - Writer: buf.SequentialWriter{ - Writer: conn, - }, + Writer: writer, noise: h.config.Noise, firstWrite: true, UDPOverride: UDPOverride, } - - } else { - writer = NewPacketWriter(conn, h, ctx, UDPOverride) } } @@ -401,8 +397,8 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { } type NoisePacketWriter struct { + buf.Writer noise *Noise - Writer buf.SequentialWriter firstWrite bool UDPOverride net.Destination } @@ -429,7 +425,7 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { if err != nil { return err } - _, _ = w.Writer.Write(noise) + w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)}) if w.noise.DelayMin != 0 { time.Sleep(time.Duration(randBetween(int64(w.noise.DelayMin), int64(w.noise.DelayMax))) * time.Millisecond)