diff --git a/app/policy/config.go b/app/policy/config.go index 267307b7..836b2324 100644 --- a/app/policy/config.go +++ b/app/policy/config.go @@ -27,6 +27,9 @@ func defaultPolicy() *Policy { Buffer: &Policy_Buffer{ Connection: p.Buffer.PerConnection, }, + Restriction: &Policy_Restriction{ + MaxIPs: p.Restriction.MaxIPs, + }, } } @@ -58,6 +61,11 @@ func (p *Policy) overrideWith(another *Policy) { Connection: another.Buffer.Connection, } } + if another.Restriction != nil { + p.Restriction = &Policy_Restriction{ + MaxIPs: another.Restriction.MaxIPs, + } + } } // ToCorePolicy converts this Policy to policy.Session. @@ -77,6 +85,9 @@ func (p *Policy) ToCorePolicy() policy.Session { if p.Buffer != nil { cp.Buffer.PerConnection = p.Buffer.Connection } + if p.Restriction != nil { + cp.Restriction.MaxIPs = p.Restriction.MaxIPs + } return cp } diff --git a/app/policy/config.pb.go b/app/policy/config.pb.go index fefeb4f1..2cfb48cd 100644 --- a/app/policy/config.pb.go +++ b/app/policy/config.pb.go @@ -72,9 +72,10 @@ type Policy struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timeout *Policy_Timeout `protobuf:"bytes,1,opt,name=timeout,proto3" json:"timeout,omitempty"` - Stats *Policy_Stats `protobuf:"bytes,2,opt,name=stats,proto3" json:"stats,omitempty"` - Buffer *Policy_Buffer `protobuf:"bytes,3,opt,name=buffer,proto3" json:"buffer,omitempty"` + Timeout *Policy_Timeout `protobuf:"bytes,1,opt,name=timeout,proto3" json:"timeout,omitempty"` + Stats *Policy_Stats `protobuf:"bytes,2,opt,name=stats,proto3" json:"stats,omitempty"` + Buffer *Policy_Buffer `protobuf:"bytes,3,opt,name=buffer,proto3" json:"buffer,omitempty"` + Restriction *Policy_Restriction `protobuf:"bytes,4,opt,name=restriction,proto3" json:"restriction,omitempty"` } func (x *Policy) Reset() { @@ -130,6 +131,13 @@ func (x *Policy) GetBuffer() *Policy_Buffer { return nil } +func (x *Policy) GetRestriction() *Policy_Restriction { + if x != nil { + return x.Restriction + } + return nil +} + type SystemPolicy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -407,6 +415,53 @@ func (x *Policy_Buffer) GetConnection() int32 { return 0 } +type Policy_Restriction struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MaxIPs int32 `protobuf:"varint,1,opt,name=maxIPs,proto3" json:"maxIPs,omitempty"` +} + +func (x *Policy_Restriction) Reset() { + *x = Policy_Restriction{} + if protoimpl.UnsafeEnabled { + mi := &file_app_policy_config_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy_Restriction) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy_Restriction) ProtoMessage() {} + +func (x *Policy_Restriction) ProtoReflect() protoreflect.Message { + mi := &file_app_policy_config_proto_msgTypes[7] + 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 Policy_Restriction.ProtoReflect.Descriptor instead. +func (*Policy_Restriction) Descriptor() ([]byte, []int) { + return file_app_policy_config_proto_rawDescGZIP(), []int{1, 3} +} + +func (x *Policy_Restriction) GetMaxIPs() int32 { + if x != nil { + return x.MaxIPs + } + return 0 +} + type SystemPolicy_Stats struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -421,7 +476,7 @@ type SystemPolicy_Stats struct { func (x *SystemPolicy_Stats) Reset() { *x = SystemPolicy_Stats{} if protoimpl.UnsafeEnabled { - mi := &file_app_policy_config_proto_msgTypes[7] + mi := &file_app_policy_config_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -434,7 +489,7 @@ func (x *SystemPolicy_Stats) String() string { func (*SystemPolicy_Stats) ProtoMessage() {} func (x *SystemPolicy_Stats) ProtoReflect() protoreflect.Message { - mi := &file_app_policy_config_proto_msgTypes[7] + mi := &file_app_policy_config_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -485,7 +540,7 @@ var file_app_policy_config_proto_rawDesc = []byte{ 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x1e, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa6, 0x04, 0x0a, 0x06, 0x50, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x94, 0x05, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, @@ -496,65 +551,72 @@ var file_app_policy_config_proto_rawDesc = []byte{ 0x73, 0x74, 0x61, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x42, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x1a, 0xfa, 0x01, - 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x68, 0x61, 0x6e, - 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, - 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x09, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, - 0x12, 0x40, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, - 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x6e, 0x6c, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, - 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, - 0x52, 0x0a, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x3c, 0x0a, 0x0d, - 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, + 0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x45, 0x0a, + 0x0b, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x74, + 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xfa, 0x01, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x12, 0x35, 0x0a, 0x09, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x0c, 0x64, 0x6f, - 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, 0x6e, 0x6c, 0x79, 0x1a, 0x4d, 0x0a, 0x05, 0x53, 0x74, - 0x61, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x6c, 0x69, - 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x55, 0x70, - 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x77, - 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, - 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x1a, 0x28, 0x0a, 0x06, 0x42, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0xfb, 0x01, 0x0a, 0x0c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x1a, - 0xaf, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, - 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, - 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x27, 0x0a, 0x0f, 0x6f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, - 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, - 0x6b, 0x22, 0xcc, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x05, - 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, - 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x1a, 0x51, 0x0a, - 0x0a, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, - 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, - 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, - 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xaa, - 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x09, 0x68, 0x61, + 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x40, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x75, 0x70, 0x6c, + 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x0a, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, + 0x6e, 0x6c, 0x79, 0x12, 0x3c, 0x0a, 0x0d, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, + 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, + 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x52, 0x0c, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, 0x6e, 0x6c, + 0x79, 0x1a, 0x4d, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x75, 0x73, 0x65, 0x72, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, + 0x1a, 0x28, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x25, 0x0a, 0x0b, 0x52, 0x65, + 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, + 0x49, 0x50, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x49, 0x50, + 0x73, 0x22, 0xfb, 0x01, 0x0a, 0x0c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x1a, 0xaf, 0x01, + 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0d, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x29, + 0x0a, 0x10, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, + 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x75, 0x74, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, 0x6c, 0x69, + 0x6e, 0x6b, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x64, + 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6f, + 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x22, + 0xcc, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x05, 0x6c, 0x65, + 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x6c, + 0x65, 0x76, 0x65, 0x6c, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x1a, 0x51, 0x0a, 0x0a, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, + 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x4f, + 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, + 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0xaa, 0x02, 0x0f, + 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -569,7 +631,7 @@ func file_app_policy_config_proto_rawDescGZIP() []byte { return file_app_policy_config_proto_rawDescData } -var file_app_policy_config_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_app_policy_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_app_policy_config_proto_goTypes = []interface{}{ (*Second)(nil), // 0: xray.app.policy.Second (*Policy)(nil), // 1: xray.app.policy.Policy @@ -578,26 +640,28 @@ var file_app_policy_config_proto_goTypes = []interface{}{ (*Policy_Timeout)(nil), // 4: xray.app.policy.Policy.Timeout (*Policy_Stats)(nil), // 5: xray.app.policy.Policy.Stats (*Policy_Buffer)(nil), // 6: xray.app.policy.Policy.Buffer - (*SystemPolicy_Stats)(nil), // 7: xray.app.policy.SystemPolicy.Stats - nil, // 8: xray.app.policy.Config.LevelEntry + (*Policy_Restriction)(nil), // 7: xray.app.policy.Policy.Restriction + (*SystemPolicy_Stats)(nil), // 8: xray.app.policy.SystemPolicy.Stats + nil, // 9: xray.app.policy.Config.LevelEntry } var file_app_policy_config_proto_depIdxs = []int32{ 4, // 0: xray.app.policy.Policy.timeout:type_name -> xray.app.policy.Policy.Timeout 5, // 1: xray.app.policy.Policy.stats:type_name -> xray.app.policy.Policy.Stats 6, // 2: xray.app.policy.Policy.buffer:type_name -> xray.app.policy.Policy.Buffer - 7, // 3: xray.app.policy.SystemPolicy.stats:type_name -> xray.app.policy.SystemPolicy.Stats - 8, // 4: xray.app.policy.Config.level:type_name -> xray.app.policy.Config.LevelEntry - 2, // 5: xray.app.policy.Config.system:type_name -> xray.app.policy.SystemPolicy - 0, // 6: xray.app.policy.Policy.Timeout.handshake:type_name -> xray.app.policy.Second - 0, // 7: xray.app.policy.Policy.Timeout.connection_idle:type_name -> xray.app.policy.Second - 0, // 8: xray.app.policy.Policy.Timeout.uplink_only:type_name -> xray.app.policy.Second - 0, // 9: xray.app.policy.Policy.Timeout.downlink_only:type_name -> xray.app.policy.Second - 1, // 10: xray.app.policy.Config.LevelEntry.value:type_name -> xray.app.policy.Policy - 11, // [11:11] is the sub-list for method output_type - 11, // [11:11] is the sub-list for method input_type - 11, // [11:11] is the sub-list for extension type_name - 11, // [11:11] is the sub-list for extension extendee - 0, // [0:11] is the sub-list for field type_name + 7, // 3: xray.app.policy.Policy.restriction:type_name -> xray.app.policy.Policy.Restriction + 8, // 4: xray.app.policy.SystemPolicy.stats:type_name -> xray.app.policy.SystemPolicy.Stats + 9, // 5: xray.app.policy.Config.level:type_name -> xray.app.policy.Config.LevelEntry + 2, // 6: xray.app.policy.Config.system:type_name -> xray.app.policy.SystemPolicy + 0, // 7: xray.app.policy.Policy.Timeout.handshake:type_name -> xray.app.policy.Second + 0, // 8: xray.app.policy.Policy.Timeout.connection_idle:type_name -> xray.app.policy.Second + 0, // 9: xray.app.policy.Policy.Timeout.uplink_only:type_name -> xray.app.policy.Second + 0, // 10: xray.app.policy.Policy.Timeout.downlink_only:type_name -> xray.app.policy.Second + 1, // 11: xray.app.policy.Config.LevelEntry.value:type_name -> xray.app.policy.Policy + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_app_policy_config_proto_init() } @@ -691,6 +755,18 @@ func file_app_policy_config_proto_init() { } } file_app_policy_config_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Policy_Restriction); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_app_policy_config_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SystemPolicy_Stats); i { case 0: return &v.state @@ -709,7 +785,7 @@ func file_app_policy_config_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_app_policy_config_proto_rawDesc, NumEnums: 0, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 0, }, diff --git a/app/policy/config.proto b/app/policy/config.proto index e5f29547..a0f37f96 100644 --- a/app/policy/config.proto +++ b/app/policy/config.proto @@ -29,9 +29,14 @@ message Policy { int32 connection = 1; } + message Restriction { + int32 maxIPs = 1; + } + Timeout timeout = 1; Stats stats = 2; Buffer buffer = 3; + Restriction restriction = 4; } message SystemPolicy { diff --git a/app/proxyman/inbound/worker.go b/app/proxyman/inbound/worker.go index 1fe86655..199fd4c5 100644 --- a/app/proxyman/inbound/worker.go +++ b/app/proxyman/inbound/worker.go @@ -18,6 +18,7 @@ import ( "github.com/xtls/xray-core/features/stats" "github.com/xtls/xray-core/proxy" "github.com/xtls/xray-core/transport/internet" + "github.com/xtls/xray-core/transport/internet/restriction" "github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/tcp" "github.com/xtls/xray-core/transport/internet/udp" @@ -32,6 +33,8 @@ type worker interface { } type tcpWorker struct { + sync.Mutex + address net.Address port net.Port proxy proxy.Inbound @@ -42,6 +45,7 @@ type tcpWorker struct { sniffingConfig *proxyman.SniffingConfig uplinkCounter stats.Counter downlinkCounter stats.Counter + ipLimitPool map[session.ID]*restriction.UserMaxIp hub internet.Listener @@ -104,9 +108,22 @@ func (w *tcpWorker) callback(conn stat.Connection) { } ctx = session.ContextWithContent(ctx, content) - if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil { + // Add this IP address to the pool for futher IP limit check + w.Lock() + w.ipLimitPool[sid] = &restriction.UserMaxIp{ + IpAddress: net.IP(conn.RemoteAddr().Network()), + } + w.Unlock() + + if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher, &w.ipLimitPool, w.ipLimitPool[sid]); err != nil { newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx)) } + + // Deletes the IP address from the pool after the connection ends + w.Lock() + delete(w.ipLimitPool, sid) + w.Unlock() + cancel() conn.Close() } @@ -116,6 +133,9 @@ func (w *tcpWorker) Proxy() proxy.Inbound { } func (w *tcpWorker) Start() error { + if len(w.ipLimitPool) == 0 { + w.ipLimitPool = make(map[session.ID]*restriction.UserMaxIp) + } ctx := context.Background() hub, err := internet.ListenTCP(ctx, w.address, w.port, w.stream, func(conn stat.Connection) { go w.callback(conn) @@ -244,6 +264,7 @@ type udpWorker struct { sniffingConfig *proxyman.SniffingConfig uplinkCounter stats.Counter downlinkCounter stats.Counter + ipLimitPool map[session.ID]*restriction.UserMaxIp checker *task.Periodic activeConn map[connID]*udpConn @@ -326,9 +347,23 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly } ctx = session.ContextWithContent(ctx, content) - if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil { + + // Add this IP address to the pool for futher IP limit check + w.Lock() + w.ipLimitPool[sid] = &restriction.UserMaxIp{ + IpAddress: net.IP(conn.RemoteAddr().Network()), + } + w.Unlock() + + if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher, &w.ipLimitPool, w.ipLimitPool[sid]); err != nil { newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx)) } + + // Deletes the IP address from the pool after the connection ends + w.Lock() + delete(w.ipLimitPool, sid) + w.Unlock() + conn.Close() // conn not removed by checker TODO may be lock worker here is better if !conn.inactive { @@ -379,6 +414,9 @@ func (w *udpWorker) clean() error { } func (w *udpWorker) Start() error { + if len(w.ipLimitPool) == 0 { + w.ipLimitPool = make(map[session.ID]*restriction.UserMaxIp) + } w.activeConn = make(map[connID]*udpConn, 16) ctx := context.Background() h, err := udp.ListenUDP(ctx, w.address, w.port, w.stream, udp.HubCapacity(256)) @@ -478,7 +516,7 @@ func (w *dsWorker) callback(conn stat.Connection) { } ctx = session.ContextWithContent(ctx, content) - if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil { + if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher, nil, nil); err != nil { newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx)) } cancel() diff --git a/features/policy/policy.go b/features/policy/policy.go index 4d3f7ecf..b71e76c3 100644 --- a/features/policy/policy.go +++ b/features/policy/policy.go @@ -35,6 +35,12 @@ type Buffer struct { PerConnection int32 } +// Buffer contains settings for restriction such as ip restriction. +type Restriction struct { + // Maximum allowed ips, -1 for unlimited + MaxIPs int32 +} + // SystemStats contains stat policy settings on system level. type SystemStats struct { // Whether or not to enable stat counter for uplink traffic in inbound handlers. @@ -55,9 +61,10 @@ type System struct { // Session is session based settings for controlling Xray requests. It contains various settings (or limits) that may differ for different users in the context. type Session struct { - Timeouts Timeout // Timeout settings - Stats Stats - Buffer Buffer + Timeouts Timeout // Timeout settings + Stats Stats + Buffer Buffer + Restriction Restriction } // Manager is a feature that provides Policy for the given user by its id or level. @@ -109,6 +116,12 @@ func defaultBufferPolicy() Buffer { } } +func defaultRestrictionPolicy() Restriction { + return Restriction{ + MaxIPs: -1, + } +} + // SessionDefault returns the Policy when user is not specified. func SessionDefault() Session { return Session{ @@ -124,7 +137,8 @@ func SessionDefault() Session { UserUplink: false, UserDownlink: false, }, - Buffer: defaultBufferPolicy(), + Buffer: defaultBufferPolicy(), + Restriction: defaultRestrictionPolicy(), } } diff --git a/infra/conf/common.go b/infra/conf/common.go index 20868b83..e755b70f 100644 --- a/infra/conf/common.go +++ b/infra/conf/common.go @@ -231,8 +231,8 @@ func (list *PortList) UnmarshalJSON(data []byte) error { } type User struct { - EmailString string `json:"email"` - LevelByte byte `json:"level"` + EmailString string `json:"email"` + LevelByte byte `json:"level"` } func (v *User) Build() *protocol.User { diff --git a/infra/conf/policy.go b/infra/conf/policy.go index 5fbf01e6..74809401 100644 --- a/infra/conf/policy.go +++ b/infra/conf/policy.go @@ -12,6 +12,7 @@ type Policy struct { StatsUserUplink bool `json:"statsUserUplink"` StatsUserDownlink bool `json:"statsUserDownlink"` BufferSize *int32 `json:"bufferSize"` + MaxIPs *int32 `json:"maxIPs"` } func (t *Policy) Build() (*policy.Policy, error) { @@ -47,6 +48,12 @@ func (t *Policy) Build() (*policy.Policy, error) { } } + if t.MaxIPs != nil { + p.Restriction = &policy.Policy_Restriction{ + MaxIPs: (*t.MaxIPs), + } + } + return p, nil } diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index 1c59fe62..269fa62f 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -18,6 +18,7 @@ import ( "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/routing" + "github.com/xtls/xray-core/transport/internet/restriction" "github.com/xtls/xray-core/transport/internet/stat" ) @@ -76,7 +77,7 @@ type hasHandshakeAddressContext interface { } // Process implements proxy.Inbound. -func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error { +func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher, _ *map[session.ID]*restriction.UserMaxIp, _ *restriction.UserMaxIp) error { newError("processing connection from: ", conn.RemoteAddr()).AtDebug().WriteToLog(session.ExportIDToError(ctx)) dest := net.Destination{ Network: network, diff --git a/proxy/proxy.go b/proxy/proxy.go index 6a5a1798..cda79b40 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -28,6 +28,7 @@ import ( "github.com/xtls/xray-core/transport" "github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet/reality" + "github.com/xtls/xray-core/transport/internet/restriction" "github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/tls" ) @@ -62,7 +63,7 @@ type Inbound interface { Network() []net.Network // Process processes a connection of given network. If necessary, the Inbound can dispatch the connection to an Outbound. - Process(context.Context, net.Network, stat.Connection, routing.Dispatcher) error + Process(context.Context, net.Network, stat.Connection, routing.Dispatcher, *map[session.ID]*restriction.UserMaxIp, *restriction.UserMaxIp) error } // An Outbound process outbound connections. diff --git a/proxy/trojan/server.go b/proxy/trojan/server.go index 5c3fcd91..244153cb 100644 --- a/proxy/trojan/server.go +++ b/proxy/trojan/server.go @@ -5,6 +5,7 @@ import ( "io" "strconv" "strings" + "sync" "time" "github.com/xtls/xray-core/common" @@ -22,6 +23,7 @@ import ( "github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/transport/internet/reality" + "github.com/xtls/xray-core/transport/internet/restriction" "github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/udp" @@ -35,6 +37,8 @@ func init() { // Server is an inbound connection handler that handles messages in trojan protocol. type Server struct { + sync.Mutex + policyManager policy.Manager validator *Validator fallbacks map[string]map[string]map[string]*Fallback // or nil @@ -131,7 +135,7 @@ func (s *Server) Network() []net.Network { } // Process implements proxy.Inbound.Process(). -func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error { +func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher, usrIpRstrct *map[session.ID]*restriction.UserMaxIp, connIp *restriction.UserMaxIp) error { sid := session.ExportIDToError(ctx) iConn := conn @@ -219,6 +223,29 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con inbound.User = user sessionPolicy = s.policyManager.ForLevel(user.Level) + if sessionPolicy.Restriction.MaxIPs > 0 { + addr := conn.RemoteAddr().(*net.TCPAddr) + + uniqueIps := make(map[string]bool) + + s.Lock() + // Iterate through the connections and find unique used IP addresses withing last 30 seconds. + for _, conn := range *usrIpRstrct { + if conn.User == user.Email && !conn.IpAddress.Equal(addr.IP) && ((time.Now().Unix() - conn.Time) < 30) { + uniqueIps[conn.IpAddress.String()] = true + } + } + s.Unlock() + + if len(uniqueIps) >= int(sessionPolicy.Restriction.MaxIPs) { + return newError("User ", user, " has exceeded their allowed IPs.").AtWarning() + } + + connIp.IpAddress = addr.IP + connIp.User = user.Email + connIp.Time = time.Now().Unix() + } + if destination.Network == net.Network_UDP { // handle udp request return s.handleUDPPayload(ctx, &PacketReader{Reader: clientReader}, &PacketWriter{Writer: conn}, dispatcher) } diff --git a/proxy/vless/inbound/inbound.go b/proxy/vless/inbound/inbound.go index 0ffa61d2..03d531c0 100644 --- a/proxy/vless/inbound/inbound.go +++ b/proxy/vless/inbound/inbound.go @@ -10,6 +10,7 @@ import ( "reflect" "strconv" "strings" + "sync" "time" "unsafe" @@ -32,6 +33,7 @@ import ( "github.com/xtls/xray-core/proxy/vless" "github.com/xtls/xray-core/proxy/vless/encoding" "github.com/xtls/xray-core/transport/internet/reality" + "github.com/xtls/xray-core/transport/internet/restriction" "github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/tls" ) @@ -51,6 +53,8 @@ func init() { // Handler is an inbound connection handler that handles messages in VLess protocol. type Handler struct { + sync.Mutex + inboundHandlerManager feature_inbound.Manager policyManager policy.Manager validator *vless.Validator @@ -176,7 +180,7 @@ func (*Handler) Network() []net.Network { } // Process implements proxy.Inbound.Process(). -func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error { +func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher, usrIpRstrct *map[session.ID]*restriction.UserMaxIp, connIp *restriction.UserMaxIp) error { sid := session.ExportIDToError(ctx) iConn := connection @@ -184,6 +188,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s iConn = statConn.Connection } + sessionPolicy := h.policyManager.ForLevel(0) if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { return newError("unable to set read deadline").Base(err).AtWarning() @@ -444,6 +449,29 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s // Flow: requestAddons.Flow, } + if sessionPolicy.Restriction.MaxIPs > 0 { + addr := connection.RemoteAddr().(*net.TCPAddr) + + uniqueIps := make(map[string]bool) + + h.Lock() + // Iterate through the connections and find unique used IP addresses withing last 30 seconds. + for _, conn := range *usrIpRstrct { + if conn.User == request.User.Email && !conn.IpAddress.Equal(addr.IP) && ((time.Now().Unix() - conn.Time) < 30) { + uniqueIps[conn.IpAddress.String()] = true + } + } + h.Unlock() + + if len(uniqueIps) >= int(sessionPolicy.Restriction.MaxIPs) { + return newError("User ", request.User.Email, " has exceeded their allowed IPs.").AtWarning() + } + + connIp.IpAddress = addr.IP + connIp.User = request.User.Email + connIp.Time = time.Now().Unix() + } + var input *bytes.Reader var rawInput *bytes.Buffer switch requestAddons.Flow { diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 679ea5da..f6c3bfdd 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -25,6 +25,7 @@ import ( "github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/proxy/vmess" "github.com/xtls/xray-core/proxy/vmess/encoding" + "github.com/xtls/xray-core/transport/internet/restriction" "github.com/xtls/xray-core/transport/internet/stat" ) @@ -97,6 +98,8 @@ func (v *userByEmail) Remove(email string) bool { // Handler is an inbound connection handler that handles messages in VMess protocol. type Handler struct { + sync.Mutex + policyManager policy.Manager inboundHandlerManager feature_inbound.Manager clients *vmess.TimedUserValidator @@ -208,7 +211,7 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess } // Process implements proxy.Inbound.Process(). -func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error { +func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher, usrIpRstrct *map[session.ID]*restriction.UserMaxIp, connIp *restriction.UserMaxIp) error { sessionPolicy := h.policyManager.ForLevel(0) if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { return newError("unable to set read deadline").Base(err).AtWarning() @@ -262,6 +265,28 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s sessionPolicy = h.policyManager.ForLevel(request.User.Level) + if sessionPolicy.Restriction.MaxIPs > 0 { + addr := connection.RemoteAddr().(*net.TCPAddr) + + uniqueIps := make(map[string]bool) + h.Lock() + // Iterate through the connections and find unique used IP addresses withing last 30 seconds. + for _, conn := range *usrIpRstrct { + if conn.User == request.User.Email && !conn.IpAddress.Equal(addr.IP) && ((time.Now().Unix() - conn.Time) < 30) { + uniqueIps[conn.IpAddress.String()] = true + } + } + h.Unlock() + + if len(uniqueIps) >= int(sessionPolicy.Restriction.MaxIPs) { + return newError("User ", request.User.Email, " has exceeded their allowed IPs.").AtWarning() + } + + connIp.IpAddress = addr.IP + connIp.User = request.User.Email + connIp.Time = time.Now().Unix() + } + ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) diff --git a/transport/internet/restriction/ip.go b/transport/internet/restriction/ip.go new file mode 100644 index 00000000..05ff2fa3 --- /dev/null +++ b/transport/internet/restriction/ip.go @@ -0,0 +1,11 @@ +package restriction + +import ( + "net" +) + +type UserMaxIp struct { + User string + IpAddress net.IP + Time int64 +}