mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-23 01:56:48 +08:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b33555cc0a | ||
![]() |
38cc306c95 | ||
![]() |
373558ed7a | ||
![]() |
84835bec7d | ||
![]() |
49580705f6 | ||
![]() |
d1fb485212 | ||
![]() |
bfe4820f2f | ||
![]() |
2807ee432a | ||
![]() |
7f778a4e2f | ||
![]() |
09cc92c61d | ||
![]() |
0fd7691d6b | ||
![]() |
1720be168f | ||
![]() |
3c20bddfcf | ||
![]() |
23d7aad461 | ||
![]() |
5c61142048 | ||
![]() |
ec1cc35188 | ||
![]() |
7ffb555fc8 | ||
![]() |
2e6a88307c | ||
![]() |
3e19bf9233 | ||
![]() |
fc137d2612 | ||
![]() |
f61c14e9c6 | ||
![]() |
0cceea75da | ||
![]() |
4b21c9aed3 | ||
![]() |
cde6e33ec9 | ||
![]() |
5dce7e4e25 | ||
![]() |
9359844149 | ||
![]() |
8222f43eea | ||
![]() |
04e6439b51 |
@@ -91,6 +91,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
|||||||
}
|
}
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
||||||
|
Local: net.DestinationFromAddr(conn.LocalAddr()),
|
||||||
Gateway: net.TCPDestination(w.address, w.port),
|
Gateway: net.TCPDestination(w.address, w.port),
|
||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
@@ -321,8 +322,10 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||||||
outbounds[0].Target = originalDest
|
outbounds[0].Target = originalDest
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||||
|
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
Source: source,
|
Source: source,
|
||||||
|
Local: net.DestinationFromAddr(w.hub.Addr()),
|
||||||
Gateway: net.UDPDestination(w.address, w.port),
|
Gateway: net.UDPDestination(w.address, w.port),
|
||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
})
|
})
|
||||||
@@ -472,6 +475,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
|
|||||||
}
|
}
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
||||||
|
Local: net.DestinationFromAddr(conn.LocalAddr()),
|
||||||
Gateway: net.UnixDestination(w.address),
|
Gateway: net.UnixDestination(w.address),
|
||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
|
@@ -42,6 +42,8 @@ type RoutingContext struct {
|
|||||||
Attributes map[string]string `protobuf:"bytes,10,rep,name=Attributes,proto3" json:"Attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
Attributes map[string]string `protobuf:"bytes,10,rep,name=Attributes,proto3" json:"Attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"`
|
OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"`
|
||||||
OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,omitempty"`
|
OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,omitempty"`
|
||||||
|
LocalIPs [][]byte `protobuf:"bytes,13,rep,name=LocalIPs,proto3" json:"LocalIPs,omitempty"`
|
||||||
|
LocalPort uint32 `protobuf:"varint,14,opt,name=LocalPort,proto3" json:"LocalPort,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingContext) Reset() {
|
func (x *RoutingContext) Reset() {
|
||||||
@@ -158,6 +160,20 @@ func (x *RoutingContext) GetOutboundTag() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *RoutingContext) GetLocalIPs() [][]byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.LocalIPs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RoutingContext) GetLocalPort() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.LocalPort
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
||||||
// opened by xray-core.
|
// opened by xray-core.
|
||||||
// * FieldSelectors selects a subset of fields in routing statistics to return.
|
// * FieldSelectors selects a subset of fields in routing statistics to return.
|
||||||
@@ -827,7 +843,7 @@ var file_app_router_command_command_proto_rawDesc = []byte{
|
|||||||
0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e,
|
0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65,
|
||||||
0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||||
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9c, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
||||||
0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x49,
|
0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x49,
|
||||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x0a, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x32, 0x0a, 0x07, 0x4e,
|
0x0a, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x32, 0x0a, 0x07, 0x4e,
|
||||||
@@ -857,123 +873,127 @@ var file_app_router_command_command_proto_rawDesc = []byte{
|
|||||||
0x03, 0x28, 0x09, 0x52, 0x11, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x47, 0x72, 0x6f,
|
0x03, 0x28, 0x09, 0x52, 0x11, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x47, 0x72, 0x6f,
|
||||||
0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
||||||
0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x75, 0x74,
|
0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x75, 0x74,
|
||||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72,
|
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
||||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
0x6c, 0x49, 0x50, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
||||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
0x6c, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72,
|
||||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f,
|
||||||
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63,
|
0x72, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||||
0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73,
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||||
0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22,
|
0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f,
|
||||||
0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71,
|
0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43,
|
0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
|
||||||
0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78,
|
0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63,
|
0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65,
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f,
|
||||||
0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
|
||||||
0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46,
|
|
||||||
0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a,
|
|
||||||
0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03,
|
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73,
|
|
||||||
0x75, 0x6c, 0x74, 0x22, 0x27, 0x0a, 0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65,
|
|
||||||
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61,
|
|
||||||
0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c,
|
|
||||||
0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06,
|
|
||||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61,
|
|
||||||
0x72, 0x67, 0x65, 0x74, 0x22, 0xa9, 0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
|
||||||
0x72, 0x4d, 0x73, 0x67, 0x12, 0x41, 0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
|
||||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
||||||
0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f,
|
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52,
|
||||||
0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63,
|
0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12,
|
||||||
0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28,
|
0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72,
|
||||||
0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65,
|
||||||
0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e,
|
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69,
|
||||||
0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d,
|
||||||
0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x27, 0x0a,
|
||||||
0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
|
0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||||
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61,
|
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||||
0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x5b, 0x0a, 0x17,
|
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
|
||||||
0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xa9,
|
||||||
0x63, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x41,
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x61, 0x6e, 0x64, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52,
|
0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65,
|
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||||
0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72,
|
0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||||
0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61,
|
0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74,
|
||||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72,
|
||||||
0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06,
|
|
||||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61,
|
|
||||||
0x72, 0x67, 0x65, 0x74, 0x22, 0x20, 0x0a, 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
|
||||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65,
|
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6e, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c,
|
|
||||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66,
|
|
||||||
0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79,
|
|
||||||
0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66,
|
|
||||||
0x69, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65,
|
|
||||||
0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
|
|
||||||
0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c,
|
|
||||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x11, 0x52, 0x65, 0x6d,
|
|
||||||
0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18,
|
|
||||||
0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
|
||||||
0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f,
|
|
||||||
0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08,
|
|
||||||
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xbf, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
|
||||||
0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x15, 0x53,
|
|
||||||
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53,
|
|
||||||
0x74, 0x61, 0x74, 0x73, 0x12, 0x35, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
|
||||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53,
|
|
||||||
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53,
|
|
||||||
0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
|
||||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54,
|
||||||
0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74,
|
0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63,
|
||||||
0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65,
|
||||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
|
||||||
0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x5b, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c,
|
||||||
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69,
|
|
||||||
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0f, 0x47,
|
|
||||||
0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f,
|
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61,
|
|
||||||
0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
|
||||||
0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
|
||||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c,
|
|
||||||
0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
0x65, 0x22, 0x00, 0x12, 0x8b, 0x01, 0x0a, 0x16, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x01, 0x20,
|
||||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36,
|
0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||||
|
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x42, 0x61,
|
||||||
|
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
||||||
|
0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42,
|
||||||
|
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
|
||||||
|
0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
||||||
|
0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x20,
|
||||||
|
0x0a, 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||||
|
0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
|
0x22, 0x6e, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
|
0x73, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
|
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73,
|
||||||
|
0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0c,
|
||||||
|
0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01,
|
||||||
|
0x28, 0x08, 0x52, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64,
|
||||||
|
0x22, 0x11, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
|
0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c,
|
||||||
|
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65,
|
||||||
|
0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54,
|
||||||
|
0x61, 0x67, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65,
|
||||||
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||||
|
0x69, 0x67, 0x32, 0xbf, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65,
|
||||||
|
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
||||||
|
0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x35,
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
||||||
0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52,
|
0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
|
||||||
0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
|
||||||
0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
|
||||||
0x00, 0x12, 0x5e, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63,
|
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65,
|
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
|
||||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
||||||
0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00,
|
||||||
0x00, 0x12, 0x67, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12,
|
0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12,
|
||||||
0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f,
|
||||||
0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x72,
|
0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
|
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65,
|
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f,
|
0x65, 0x78, 0x74, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61,
|
||||||
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74,
|
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e,
|
||||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||||
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
|
||||||
0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8b, 0x01,
|
||||||
|
0x0a, 0x16, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||||
|
0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
|
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||||
|
0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||||
|
0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
|
0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
|
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||||
|
0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65,
|
||||||
|
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x07, 0x41,
|
||||||
|
0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
|
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
||||||
|
0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
|
0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||||
|
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c,
|
||||||
|
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x0a, 0x52,
|
||||||
|
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||||
|
0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||||
|
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
||||||
|
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
|
0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||||
|
0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2c, 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, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
|
||||||
|
0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52,
|
||||||
|
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -25,6 +25,8 @@ message RoutingContext {
|
|||||||
map<string, string> Attributes = 10;
|
map<string, string> Attributes = 10;
|
||||||
repeated string OutboundGroupTags = 11;
|
repeated string OutboundGroupTags = 11;
|
||||||
string OutboundTag = 12;
|
string OutboundTag = 12;
|
||||||
|
repeated bytes LocalIPs = 13;
|
||||||
|
uint32 LocalPort = 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
||||||
|
@@ -28,6 +28,14 @@ func (c routingContext) GetTargetPort() net.Port {
|
|||||||
return net.Port(c.RoutingContext.GetTargetPort())
|
return net.Port(c.RoutingContext.GetTargetPort())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c routingContext) GetLocalIPs() []net.IP {
|
||||||
|
return mapBytesToIPs(c.RoutingContext.GetLocalIPs())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c routingContext) GetLocalPort() net.Port {
|
||||||
|
return net.Port(c.RoutingContext.GetLocalPort())
|
||||||
|
}
|
||||||
|
|
||||||
func (c routingContext) GetRuleTag() string {
|
func (c routingContext) GetRuleTag() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -54,8 +62,10 @@ var fieldMap = map[string]func(*RoutingContext, routing.Route){
|
|||||||
"network": func(s *RoutingContext, r routing.Route) { s.Network = r.GetNetwork() },
|
"network": func(s *RoutingContext, r routing.Route) { s.Network = r.GetNetwork() },
|
||||||
"ip_source": func(s *RoutingContext, r routing.Route) { s.SourceIPs = mapIPsToBytes(r.GetSourceIPs()) },
|
"ip_source": func(s *RoutingContext, r routing.Route) { s.SourceIPs = mapIPsToBytes(r.GetSourceIPs()) },
|
||||||
"ip_target": func(s *RoutingContext, r routing.Route) { s.TargetIPs = mapIPsToBytes(r.GetTargetIPs()) },
|
"ip_target": func(s *RoutingContext, r routing.Route) { s.TargetIPs = mapIPsToBytes(r.GetTargetIPs()) },
|
||||||
|
"ip_local": func(s *RoutingContext, r routing.Route) { s.LocalIPs = mapIPsToBytes(r.GetLocalIPs()) },
|
||||||
"port_source": func(s *RoutingContext, r routing.Route) { s.SourcePort = uint32(r.GetSourcePort()) },
|
"port_source": func(s *RoutingContext, r routing.Route) { s.SourcePort = uint32(r.GetSourcePort()) },
|
||||||
"port_target": func(s *RoutingContext, r routing.Route) { s.TargetPort = uint32(r.GetTargetPort()) },
|
"port_target": func(s *RoutingContext, r routing.Route) { s.TargetPort = uint32(r.GetTargetPort()) },
|
||||||
|
"port_local": func(s *RoutingContext, r routing.Route) { s.LocalPort = uint32(r.GetLocalPort()) },
|
||||||
"domain": func(s *RoutingContext, r routing.Route) { s.TargetDomain = r.GetTargetDomain() },
|
"domain": func(s *RoutingContext, r routing.Route) { s.TargetDomain = r.GetTargetDomain() },
|
||||||
"protocol": func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
|
"protocol": func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
|
||||||
"user": func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
|
"user": func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
|
||||||
|
@@ -113,10 +113,10 @@ func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
|||||||
|
|
||||||
type MultiGeoIPMatcher struct {
|
type MultiGeoIPMatcher struct {
|
||||||
matchers []*GeoIPMatcher
|
matchers []*GeoIPMatcher
|
||||||
onSource bool
|
asType string // local, source, target
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
func NewMultiGeoIPMatcher(geoips []*GeoIP, asType string) (*MultiGeoIPMatcher, error) {
|
||||||
var matchers []*GeoIPMatcher
|
var matchers []*GeoIPMatcher
|
||||||
for _, geoip := range geoips {
|
for _, geoip := range geoips {
|
||||||
matcher, err := GlobalGeoIPContainer.Add(geoip)
|
matcher, err := GlobalGeoIPContainer.Add(geoip)
|
||||||
@@ -128,7 +128,7 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, e
|
|||||||
|
|
||||||
matcher := &MultiGeoIPMatcher{
|
matcher := &MultiGeoIPMatcher{
|
||||||
matchers: matchers,
|
matchers: matchers,
|
||||||
onSource: onSource,
|
asType: asType,
|
||||||
}
|
}
|
||||||
|
|
||||||
return matcher, nil
|
return matcher, nil
|
||||||
@@ -137,11 +137,18 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, e
|
|||||||
// Apply implements Condition.
|
// Apply implements Condition.
|
||||||
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
||||||
var ips []net.IP
|
var ips []net.IP
|
||||||
if m.onSource {
|
|
||||||
|
switch m.asType {
|
||||||
|
case "local":
|
||||||
|
ips = ctx.GetLocalIPs()
|
||||||
|
case "source":
|
||||||
ips = ctx.GetSourceIPs()
|
ips = ctx.GetSourceIPs()
|
||||||
} else {
|
case "target":
|
||||||
ips = ctx.GetTargetIPs()
|
ips = ctx.GetTargetIPs()
|
||||||
|
default:
|
||||||
|
panic("unreachable, asType should be local or source or target")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
for _, matcher := range m.matchers {
|
for _, matcher := range m.matchers {
|
||||||
if matcher.Match(ip) {
|
if matcher.Match(ip) {
|
||||||
@@ -154,24 +161,30 @@ func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
|||||||
|
|
||||||
type PortMatcher struct {
|
type PortMatcher struct {
|
||||||
port net.MemoryPortList
|
port net.MemoryPortList
|
||||||
onSource bool
|
asType string // local, source, target
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPortMatcher create a new port matcher that can match source or destination port
|
// NewPortMatcher create a new port matcher that can match source or local or destination port
|
||||||
func NewPortMatcher(list *net.PortList, onSource bool) *PortMatcher {
|
func NewPortMatcher(list *net.PortList, asType string) *PortMatcher {
|
||||||
return &PortMatcher{
|
return &PortMatcher{
|
||||||
port: net.PortListFromProto(list),
|
port: net.PortListFromProto(list),
|
||||||
onSource: onSource,
|
asType: asType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply implements Condition.
|
// Apply implements Condition.
|
||||||
func (v *PortMatcher) Apply(ctx routing.Context) bool {
|
func (v *PortMatcher) Apply(ctx routing.Context) bool {
|
||||||
if v.onSource {
|
switch v.asType {
|
||||||
|
case "local":
|
||||||
|
return v.port.Contains(ctx.GetLocalPort())
|
||||||
|
case "source":
|
||||||
return v.port.Contains(ctx.GetSourcePort())
|
return v.port.Contains(ctx.GetSourcePort())
|
||||||
} else {
|
case "target":
|
||||||
return v.port.Contains(ctx.GetTargetPort())
|
return v.port.Contains(ctx.GetTargetPort())
|
||||||
|
default:
|
||||||
|
panic("unreachable, asType should be local or source or target")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetworkMatcher struct {
|
type NetworkMatcher struct {
|
||||||
|
@@ -495,7 +495,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher, err := NewMultiGeoIPMatcher(geoips, false)
|
matcher, err := NewMultiGeoIPMatcher(geoips, "target")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
||||||
|
@@ -61,11 +61,15 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rr.PortList != nil {
|
if rr.PortList != nil {
|
||||||
conds.Add(NewPortMatcher(rr.PortList, false))
|
conds.Add(NewPortMatcher(rr.PortList, "target"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if rr.SourcePortList != nil {
|
if rr.SourcePortList != nil {
|
||||||
conds.Add(NewPortMatcher(rr.SourcePortList, true))
|
conds.Add(NewPortMatcher(rr.SourcePortList, "source"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.LocalPortList != nil {
|
||||||
|
conds.Add(NewPortMatcher(rr.LocalPortList, "local"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Networks) > 0 {
|
if len(rr.Networks) > 0 {
|
||||||
@@ -73,7 +77,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Geoip) > 0 {
|
if len(rr.Geoip) > 0 {
|
||||||
cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
|
cond, err := NewMultiGeoIPMatcher(rr.Geoip, "target")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -81,13 +85,22 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.SourceGeoip) > 0 {
|
if len(rr.SourceGeoip) > 0 {
|
||||||
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
|
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, "source")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conds.Add(cond)
|
conds.Add(cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(rr.LocalGeoip) > 0 {
|
||||||
|
cond, err := NewMultiGeoIPMatcher(rr.LocalGeoip, "local")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conds.Add(cond)
|
||||||
|
errors.LogWarning(context.Background(), "Due to some limitations, in UDP connections, localIP is always equal to listen interface IP, so \"localIP\" rule condition does not work properly on UDP inbound connections that listen on all interfaces")
|
||||||
|
}
|
||||||
|
|
||||||
if len(rr.Protocol) > 0 {
|
if len(rr.Protocol) > 0 {
|
||||||
conds.Add(NewProtocolMatcher(rr.Protocol))
|
conds.Add(NewProtocolMatcher(rr.Protocol))
|
||||||
}
|
}
|
||||||
|
@@ -470,7 +470,7 @@ type RoutingRule struct {
|
|||||||
// *RoutingRule_Tag
|
// *RoutingRule_Tag
|
||||||
// *RoutingRule_BalancingTag
|
// *RoutingRule_BalancingTag
|
||||||
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
||||||
RuleTag string `protobuf:"bytes,18,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
|
RuleTag string `protobuf:"bytes,20,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
|
||||||
// List of domains for target domain matching.
|
// List of domains for target domain matching.
|
||||||
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
||||||
// List of GeoIPs for target IP address matching. If this entry exists, the
|
// List of GeoIPs for target IP address matching. If this entry exists, the
|
||||||
@@ -492,6 +492,8 @@ type RoutingRule struct {
|
|||||||
Protocol []string `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
|
Protocol []string `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
|
||||||
Attributes map[string]string `protobuf:"bytes,15,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
Attributes map[string]string `protobuf:"bytes,15,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
DomainMatcher string `protobuf:"bytes,17,opt,name=domain_matcher,json=domainMatcher,proto3" json:"domain_matcher,omitempty"`
|
DomainMatcher string `protobuf:"bytes,17,opt,name=domain_matcher,json=domainMatcher,proto3" json:"domain_matcher,omitempty"`
|
||||||
|
LocalGeoip []*GeoIP `protobuf:"bytes,18,rep,name=local_geoip,json=localGeoip,proto3" json:"local_geoip,omitempty"`
|
||||||
|
LocalPortList *net.PortList `protobuf:"bytes,19,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) Reset() {
|
func (x *RoutingRule) Reset() {
|
||||||
@@ -629,6 +631,20 @@ func (x *RoutingRule) GetDomainMatcher() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *RoutingRule) GetLocalGeoip() []*GeoIP {
|
||||||
|
if x != nil {
|
||||||
|
return x.LocalGeoip
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RoutingRule) GetLocalPortList() *net.PortList {
|
||||||
|
if x != nil {
|
||||||
|
return x.LocalPortList
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type isRoutingRule_TargetTag interface {
|
type isRoutingRule_TargetTag interface {
|
||||||
isRoutingRule_TargetTag()
|
isRoutingRule_TargetTag()
|
||||||
}
|
}
|
||||||
@@ -1069,13 +1085,13 @@ var file_app_router_config_proto_rawDesc = []byte{
|
|||||||
0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74,
|
0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74,
|
||||||
0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69,
|
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69,
|
||||||
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xce, 0x05, 0x0a, 0x0b, 0x52, 0x6f,
|
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xca, 0x06, 0x0a, 0x0b, 0x52, 0x6f,
|
||||||
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67,
|
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a,
|
||||||
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c,
|
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e,
|
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e,
|
||||||
0x67, 0x54, 0x61, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x67,
|
0x67, 0x54, 0x61, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x67,
|
||||||
0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x12,
|
0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x12,
|
||||||
0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||||
0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||||
0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
@@ -1109,67 +1125,75 @@ var file_app_router_config_proto_rawDesc = []byte{
|
|||||||
0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72,
|
0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72,
|
||||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x3d, 0x0a,
|
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x37, 0x0a,
|
||||||
0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x12, 0x20, 0x03,
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||||
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
|
||||||
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a,
|
0x6c, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x41, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f,
|
||||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42,
|
0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03,
|
0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
||||||
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b,
|
0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61,
|
||||||
0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
|
0x6c, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74,
|
||||||
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
|
||||||
0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73,
|
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
|
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74,
|
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67,
|
||||||
0x65, 0x67, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
|
0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
||||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75,
|
||||||
0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65,
|
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18,
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53,
|
||||||
0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61,
|
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||||
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72,
|
0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72,
|
0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f,
|
||||||
0x65, 0x67, 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67,
|
0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
|
||||||
0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72,
|
||||||
0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||||
0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
|
0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73,
|
0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74,
|
||||||
0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63,
|
0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
||||||
0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61,
|
0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72,
|
0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78,
|
||||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73,
|
0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12,
|
||||||
0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18,
|
0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73,
|
0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03,
|
||||||
0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01,
|
0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17,
|
||||||
0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06,
|
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61,
|
||||||
0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61,
|
0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73,
|
||||||
0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63,
|
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e,
|
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x63, 0x65, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a,
|
0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c,
|
||||||
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08,
|
||||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
|
||||||
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e,
|
0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30,
|
0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54,
|
||||||
0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78,
|
0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52,
|
0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x9b,
|
||||||
0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d,
|
||||||
0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75,
|
0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
|
||||||
0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61,
|
||||||
0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75,
|
||||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49,
|
0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10,
|
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69,
|
||||||
0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02,
|
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e,
|
||||||
0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03,
|
0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03,
|
||||||
0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75,
|
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67,
|
||||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52,
|
||||||
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa,
|
0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
|
||||||
0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12,
|
||||||
0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70,
|
||||||
|
0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a,
|
||||||
|
0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13,
|
||||||
|
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||||
|
0x74, 0x65, 0x72, 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, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72,
|
||||||
|
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1220,16 +1244,18 @@ var file_app_router_config_proto_depIdxs = []int32{
|
|||||||
4, // 10: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
|
4, // 10: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
|
||||||
15, // 11: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
|
15, // 11: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
|
||||||
14, // 12: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
|
14, // 12: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
|
||||||
17, // 13: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
4, // 13: xray.app.router.RoutingRule.local_geoip:type_name -> xray.app.router.GeoIP
|
||||||
10, // 14: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
15, // 14: xray.app.router.RoutingRule.local_port_list:type_name -> xray.common.net.PortList
|
||||||
1, // 15: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
17, // 15: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
8, // 16: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
10, // 16: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
||||||
9, // 17: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
1, // 17: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
||||||
18, // [18:18] is the sub-list for method output_type
|
8, // 18: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
||||||
18, // [18:18] is the sub-list for method input_type
|
9, // 19: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
||||||
18, // [18:18] is the sub-list for extension type_name
|
20, // [20:20] is the sub-list for method output_type
|
||||||
18, // [18:18] is the sub-list for extension extendee
|
20, // [20:20] is the sub-list for method input_type
|
||||||
0, // [0:18] is the sub-list for field type_name
|
20, // [20:20] is the sub-list for extension type_name
|
||||||
|
20, // [20:20] is the sub-list for extension extendee
|
||||||
|
0, // [0:20] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_router_config_proto_init() }
|
func init() { file_app_router_config_proto_init() }
|
||||||
|
@@ -79,7 +79,7 @@ message RoutingRule {
|
|||||||
// Tag of routing balancer.
|
// Tag of routing balancer.
|
||||||
string balancing_tag = 12;
|
string balancing_tag = 12;
|
||||||
}
|
}
|
||||||
string rule_tag = 18;
|
string rule_tag = 20;
|
||||||
|
|
||||||
// List of domains for target domain matching.
|
// List of domains for target domain matching.
|
||||||
repeated Domain domain = 2;
|
repeated Domain domain = 2;
|
||||||
@@ -110,6 +110,9 @@ message RoutingRule {
|
|||||||
map<string, string> attributes = 15;
|
map<string, string> attributes = 15;
|
||||||
|
|
||||||
string domain_matcher = 17;
|
string domain_matcher = 17;
|
||||||
|
|
||||||
|
repeated GeoIP local_geoip = 18;
|
||||||
|
xray.common.net.PortList local_port_list = 19;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BalancingRule {
|
message BalancingRule {
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
// OnlineMap is an implementation of stats.OnlineMap.
|
// OnlineMap is an implementation of stats.OnlineMap.
|
||||||
type OnlineMap struct {
|
type OnlineMap struct {
|
||||||
value int
|
|
||||||
ipList map[string]time.Time
|
ipList map[string]time.Time
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
lastCleanup time.Time
|
lastCleanup time.Time
|
||||||
@@ -25,7 +24,10 @@ func NewOnlineMap() *OnlineMap {
|
|||||||
|
|
||||||
// Count implements stats.OnlineMap.
|
// Count implements stats.OnlineMap.
|
||||||
func (c *OnlineMap) Count() int {
|
func (c *OnlineMap) Count() int {
|
||||||
return c.value
|
c.access.RLock()
|
||||||
|
defer c.access.RUnlock()
|
||||||
|
|
||||||
|
return len(c.ipList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List implements stats.OnlineMap.
|
// List implements stats.OnlineMap.
|
||||||
@@ -35,23 +37,18 @@ func (c *OnlineMap) List() []string {
|
|||||||
|
|
||||||
// AddIP implements stats.OnlineMap.
|
// AddIP implements stats.OnlineMap.
|
||||||
func (c *OnlineMap) AddIP(ip string) {
|
func (c *OnlineMap) AddIP(ip string) {
|
||||||
list := c.ipList
|
|
||||||
|
|
||||||
if ip == "127.0.0.1" {
|
if ip == "127.0.0.1" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.access.Lock()
|
c.access.Lock()
|
||||||
if _, ok := list[ip]; !ok {
|
c.ipList[ip] = time.Now()
|
||||||
list[ip] = time.Now()
|
|
||||||
}
|
|
||||||
c.access.Unlock()
|
c.access.Unlock()
|
||||||
|
|
||||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||||
list = c.RemoveExpiredIPs(list)
|
c.RemoveExpiredIPs()
|
||||||
c.lastCleanup = time.Now()
|
c.lastCleanup = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
c.value = len(list)
|
|
||||||
c.ipList = list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OnlineMap) GetKeys() []string {
|
func (c *OnlineMap) GetKeys() []string {
|
||||||
@@ -65,24 +62,22 @@ func (c *OnlineMap) GetKeys() []string {
|
|||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.Time {
|
func (c *OnlineMap) RemoveExpiredIPs() {
|
||||||
c.access.Lock()
|
c.access.Lock()
|
||||||
defer c.access.Unlock()
|
defer c.access.Unlock()
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for k, t := range list {
|
for k, t := range c.ipList {
|
||||||
diff := now.Sub(t)
|
diff := now.Sub(t)
|
||||||
if diff.Seconds() > 20 {
|
if diff.Seconds() > 20 {
|
||||||
delete(list, k)
|
delete(c.ipList, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
|
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
|
||||||
list := c.ipList
|
|
||||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||||
list = c.RemoveExpiredIPs(list)
|
c.RemoveExpiredIPs()
|
||||||
c.lastCleanup = time.Now()
|
c.lastCleanup = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -79,20 +79,18 @@ type CommandSwitchAccount struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
|
// Keep in sync with crypto/tls/cipher_suites.go.
|
||||||
|
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3
|
||||||
hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
|
hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
|
||||||
// Keep in sync with crypto/aes/cipher_s390x.go.
|
hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCTR && cpu.S390X.HasGHASH
|
||||||
hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR &&
|
hasGCMAsmPPC64 = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"
|
||||||
(cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
|
|
||||||
|
|
||||||
hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 ||
|
HasAESGCMHardwareSupport = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X || hasGCMAsmPPC64
|
||||||
runtime.GOARCH == "arm64" && hasGCMAsmARM64 ||
|
|
||||||
runtime.GOARCH == "s390x" && hasGCMAsmS390X
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sc *SecurityConfig) GetSecurityType() SecurityType {
|
func (sc *SecurityConfig) GetSecurityType() SecurityType {
|
||||||
if sc == nil || sc.Type == SecurityType_AUTO {
|
if sc == nil || sc.Type == SecurityType_AUTO {
|
||||||
if hasAESGCMHardwareSupport {
|
if HasAESGCMHardwareSupport {
|
||||||
return SecurityType_AES128_GCM
|
return SecurityType_AES128_GCM
|
||||||
}
|
}
|
||||||
return SecurityType_CHACHA20_POLY1305
|
return SecurityType_CHACHA20_POLY1305
|
||||||
|
@@ -36,6 +36,8 @@ func ExportIDToError(ctx context.Context) errors.ExportOption {
|
|||||||
type Inbound struct {
|
type Inbound struct {
|
||||||
// Source address of the inbound connection.
|
// Source address of the inbound connection.
|
||||||
Source net.Destination
|
Source net.Destination
|
||||||
|
// Local address of the inbound connection.
|
||||||
|
Local net.Destination
|
||||||
// Gateway address.
|
// Gateway address.
|
||||||
Gateway net.Destination
|
Gateway net.Destination
|
||||||
// Tag of the inbound proxy that handles the connection.
|
// Tag of the inbound proxy that handles the connection.
|
||||||
|
@@ -23,6 +23,12 @@ type Context interface {
|
|||||||
// GetTargetPort returns the target port of the connection.
|
// GetTargetPort returns the target port of the connection.
|
||||||
GetTargetPort() net.Port
|
GetTargetPort() net.Port
|
||||||
|
|
||||||
|
// GetLocalIPs returns the local IPs bound to the connection.
|
||||||
|
GetLocalIPs() []net.IP
|
||||||
|
|
||||||
|
// GetLocalPort returns the local port of the connection.
|
||||||
|
GetLocalPort() net.Port
|
||||||
|
|
||||||
// GetTargetDomain returns the target domain of the connection, if exists.
|
// GetTargetDomain returns the target domain of the connection, if exists.
|
||||||
GetTargetDomain() string
|
GetTargetDomain() string
|
||||||
|
|
||||||
|
@@ -28,12 +28,13 @@ func (ctx *Context) GetSourceIPs() []net.IP {
|
|||||||
if ctx.Inbound == nil || !ctx.Inbound.Source.IsValid() {
|
if ctx.Inbound == nil || !ctx.Inbound.Source.IsValid() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
dest := ctx.Inbound.Source
|
|
||||||
if dest.Address.Family().IsDomain() {
|
if ctx.Inbound.Source.Address.Family().IsIP() {
|
||||||
return nil
|
return []net.IP{ctx.Inbound.Source.Address.IP()}
|
||||||
}
|
}
|
||||||
|
|
||||||
return []net.IP{dest.Address.IP()}
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSourcePort implements routing.Context.
|
// GetSourcePort implements routing.Context.
|
||||||
@@ -65,6 +66,27 @@ func (ctx *Context) GetTargetPort() net.Port {
|
|||||||
return ctx.Outbound.Target.Port
|
return ctx.Outbound.Target.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLocalIPs implements routing.Context.
|
||||||
|
func (ctx *Context) GetLocalIPs() []net.IP {
|
||||||
|
if ctx.Inbound == nil || !ctx.Inbound.Local.IsValid() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.Inbound.Local.Address.Family().IsIP() {
|
||||||
|
return []net.IP{ctx.Inbound.Local.Address.IP()}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocalPort implements routing.Context.
|
||||||
|
func (ctx *Context) GetLocalPort() net.Port {
|
||||||
|
if ctx.Inbound == nil || !ctx.Inbound.Local.IsValid() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return ctx.Inbound.Local.Port
|
||||||
|
}
|
||||||
|
|
||||||
// GetTargetDomain implements routing.Context.
|
// GetTargetDomain implements routing.Context.
|
||||||
func (ctx *Context) GetTargetDomain() string {
|
func (ctx *Context) GetTargetDomain() string {
|
||||||
if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
|
if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
|
||||||
|
16
go.mod
16
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/golang/mock v1.7.0-rc.1
|
github.com/golang/mock v1.7.0-rc.1
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/miekg/dns v1.1.67
|
github.com/miekg/dns v1.1.68
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/pires/go-proxyproto v0.8.1
|
github.com/pires/go-proxyproto v0.8.1
|
||||||
github.com/quic-go/quic-go v0.54.0
|
github.com/quic-go/quic-go v0.54.0
|
||||||
@@ -21,13 +21,13 @@ require (
|
|||||||
github.com/vishvananda/netlink v1.3.1
|
github.com/vishvananda/netlink v1.3.1
|
||||||
github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7
|
github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.40.0
|
golang.org/x/crypto v0.41.0
|
||||||
golang.org/x/net v0.42.0
|
golang.org/x/net v0.43.0
|
||||||
golang.org/x/sync v0.16.0
|
golang.org/x/sync v0.16.0
|
||||||
golang.org/x/sys v0.34.0
|
golang.org/x/sys v0.35.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||||
google.golang.org/grpc v1.74.2
|
google.golang.org/grpc v1.74.2
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.7
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
||||||
h12.io/socks v1.0.3
|
h12.io/socks v1.0.3
|
||||||
lukechampine.com/blake3 v1.4.1
|
lukechampine.com/blake3 v1.4.1
|
||||||
@@ -47,10 +47,10 @@ require (
|
|||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
github.com/vishvananda/netns v0.0.5 // indirect
|
github.com/vishvananda/netns v0.0.5 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
golang.org/x/mod v0.25.0 // indirect
|
golang.org/x/mod v0.26.0 // indirect
|
||||||
golang.org/x/text v0.27.0 // indirect
|
golang.org/x/text v0.28.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.34.0 // indirect
|
golang.org/x/tools v0.35.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
32
go.sum
32
go.sum
@@ -38,8 +38,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/miekg/dns v1.1.67 h1:kg0EHj0G4bfT5/oOys6HhZw4vmMlnoZ+gDu8tJ/AlI0=
|
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||||
github.com/miekg/dns v1.1.67/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
||||||
@@ -96,16 +96,16 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
|||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
@@ -117,21 +117,21 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -143,8 +143,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:
|
|||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
@@ -27,12 +27,14 @@ type Fragment struct {
|
|||||||
Packets string `json:"packets"`
|
Packets string `json:"packets"`
|
||||||
Length *Int32Range `json:"length"`
|
Length *Int32Range `json:"length"`
|
||||||
Interval *Int32Range `json:"interval"`
|
Interval *Int32Range `json:"interval"`
|
||||||
|
MaxSplit *Int32Range `json:"maxSplit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Noise struct {
|
type Noise struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Packet string `json:"packet"`
|
Packet string `json:"packet"`
|
||||||
Delay *Int32Range `json:"delay"`
|
Delay *Int32Range `json:"delay"`
|
||||||
|
ApplyTo string `json:"applyTo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable
|
// Build implements Buildable
|
||||||
@@ -108,6 +110,13 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
|
|||||||
config.Fragment.IntervalMin = uint64(c.Fragment.Interval.From)
|
config.Fragment.IntervalMin = uint64(c.Fragment.Interval.From)
|
||||||
config.Fragment.IntervalMax = uint64(c.Fragment.Interval.To)
|
config.Fragment.IntervalMax = uint64(c.Fragment.Interval.To)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if c.Fragment.MaxSplit != nil {
|
||||||
|
config.Fragment.MaxSplitMin = uint64(c.Fragment.MaxSplit.From)
|
||||||
|
config.Fragment.MaxSplitMax = uint64(c.Fragment.MaxSplit.To)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Noise != nil {
|
if c.Noise != nil {
|
||||||
@@ -193,5 +202,15 @@ func ParseNoise(noise *Noise) (*freedom.Noise, error) {
|
|||||||
NConfig.DelayMin = uint64(noise.Delay.From)
|
NConfig.DelayMin = uint64(noise.Delay.From)
|
||||||
NConfig.DelayMax = uint64(noise.Delay.To)
|
NConfig.DelayMax = uint64(noise.Delay.To)
|
||||||
}
|
}
|
||||||
|
switch strings.ToLower(noise.ApplyTo) {
|
||||||
|
case "", "ip", "all":
|
||||||
|
NConfig.ApplyTo = "ip"
|
||||||
|
case "ipv4":
|
||||||
|
NConfig.ApplyTo = "ipv4"
|
||||||
|
case "ipv6":
|
||||||
|
NConfig.ApplyTo = "ipv6"
|
||||||
|
default:
|
||||||
|
return nil, errors.New("Invalid applyTo, only ip/ipv4/ipv6 are supported")
|
||||||
|
}
|
||||||
return NConfig, nil
|
return NConfig, nil
|
||||||
}
|
}
|
||||||
|
@@ -536,12 +536,15 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
IP *StringList `json:"ip"`
|
IP *StringList `json:"ip"`
|
||||||
Port *PortList `json:"port"`
|
Port *PortList `json:"port"`
|
||||||
Network *NetworkList `json:"network"`
|
Network *NetworkList `json:"network"`
|
||||||
SourceIP *StringList `json:"source"`
|
SourceIP *StringList `json:"sourceIP"`
|
||||||
|
Source *StringList `json:"source"`
|
||||||
SourcePort *PortList `json:"sourcePort"`
|
SourcePort *PortList `json:"sourcePort"`
|
||||||
User *StringList `json:"user"`
|
User *StringList `json:"user"`
|
||||||
InboundTag *StringList `json:"inboundTag"`
|
InboundTag *StringList `json:"inboundTag"`
|
||||||
Protocols *StringList `json:"protocol"`
|
Protocols *StringList `json:"protocol"`
|
||||||
Attributes map[string]string `json:"attrs"`
|
Attributes map[string]string `json:"attrs"`
|
||||||
|
LocalIP *StringList `json:"localIP"`
|
||||||
|
LocalPort *PortList `json:"localPort"`
|
||||||
}
|
}
|
||||||
rawFieldRule := new(RawFieldRule)
|
rawFieldRule := new(RawFieldRule)
|
||||||
err := json.Unmarshal(msg, rawFieldRule)
|
err := json.Unmarshal(msg, rawFieldRule)
|
||||||
@@ -604,6 +607,10 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
rule.Networks = rawFieldRule.Network.Build()
|
rule.Networks = rawFieldRule.Network.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rawFieldRule.SourceIP == nil {
|
||||||
|
rawFieldRule.SourceIP = rawFieldRule.Source
|
||||||
|
}
|
||||||
|
|
||||||
if rawFieldRule.SourceIP != nil {
|
if rawFieldRule.SourceIP != nil {
|
||||||
geoipList, err := ToCidrList(*rawFieldRule.SourceIP)
|
geoipList, err := ToCidrList(*rawFieldRule.SourceIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -616,6 +623,18 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
rule.SourcePortList = rawFieldRule.SourcePort.Build()
|
rule.SourcePortList = rawFieldRule.SourcePort.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rawFieldRule.LocalIP != nil {
|
||||||
|
geoipList, err := ToCidrList(*rawFieldRule.LocalIP)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rule.LocalGeoip = geoipList
|
||||||
|
}
|
||||||
|
|
||||||
|
if rawFieldRule.LocalPort != nil {
|
||||||
|
rule.LocalPortList = rawFieldRule.LocalPort.Build()
|
||||||
|
}
|
||||||
|
|
||||||
if rawFieldRule.User != nil {
|
if rawFieldRule.User != nil {
|
||||||
for _, s := range *rawFieldRule.User {
|
for _, s := range *rawFieldRule.User {
|
||||||
rule.UserEmail = append(rule.UserEmail, s)
|
rule.UserEmail = append(rule.UserEmail, s)
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package conf
|
package conf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -68,10 +69,46 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
config.Clients[idx] = user
|
config.Clients[idx] = user
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Decryption != "none" {
|
config.Decryption = c.Decryption
|
||||||
|
if !func() bool {
|
||||||
|
s := strings.Split(config.Decryption, ".")
|
||||||
|
if len(s) != 5 || s[2] != "mlkem768Seed" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s[0] != "1rtt" {
|
||||||
|
t := strings.TrimSuffix(s[0], "min")
|
||||||
|
if t == s[0] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
i, err := strconv.Atoi(t)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
config.Minutes = uint32(i)
|
||||||
|
}
|
||||||
|
switch s[1] {
|
||||||
|
case "native":
|
||||||
|
case "divide":
|
||||||
|
config.XorMode = 1
|
||||||
|
case "random":
|
||||||
|
config.XorMode = 2
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b, _ := base64.RawURLEncoding.DecodeString(s[3]); len(b) != 32 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b, _ := base64.RawURLEncoding.DecodeString(s[4]); len(b) != 64 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
config.Decryption = s[4] + "." + s[3]
|
||||||
|
return true
|
||||||
|
}() && config.Decryption != "none" {
|
||||||
|
if config.Decryption == "" {
|
||||||
return nil, errors.New(`VLESS settings: please add/set "decryption":"none" to every settings`)
|
return nil, errors.New(`VLESS settings: please add/set "decryption":"none" to every settings`)
|
||||||
}
|
}
|
||||||
config.Decryption = c.Decryption
|
return nil, errors.New(`VLESS settings: unsupported "decryption": ` + config.Decryption)
|
||||||
|
}
|
||||||
|
|
||||||
for _, fb := range c.Fallbacks {
|
for _, fb := range c.Fallbacks {
|
||||||
var i uint16
|
var i uint16
|
||||||
@@ -143,16 +180,16 @@ type VLessOutboundConfig struct {
|
|||||||
func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
||||||
config := new(outbound.Config)
|
config := new(outbound.Config)
|
||||||
|
|
||||||
if len(c.Vnext) == 0 {
|
if len(c.Vnext) != 1 {
|
||||||
return nil, errors.New(`VLESS settings: "vnext" is empty`)
|
return nil, errors.New(`VLESS settings: "vnext" should have one and only one member`)
|
||||||
}
|
}
|
||||||
config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext))
|
config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext))
|
||||||
for idx, rec := range c.Vnext {
|
for idx, rec := range c.Vnext {
|
||||||
if rec.Address == nil {
|
if rec.Address == nil {
|
||||||
return nil, errors.New(`VLESS vnext: "address" is not set`)
|
return nil, errors.New(`VLESS vnext: "address" is not set`)
|
||||||
}
|
}
|
||||||
if len(rec.Users) == 0 {
|
if len(rec.Users) != 1 {
|
||||||
return nil, errors.New(`VLESS vnext: "users" is empty`)
|
return nil, errors.New(`VLESS vnext: "users" should have one and only one member`)
|
||||||
}
|
}
|
||||||
spec := &protocol.ServerEndpoint{
|
spec := &protocol.ServerEndpoint{
|
||||||
Address: rec.Address.Build(),
|
Address: rec.Address.Build(),
|
||||||
@@ -181,9 +218,45 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
|||||||
return nil, errors.New(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`)
|
return nil, errors.New(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if account.Encryption != "none" {
|
if !func() bool {
|
||||||
|
s := strings.Split(account.Encryption, ".")
|
||||||
|
if len(s) != 5 || s[2] != "mlkem768Client" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if s[0] != "1rtt" {
|
||||||
|
t := strings.TrimSuffix(s[0], "min")
|
||||||
|
if t == s[0] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
i, err := strconv.Atoi(t)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
account.Minutes = uint32(i)
|
||||||
|
}
|
||||||
|
switch s[1] {
|
||||||
|
case "native":
|
||||||
|
case "divide":
|
||||||
|
account.XorMode = 1
|
||||||
|
case "random":
|
||||||
|
account.XorMode = 2
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b, _ := base64.RawURLEncoding.DecodeString(s[3]); len(b) != 32 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if b, _ := base64.RawURLEncoding.DecodeString(s[4]); len(b) != 1184 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
account.Encryption = s[4] + "." + s[3]
|
||||||
|
return true
|
||||||
|
}() && account.Encryption != "none" {
|
||||||
|
if account.Encryption == "" {
|
||||||
return nil, errors.New(`VLESS users: please add/set "encryption":"none" for every user`)
|
return nil, errors.New(`VLESS users: please add/set "encryption":"none" for every user`)
|
||||||
}
|
}
|
||||||
|
return nil, errors.New(`VLESS users: unsupported "encryption": ` + account.Encryption)
|
||||||
|
}
|
||||||
|
|
||||||
user.Account = serial.ToTypedMessage(account)
|
user.Account = serial.ToTypedMessage(account)
|
||||||
spec.User[idx] = user
|
spec.User[idx] = user
|
||||||
|
@@ -17,5 +17,6 @@ func init() {
|
|||||||
cmdX25519,
|
cmdX25519,
|
||||||
cmdWG,
|
cmdWG,
|
||||||
cmdMLDSA65,
|
cmdMLDSA65,
|
||||||
|
cmdMLKEM768,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,13 @@
|
|||||||
package all
|
package all
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdh"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Curve25519Genkey(StdEncoding bool, input_base64 string) {
|
func Curve25519Genkey(StdEncoding bool, input_base64 string) {
|
||||||
var output string
|
|
||||||
var err error
|
|
||||||
var privateKey, publicKey []byte
|
|
||||||
var encoding *base64.Encoding
|
var encoding *base64.Encoding
|
||||||
if *input_stdEncoding || StdEncoding {
|
if *input_stdEncoding || StdEncoding {
|
||||||
encoding = base64.StdEncoding
|
encoding = base64.StdEncoding
|
||||||
@@ -19,40 +15,32 @@ func Curve25519Genkey(StdEncoding bool, input_base64 string) {
|
|||||||
encoding = base64.RawURLEncoding
|
encoding = base64.RawURLEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var privateKey []byte
|
||||||
if len(input_base64) > 0 {
|
if len(input_base64) > 0 {
|
||||||
privateKey, err = encoding.DecodeString(input_base64)
|
privateKey, _ = encoding.DecodeString(input_base64)
|
||||||
if err != nil {
|
if len(privateKey) != 32 {
|
||||||
output = err.Error()
|
fmt.Println("Invalid length of X25519 private key.")
|
||||||
goto out
|
return
|
||||||
}
|
|
||||||
if len(privateKey) != curve25519.ScalarSize {
|
|
||||||
output = "Invalid length of private key."
|
|
||||||
goto out
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if privateKey == nil {
|
if privateKey == nil {
|
||||||
privateKey = make([]byte, curve25519.ScalarSize)
|
privateKey = make([]byte, 32)
|
||||||
if _, err = rand.Read(privateKey); err != nil {
|
rand.Read(privateKey)
|
||||||
output = err.Error()
|
|
||||||
goto out
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify random bytes using algorithm described at:
|
// Modify random bytes using algorithm described at:
|
||||||
// https://cr.yp.to/ecdh.html.
|
// https://cr.yp.to/ecdh.html
|
||||||
|
// (Just to make sure printing the real private key)
|
||||||
privateKey[0] &= 248
|
privateKey[0] &= 248
|
||||||
privateKey[31] &= 127
|
privateKey[31] &= 127
|
||||||
privateKey[31] |= 64
|
privateKey[31] |= 64
|
||||||
|
|
||||||
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
|
key, err := ecdh.X25519().NewPrivateKey(privateKey)
|
||||||
output = err.Error()
|
if err != nil {
|
||||||
goto out
|
fmt.Println(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
fmt.Printf("PrivateKey: %v\nPassword: %v",
|
||||||
output = fmt.Sprintf("Private key: %v\nPublic key: %v",
|
|
||||||
encoding.EncodeToString(privateKey),
|
encoding.EncodeToString(privateKey),
|
||||||
encoding.EncodeToString(publicKey))
|
encoding.EncodeToString(key.PublicKey().Bytes()))
|
||||||
out:
|
|
||||||
fmt.Println(output)
|
|
||||||
}
|
}
|
||||||
|
@@ -11,9 +11,9 @@ import (
|
|||||||
|
|
||||||
var cmdMLDSA65 = &base.Command{
|
var cmdMLDSA65 = &base.Command{
|
||||||
UsageLine: `{{.Exec}} mldsa65 [-i "seed (base64.RawURLEncoding)"]`,
|
UsageLine: `{{.Exec}} mldsa65 [-i "seed (base64.RawURLEncoding)"]`,
|
||||||
Short: `Generate key pair for ML-DSA-65 post-quantum signature`,
|
Short: `Generate key pair for ML-DSA-65 post-quantum signature (REALITY)`,
|
||||||
Long: `
|
Long: `
|
||||||
Generate key pair for ML-DSA-65 post-quantum signature.
|
Generate key pair for ML-DSA-65 post-quantum signature (REALITY).
|
||||||
|
|
||||||
Random: {{.Exec}} mldsa65
|
Random: {{.Exec}} mldsa65
|
||||||
|
|
||||||
@@ -25,12 +25,16 @@ func init() {
|
|||||||
cmdMLDSA65.Run = executeMLDSA65 // break init loop
|
cmdMLDSA65.Run = executeMLDSA65 // break init loop
|
||||||
}
|
}
|
||||||
|
|
||||||
var input_seed = cmdMLDSA65.Flag.String("i", "", "")
|
var input_mldsa65 = cmdMLDSA65.Flag.String("i", "", "")
|
||||||
|
|
||||||
func executeMLDSA65(cmd *base.Command, args []string) {
|
func executeMLDSA65(cmd *base.Command, args []string) {
|
||||||
var seed [32]byte
|
var seed [32]byte
|
||||||
if len(*input_seed) > 0 {
|
if len(*input_mldsa65) > 0 {
|
||||||
s, _ := base64.RawURLEncoding.DecodeString(*input_seed)
|
s, _ := base64.RawURLEncoding.DecodeString(*input_mldsa65)
|
||||||
|
if len(s) != 32 {
|
||||||
|
fmt.Println("Invalid length of ML-DSA-65 seed.")
|
||||||
|
return
|
||||||
|
}
|
||||||
seed = [32]byte(s)
|
seed = [32]byte(s)
|
||||||
} else {
|
} else {
|
||||||
rand.Read(seed[:])
|
rand.Read(seed[:])
|
||||||
|
50
main/commands/all/mlkem768.go
Normal file
50
main/commands/all/mlkem768.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package all
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/mlkem"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha3"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/main/commands/base"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cmdMLKEM768 = &base.Command{
|
||||||
|
UsageLine: `{{.Exec}} mlkem768 [-i "seed (base64.RawURLEncoding)"]`,
|
||||||
|
Short: `Generate key pair for ML-KEM-768 post-quantum key exchange (VLESS)`,
|
||||||
|
Long: `
|
||||||
|
Generate key pair for ML-KEM-768 post-quantum key exchange (VLESS).
|
||||||
|
|
||||||
|
Random: {{.Exec}} mlkem768
|
||||||
|
|
||||||
|
From seed: {{.Exec}} mlkem768 -i "seed (base64.RawURLEncoding)"
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmdMLKEM768.Run = executeMLKEM768 // break init loop
|
||||||
|
}
|
||||||
|
|
||||||
|
var input_mlkem768 = cmdMLKEM768.Flag.String("i", "", "")
|
||||||
|
|
||||||
|
func executeMLKEM768(cmd *base.Command, args []string) {
|
||||||
|
var seed [64]byte
|
||||||
|
if len(*input_mlkem768) > 0 {
|
||||||
|
s, _ := base64.RawURLEncoding.DecodeString(*input_mlkem768)
|
||||||
|
if len(s) != 64 {
|
||||||
|
fmt.Println("Invalid length of ML-KEM-768 seed.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
seed = [64]byte(s)
|
||||||
|
} else {
|
||||||
|
rand.Read(seed[:])
|
||||||
|
}
|
||||||
|
key, _ := mlkem.NewDecapsulationKey768(seed[:])
|
||||||
|
client := key.EncapsulationKey().Bytes()
|
||||||
|
hash32 := sha3.Sum256(client)
|
||||||
|
fmt.Printf("Seed: %v\nClient: %v\nHash11: %v",
|
||||||
|
base64.RawURLEncoding.EncodeToString(seed[:]),
|
||||||
|
base64.RawURLEncoding.EncodeToString(client),
|
||||||
|
base64.RawURLEncoding.EncodeToString(hash32[:11]))
|
||||||
|
}
|
@@ -9,9 +9,9 @@ import (
|
|||||||
|
|
||||||
var cmdUUID = &base.Command{
|
var cmdUUID = &base.Command{
|
||||||
UsageLine: `{{.Exec}} uuid [-i "example"]`,
|
UsageLine: `{{.Exec}} uuid [-i "example"]`,
|
||||||
Short: `Generate UUIDv4 or UUIDv5`,
|
Short: `Generate UUIDv4 or UUIDv5 (VLESS)`,
|
||||||
Long: `
|
Long: `
|
||||||
Generate UUIDv4 or UUIDv5.
|
Generate UUIDv4 or UUIDv5 (VLESS).
|
||||||
|
|
||||||
UUIDv4 (random): {{.Exec}} uuid
|
UUIDv4 (random): {{.Exec}} uuid
|
||||||
|
|
||||||
|
@@ -6,9 +6,9 @@ import (
|
|||||||
|
|
||||||
var cmdWG = &base.Command{
|
var cmdWG = &base.Command{
|
||||||
UsageLine: `{{.Exec}} wg [-i "private key (base64.StdEncoding)"]`,
|
UsageLine: `{{.Exec}} wg [-i "private key (base64.StdEncoding)"]`,
|
||||||
Short: `Generate key pair for wireguard key exchange`,
|
Short: `Generate key pair for X25519 key exchange (WireGuard)`,
|
||||||
Long: `
|
Long: `
|
||||||
Generate key pair for wireguard key exchange.
|
Generate key pair for X25519 key exchange (WireGuard).
|
||||||
|
|
||||||
Random: {{.Exec}} wg
|
Random: {{.Exec}} wg
|
||||||
|
|
||||||
|
@@ -6,9 +6,9 @@ import (
|
|||||||
|
|
||||||
var cmdX25519 = &base.Command{
|
var cmdX25519 = &base.Command{
|
||||||
UsageLine: `{{.Exec}} x25519 [-i "private key (base64.RawURLEncoding)"] [--std-encoding]`,
|
UsageLine: `{{.Exec}} x25519 [-i "private key (base64.RawURLEncoding)"] [--std-encoding]`,
|
||||||
Short: `Generate key pair for x25519 key exchange`,
|
Short: `Generate key pair for X25519 key exchange (VLESS, REALITY)`,
|
||||||
Long: `
|
Long: `
|
||||||
Generate key pair for x25519 key exchange.
|
Generate key pair for X25519 key exchange (VLESS, REALITY).
|
||||||
|
|
||||||
Random: {{.Exec}} x25519
|
Random: {{.Exec}} x25519
|
||||||
|
|
||||||
|
@@ -150,6 +150,8 @@ type Fragment struct {
|
|||||||
LengthMax uint64 `protobuf:"varint,4,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"`
|
LengthMax uint64 `protobuf:"varint,4,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"`
|
||||||
IntervalMin uint64 `protobuf:"varint,5,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
|
IntervalMin uint64 `protobuf:"varint,5,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
|
||||||
IntervalMax uint64 `protobuf:"varint,6,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
|
IntervalMax uint64 `protobuf:"varint,6,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
|
||||||
|
MaxSplitMin uint64 `protobuf:"varint,7,opt,name=max_split_min,json=maxSplitMin,proto3" json:"max_split_min,omitempty"`
|
||||||
|
MaxSplitMax uint64 `protobuf:"varint,8,opt,name=max_split_max,json=maxSplitMax,proto3" json:"max_split_max,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Fragment) Reset() {
|
func (x *Fragment) Reset() {
|
||||||
@@ -224,6 +226,20 @@ func (x *Fragment) GetIntervalMax() uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Fragment) GetMaxSplitMin() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.MaxSplitMin
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Fragment) GetMaxSplitMax() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.MaxSplitMax
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type Noise struct {
|
type Noise struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -234,6 +250,7 @@ type Noise struct {
|
|||||||
DelayMin uint64 `protobuf:"varint,3,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,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"`
|
DelayMax uint64 `protobuf:"varint,4,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"`
|
||||||
Packet []byte `protobuf:"bytes,5,opt,name=packet,proto3" json:"packet,omitempty"`
|
Packet []byte `protobuf:"bytes,5,opt,name=packet,proto3" json:"packet,omitempty"`
|
||||||
|
ApplyTo string `protobuf:"bytes,6,opt,name=apply_to,json=applyTo,proto3" json:"apply_to,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Noise) Reset() {
|
func (x *Noise) Reset() {
|
||||||
@@ -301,6 +318,13 @@ func (x *Noise) GetPacket() []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Noise) GetApplyTo() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ApplyTo
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -399,7 +423,7 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
|
|||||||
0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
|
0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||||
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0xd0, 0x01, 0x0a, 0x08, 0x46, 0x72, 0x61,
|
0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x02, 0x0a, 0x08, 0x46, 0x72, 0x61,
|
||||||
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
|
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
|
||||||
0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61, 0x63,
|
0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61, 0x63,
|
||||||
0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b,
|
0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b,
|
||||||
@@ -412,57 +436,63 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
|
|||||||
0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74,
|
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,
|
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,
|
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, 0x97, 0x01, 0x0a, 0x05,
|
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x22, 0x0a, 0x0d, 0x6d,
|
||||||
0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f,
|
0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01,
|
||||||
0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74,
|
0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x69, 0x6e, 0x12,
|
||||||
0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d,
|
0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x61, 0x78,
|
||||||
0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
|
0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74,
|
||||||
0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e,
|
0x4d, 0x61, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e,
|
0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20,
|
0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a,
|
||||||
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a,
|
0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
|
||||||
0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70,
|
0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64,
|
||||||
0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
|
||||||
0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74,
|
0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61,
|
||||||
0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x43,
|
0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61,
|
0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19, 0x0a,
|
||||||
0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61,
|
0x08, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
0x07, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
|
||||||
0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01,
|
0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74,
|
||||||
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78,
|
||||||
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f,
|
||||||
0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, 0x64, 0x65, 0x73,
|
0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||||
0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||||
0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69,
|
||||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12,
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18,
|
||||||
0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
|
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66,
|
0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69,
|
||||||
0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52,
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13,
|
||||||
0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f,
|
0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||||
0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28,
|
0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65,
|
||||||
0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76,
|
||||||
0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b,
|
0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05,
|
||||||
0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06, 0x6e, 0x6f, 0x69,
|
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65,
|
||||||
0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
|
0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e,
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10,
|
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06,
|
||||||
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a,
|
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53,
|
0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20,
|
||||||
0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||||
0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36,
|
0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06,
|
||||||
0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10,
|
0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07,
|
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f,
|
||||||
0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12,
|
0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01,
|
||||||
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12,
|
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a,
|
||||||
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42,
|
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
|
||||||
0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
|
||||||
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74,
|
0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
|
||||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x66, 0x72, 0x65,
|
0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36,
|
||||||
0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78,
|
0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36,
|
||||||
0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34,
|
||||||
0x33,
|
0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||||
|
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27,
|
||||||
|
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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
||||||
|
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50,
|
||||||
|
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -19,6 +19,8 @@ message Fragment {
|
|||||||
uint64 length_max = 4;
|
uint64 length_max = 4;
|
||||||
uint64 interval_min = 5;
|
uint64 interval_min = 5;
|
||||||
uint64 interval_max = 6;
|
uint64 interval_max = 6;
|
||||||
|
uint64 max_split_min = 7;
|
||||||
|
uint64 max_split_max = 8;
|
||||||
}
|
}
|
||||||
message Noise {
|
message Noise {
|
||||||
uint64 length_min = 1;
|
uint64 length_min = 1;
|
||||||
@@ -26,6 +28,7 @@ message Noise {
|
|||||||
uint64 delay_min = 3;
|
uint64 delay_min = 3;
|
||||||
uint64 delay_max = 4;
|
uint64 delay_max = 4;
|
||||||
bytes packet = 5;
|
bytes packet = 5;
|
||||||
|
string apply_to = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
|
@@ -194,7 +194,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
if destination.Network == net.Network_TCP {
|
if destination.Network == net.Network_TCP {
|
||||||
if h.config.Fragment != nil {
|
if h.config.Fragment != nil {
|
||||||
errors.LogDebug(ctx, "FRAGMENT", h.config.Fragment.PacketsFrom, h.config.Fragment.PacketsTo, h.config.Fragment.LengthMin, h.config.Fragment.LengthMax,
|
errors.LogDebug(ctx, "FRAGMENT", h.config.Fragment.PacketsFrom, h.config.Fragment.PacketsTo, h.config.Fragment.LengthMin, h.config.Fragment.LengthMax,
|
||||||
h.config.Fragment.IntervalMin, h.config.Fragment.IntervalMax)
|
h.config.Fragment.IntervalMin, h.config.Fragment.IntervalMax, h.config.Fragment.MaxSplitMin, h.config.Fragment.MaxSplitMax)
|
||||||
writer = buf.NewWriter(&FragmentWriter{
|
writer = buf.NewWriter(&FragmentWriter{
|
||||||
fragment: h.config.Fragment,
|
fragment: h.config.Fragment,
|
||||||
writer: conn,
|
writer: conn,
|
||||||
@@ -211,6 +211,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
noises: h.config.Noises,
|
noises: h.config.Noises,
|
||||||
firstWrite: true,
|
firstWrite: true,
|
||||||
UDPOverride: UDPOverride,
|
UDPOverride: UDPOverride,
|
||||||
|
remoteAddr: net.DestinationFromAddr(conn.RemoteAddr()).Address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,14 +290,13 @@ func NewPacketReader(conn net.Conn, UDPOverride net.Destination, DialDest net.De
|
|||||||
if UDPOverride.Address != nil || UDPOverride.Port != 0 {
|
if UDPOverride.Address != nil || UDPOverride.Port != 0 {
|
||||||
isOverridden = true
|
isOverridden = true
|
||||||
}
|
}
|
||||||
changedAddress, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
|
||||||
|
|
||||||
return &PacketReader{
|
return &PacketReader{
|
||||||
PacketConnWrapper: c,
|
PacketConnWrapper: c,
|
||||||
Counter: counter,
|
Counter: counter,
|
||||||
IsOverridden: isOverridden,
|
IsOverridden: isOverridden,
|
||||||
InitUnchangedAddr: DialDest.Address,
|
InitUnchangedAddr: DialDest.Address,
|
||||||
InitChangedAddr: net.ParseAddress(changedAddress),
|
InitChangedAddr: net.DestinationFromAddr(conn.RemoteAddr()).Address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &buf.PacketReader{Reader: conn}
|
return &buf.PacketReader{Reader: conn}
|
||||||
@@ -354,8 +354,7 @@ func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride
|
|||||||
// check this behavior and add it to map
|
// check this behavior and add it to map
|
||||||
resolvedUDPAddr := utils.NewTypedSyncMap[string, net.Address]()
|
resolvedUDPAddr := utils.NewTypedSyncMap[string, net.Address]()
|
||||||
if DialDest.Address.Family().IsDomain() {
|
if DialDest.Address.Family().IsDomain() {
|
||||||
RemoteAddress, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
resolvedUDPAddr.Store(DialDest.Address.Domain(), net.DestinationFromAddr(conn.RemoteAddr()).Address)
|
||||||
resolvedUDPAddr.Store(DialDest.Address.String(), net.ParseAddress(RemoteAddress))
|
|
||||||
}
|
}
|
||||||
return &PacketWriter{
|
return &PacketWriter{
|
||||||
PacketConnWrapper: c,
|
PacketConnWrapper: c,
|
||||||
@@ -456,6 +455,7 @@ type NoisePacketWriter struct {
|
|||||||
noises []*Noise
|
noises []*Noise
|
||||||
firstWrite bool
|
firstWrite bool
|
||||||
UDPOverride net.Destination
|
UDPOverride net.Destination
|
||||||
|
remoteAddr net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultiBuffer writer with Noise before first packet
|
// MultiBuffer writer with Noise before first packet
|
||||||
@@ -468,8 +468,24 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
}
|
}
|
||||||
var noise []byte
|
var noise []byte
|
||||||
var err error
|
var err error
|
||||||
|
if w.remoteAddr.Family().IsDomain() {
|
||||||
|
panic("impossible, remoteAddr is always IP")
|
||||||
|
}
|
||||||
for _, n := range w.noises {
|
for _, n := range w.noises {
|
||||||
//User input string or base64 encoded string
|
switch n.ApplyTo {
|
||||||
|
case "ipv4":
|
||||||
|
if w.remoteAddr.Family().IsIPv6() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case "ipv6":
|
||||||
|
if w.remoteAddr.Family().IsIPv4() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case "ip":
|
||||||
|
default:
|
||||||
|
panic("unreachable, applyTo is ip/ipv4/ipv6")
|
||||||
|
}
|
||||||
|
//User input string or base64 encoded string or hex string
|
||||||
if n.Packet != nil {
|
if n.Packet != nil {
|
||||||
noise = n.Packet
|
noise = n.Packet
|
||||||
} else {
|
} else {
|
||||||
@@ -509,23 +525,29 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
|
|||||||
return f.writer.Write(b)
|
return f.writer.Write(b)
|
||||||
}
|
}
|
||||||
data := b[5:recordLen]
|
data := b[5:recordLen]
|
||||||
buf := make([]byte, 1024)
|
buff := make([]byte, 2048)
|
||||||
var hello []byte
|
var hello []byte
|
||||||
|
maxSplit := crypto.RandBetween(int64(f.fragment.MaxSplitMin), int64(f.fragment.MaxSplitMax))
|
||||||
|
var splitNum int64
|
||||||
for from := 0; ; {
|
for from := 0; ; {
|
||||||
to := from + int(crypto.RandBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
|
to := from + int(crypto.RandBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
|
||||||
if to > len(data) {
|
splitNum++
|
||||||
|
if to > len(data) || (maxSplit > 0 && splitNum >= maxSplit) {
|
||||||
to = len(data)
|
to = len(data)
|
||||||
}
|
}
|
||||||
copy(buf[:3], b)
|
|
||||||
copy(buf[5:], data[from:to])
|
|
||||||
l := to - from
|
l := to - from
|
||||||
|
if 5+l > len(buff) {
|
||||||
|
buff = make([]byte, 5+l)
|
||||||
|
}
|
||||||
|
copy(buff[:3], b)
|
||||||
|
copy(buff[5:], data[from:to])
|
||||||
from = to
|
from = to
|
||||||
buf[3] = byte(l >> 8)
|
buff[3] = byte(l >> 8)
|
||||||
buf[4] = byte(l)
|
buff[4] = byte(l)
|
||||||
if f.fragment.IntervalMax == 0 { // combine fragmented tlshello if interval is 0
|
if f.fragment.IntervalMax == 0 { // combine fragmented tlshello if interval is 0
|
||||||
hello = append(hello, buf[:5+l]...)
|
hello = append(hello, buff[:5+l]...)
|
||||||
} else {
|
} else {
|
||||||
_, err := f.writer.Write(buf[:5+l])
|
_, err := f.writer.Write(buff[:5+l])
|
||||||
time.Sleep(time.Duration(crypto.RandBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
|
time.Sleep(time.Duration(crypto.RandBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -552,17 +574,20 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
|
|||||||
if f.fragment.PacketsFrom != 0 && (f.count < f.fragment.PacketsFrom || f.count > f.fragment.PacketsTo) {
|
if f.fragment.PacketsFrom != 0 && (f.count < f.fragment.PacketsFrom || f.count > f.fragment.PacketsTo) {
|
||||||
return f.writer.Write(b)
|
return f.writer.Write(b)
|
||||||
}
|
}
|
||||||
|
maxSplit := crypto.RandBetween(int64(f.fragment.MaxSplitMin), int64(f.fragment.MaxSplitMax))
|
||||||
|
var splitNum int64
|
||||||
for from := 0; ; {
|
for from := 0; ; {
|
||||||
to := from + int(crypto.RandBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
|
to := from + int(crypto.RandBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
|
||||||
if to > len(b) {
|
splitNum++
|
||||||
|
if to > len(b) || (maxSplit > 0 && splitNum >= maxSplit) {
|
||||||
to = len(b)
|
to = len(b)
|
||||||
}
|
}
|
||||||
n, err := f.writer.Write(b[from:to])
|
n, err := f.writer.Write(b[from:to])
|
||||||
from += n
|
from += n
|
||||||
time.Sleep(time.Duration(crypto.RandBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return from, err
|
return from, err
|
||||||
}
|
}
|
||||||
|
time.Sleep(time.Duration(crypto.RandBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
|
||||||
if from >= len(b) {
|
if from >= len(b) {
|
||||||
return from, nil
|
return from, nil
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/signal"
|
"github.com/xtls/xray-core/common/signal"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
|
"github.com/xtls/xray-core/proxy/vless/encryption"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
@@ -524,16 +525,31 @@ func XtlsFilterTls(buffer buf.MultiBuffer, trafficState *TrafficState, ctx conte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnwrapRawConn support unwrap stats, tls, utls, reality, proxyproto, uds-wrapper conn and get raw tcp/uds conn from it
|
// UnwrapRawConn support unwrap encryption, stats, tls, utls, reality, proxyproto, uds-wrapper conn and get raw tcp/uds conn from it
|
||||||
func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
|
func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
|
||||||
var readCounter, writerCounter stats.Counter
|
var readCounter, writerCounter stats.Counter
|
||||||
if conn != nil {
|
if conn != nil {
|
||||||
statConn, ok := conn.(*stat.CounterConnection)
|
isEncryption := false
|
||||||
if ok {
|
if clientConn, ok := conn.(*encryption.ClientConn); ok {
|
||||||
|
conn = clientConn.Conn
|
||||||
|
isEncryption = true
|
||||||
|
}
|
||||||
|
if serverConn, ok := conn.(*encryption.ServerConn); ok {
|
||||||
|
conn = serverConn.Conn
|
||||||
|
isEncryption = true
|
||||||
|
}
|
||||||
|
if xorConn, ok := conn.(*encryption.XorConn); ok {
|
||||||
|
if !xorConn.Divide {
|
||||||
|
return xorConn, nil, nil // full-random xorConn should not be penetrated
|
||||||
|
}
|
||||||
|
conn = xorConn.Conn
|
||||||
|
}
|
||||||
|
if statConn, ok := conn.(*stat.CounterConnection); ok {
|
||||||
conn = statConn.Connection
|
conn = statConn.Connection
|
||||||
readCounter = statConn.ReadCounter
|
readCounter = statConn.ReadCounter
|
||||||
writerCounter = statConn.WriteCounter
|
writerCounter = statConn.WriteCounter
|
||||||
}
|
}
|
||||||
|
if !isEncryption { // avoids double penetration
|
||||||
if xc, ok := conn.(*tls.Conn); ok {
|
if xc, ok := conn.(*tls.Conn); ok {
|
||||||
conn = xc.NetConn()
|
conn = xc.NetConn()
|
||||||
} else if utlsConn, ok := conn.(*tls.UConn); ok {
|
} else if utlsConn, ok := conn.(*tls.UConn); ok {
|
||||||
@@ -543,6 +559,7 @@ func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
|
|||||||
} else if realityUConn, ok := conn.(*reality.UConn); ok {
|
} else if realityUConn, ok := conn.(*reality.UConn); ok {
|
||||||
conn = realityUConn.NetConn()
|
conn = realityUConn.NetConn()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if pc, ok := conn.(*proxyproto.Conn); ok {
|
if pc, ok := conn.(*proxyproto.Conn); ok {
|
||||||
conn = pc.Raw()
|
conn = pc.Raw()
|
||||||
// 8192 > 4096, there is no need to process pc's bufReader
|
// 8192 > 4096, there is no need to process pc's bufReader
|
||||||
@@ -632,9 +649,20 @@ func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net
|
|||||||
}
|
}
|
||||||
|
|
||||||
func readV(ctx context.Context, reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, readCounter stats.Counter) error {
|
func readV(ctx context.Context, reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, readCounter stats.Counter) error {
|
||||||
errors.LogInfo(ctx, "CopyRawConn readv")
|
errors.LogInfo(ctx, "CopyRawConn (maybe) readv")
|
||||||
if err := buf.Copy(reader, writer, buf.UpdateActivity(timer), buf.AddToStatCounter(readCounter)); err != nil {
|
if err := buf.Copy(reader, writer, buf.UpdateActivity(timer), buf.AddToStatCounter(readCounter)); err != nil {
|
||||||
return errors.New("failed to process response").Base(err)
|
return errors.New("failed to process response").Base(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsRAWTransport(conn stat.Connection) bool {
|
||||||
|
iConn := conn
|
||||||
|
if statConn, ok := iConn.(*stat.CounterConnection); ok {
|
||||||
|
iConn = statConn.Connection
|
||||||
|
}
|
||||||
|
_, ok1 := iConn.(*proxyproto.Conn)
|
||||||
|
_, ok2 := iConn.(*net.TCPConn)
|
||||||
|
_, ok3 := iConn.(*internet.UnixConnWrapper)
|
||||||
|
return ok1 || ok2 || ok3
|
||||||
|
}
|
||||||
|
@@ -18,6 +18,8 @@ func (a *Account) AsAccount() (protocol.Account, error) {
|
|||||||
ID: protocol.NewID(id),
|
ID: protocol.NewID(id),
|
||||||
Flow: a.Flow, // needs parser here?
|
Flow: a.Flow, // needs parser here?
|
||||||
Encryption: a.Encryption, // needs parser here?
|
Encryption: a.Encryption, // needs parser here?
|
||||||
|
XorMode: a.XorMode,
|
||||||
|
Minutes: a.Minutes,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,8 +29,10 @@ type MemoryAccount struct {
|
|||||||
ID *protocol.ID
|
ID *protocol.ID
|
||||||
// Flow of the account. May be "xtls-rprx-vision".
|
// Flow of the account. May be "xtls-rprx-vision".
|
||||||
Flow string
|
Flow string
|
||||||
// Encryption of the account. Used for client connections, and only accepts "none" for now.
|
|
||||||
Encryption string
|
Encryption string
|
||||||
|
XorMode uint32
|
||||||
|
Minutes uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equals implements protocol.Account.Equals().
|
// Equals implements protocol.Account.Equals().
|
||||||
@@ -45,5 +49,7 @@ func (a *MemoryAccount) ToProto() proto.Message {
|
|||||||
Id: a.ID.String(),
|
Id: a.ID.String(),
|
||||||
Flow: a.Flow,
|
Flow: a.Flow,
|
||||||
Encryption: a.Encryption,
|
Encryption: a.Encryption,
|
||||||
|
XorMode: a.XorMode,
|
||||||
|
Minutes: a.Minutes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,8 +29,9 @@ type Account struct {
|
|||||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
// Flow settings. May be "xtls-rprx-vision".
|
// Flow settings. May be "xtls-rprx-vision".
|
||||||
Flow string `protobuf:"bytes,2,opt,name=flow,proto3" json:"flow,omitempty"`
|
Flow string `protobuf:"bytes,2,opt,name=flow,proto3" json:"flow,omitempty"`
|
||||||
// Encryption settings. Only applies to client side, and only accepts "none" for now.
|
|
||||||
Encryption string `protobuf:"bytes,3,opt,name=encryption,proto3" json:"encryption,omitempty"`
|
Encryption string `protobuf:"bytes,3,opt,name=encryption,proto3" json:"encryption,omitempty"`
|
||||||
|
XorMode uint32 `protobuf:"varint,4,opt,name=xorMode,proto3" json:"xorMode,omitempty"`
|
||||||
|
Minutes uint32 `protobuf:"varint,5,opt,name=minutes,proto3" json:"minutes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Account) Reset() {
|
func (x *Account) Reset() {
|
||||||
@@ -84,23 +85,40 @@ func (x *Account) GetEncryption() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Account) GetXorMode() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.XorMode
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Account) GetMinutes() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Minutes
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
var File_proxy_vless_account_proto protoreflect.FileDescriptor
|
var File_proxy_vless_account_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_proxy_vless_account_proto_rawDesc = []byte{
|
var file_proxy_vless_account_proto_rawDesc = []byte{
|
||||||
0x0a, 0x19, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x61, 0x63,
|
0x0a, 0x19, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x61, 0x63,
|
||||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61,
|
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61,
|
||||||
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x22, 0x4d, 0x0a,
|
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x22, 0x81, 0x01,
|
||||||
0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x6f, 0x77,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x6f,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1e, 0x0a, 0x0a,
|
0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1e, 0x0a,
|
||||||
0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
0x52, 0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x52, 0x0a, 0x14,
|
0x09, 0x52, 0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a,
|
||||||
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76,
|
0x07, 0x78, 0x6f, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
|
||||||
0x6c, 0x65, 0x73, 0x73, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
0x78, 0x6f, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x75, 0x74,
|
||||||
0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72,
|
0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x65,
|
||||||
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0xaa, 0x02, 0x10,
|
0x73, 0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72,
|
||||||
0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73,
|
0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74,
|
||||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65,
|
||||||
|
0x73, 0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
||||||
|
0x56, 0x6c, 0x65, 0x73, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -11,6 +11,8 @@ message Account {
|
|||||||
string id = 1;
|
string id = 1;
|
||||||
// Flow settings. May be "xtls-rprx-vision".
|
// Flow settings. May be "xtls-rprx-vision".
|
||||||
string flow = 2;
|
string flow = 2;
|
||||||
// Encryption settings. Only applies to client side, and only accepts "none" for now.
|
|
||||||
string encryption = 3;
|
string encryption = 3;
|
||||||
|
uint32 xorMode = 4;
|
||||||
|
uint32 minutes = 5;
|
||||||
}
|
}
|
||||||
|
@@ -172,7 +172,7 @@ func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*A
|
|||||||
}
|
}
|
||||||
|
|
||||||
// XtlsRead filter and read xtls protocol
|
// XtlsRead filter and read xtls protocol
|
||||||
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
|
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, peerCache *[]byte, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
for {
|
for {
|
||||||
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
|
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
|
||||||
@@ -194,7 +194,12 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
|
|||||||
if !buffer.IsEmpty() {
|
if !buffer.IsEmpty() {
|
||||||
timer.Update()
|
timer.Update()
|
||||||
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
|
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
|
||||||
// XTLS Vision processes struct TLS Conn's input and rawInput
|
// XTLS Vision processes struct Encryption Conn's peerCache or TLS Conn's input and rawInput
|
||||||
|
if peerCache != nil {
|
||||||
|
if len(*peerCache) != 0 {
|
||||||
|
buffer = buf.MergeBytes(buffer, *peerCache)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if inputBuffer, err := buf.ReadFrom(input); err == nil {
|
if inputBuffer, err := buf.ReadFrom(input); err == nil {
|
||||||
if !inputBuffer.IsEmpty() {
|
if !inputBuffer.IsEmpty() {
|
||||||
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
|
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
|
||||||
@@ -206,6 +211,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if werr := writer.WriteMultiBuffer(buffer); werr != nil {
|
if werr := writer.WriteMultiBuffer(buffer); werr != nil {
|
||||||
return werr
|
return werr
|
||||||
}
|
}
|
||||||
|
266
proxy/vless/encryption/client.go
Normal file
266
proxy/vless/encryption/client.go
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
package encryption
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/ecdh"
|
||||||
|
"crypto/mlkem"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha3"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ClientCipher byte
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if protocol.HasAESGCMHardwareSupport {
|
||||||
|
ClientCipher = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientInstance struct {
|
||||||
|
sync.RWMutex
|
||||||
|
nfsEKey *mlkem.EncapsulationKey768
|
||||||
|
hash11 [11]byte // no more capacity
|
||||||
|
xorMode uint32
|
||||||
|
xorPKey *ecdh.PublicKey
|
||||||
|
minutes time.Duration
|
||||||
|
expire time.Time
|
||||||
|
baseKey []byte
|
||||||
|
ticket []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientConn struct {
|
||||||
|
net.Conn
|
||||||
|
instance *ClientInstance
|
||||||
|
baseKey []byte
|
||||||
|
ticket []byte
|
||||||
|
random []byte
|
||||||
|
aead cipher.AEAD
|
||||||
|
nonce []byte
|
||||||
|
peerAEAD cipher.AEAD
|
||||||
|
peerNonce []byte
|
||||||
|
PeerCache []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *ClientInstance) Init(nfsEKeyBytes, xorPKeyBytes []byte, xorMode, minutes uint32) (err error) {
|
||||||
|
if i.nfsEKey != nil {
|
||||||
|
err = errors.New("already initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if xorMode > 0 {
|
||||||
|
i.xorMode = xorMode
|
||||||
|
if i.xorPKey, err = ecdh.X25519().NewPublicKey(xorPKeyBytes); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hash32 := sha3.Sum256(nfsEKeyBytes)
|
||||||
|
copy(i.hash11[:], hash32[:])
|
||||||
|
}
|
||||||
|
i.minutes = time.Duration(minutes) * time.Minute
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *ClientInstance) Handshake(conn net.Conn) (*ClientConn, error) {
|
||||||
|
if i.nfsEKey == nil {
|
||||||
|
return nil, errors.New("uninitialized")
|
||||||
|
}
|
||||||
|
if i.xorMode > 0 {
|
||||||
|
conn, _ = NewXorConn(conn, i.xorMode, i.xorPKey, nil)
|
||||||
|
}
|
||||||
|
c := &ClientConn{Conn: conn}
|
||||||
|
|
||||||
|
if i.minutes > 0 {
|
||||||
|
i.RLock()
|
||||||
|
if time.Now().Before(i.expire) {
|
||||||
|
c.instance = i
|
||||||
|
c.baseKey = i.baseKey
|
||||||
|
c.ticket = i.ticket
|
||||||
|
i.RUnlock()
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
i.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
pfsDKeySeed := make([]byte, 64)
|
||||||
|
rand.Read(pfsDKeySeed)
|
||||||
|
pfsDKey, _ := mlkem.NewDecapsulationKey768(pfsDKeySeed)
|
||||||
|
pfsEKeyBytes := pfsDKey.EncapsulationKey().Bytes()
|
||||||
|
nfsKey, encapsulatedNfsKey := i.nfsEKey.Encapsulate()
|
||||||
|
nfsAEAD := NewAEAD(ClientCipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey)
|
||||||
|
|
||||||
|
clientHello := make([]byte, 5+11+1+1184+1088+crypto.RandBetween(100, 1000))
|
||||||
|
EncodeHeader(clientHello, 1, 11+1+1184+1088)
|
||||||
|
copy(clientHello[5:], i.hash11[:])
|
||||||
|
clientHello[5+11] = ClientCipher
|
||||||
|
copy(clientHello[5+11+1:], pfsEKeyBytes)
|
||||||
|
copy(clientHello[5+11+1+1184:], encapsulatedNfsKey)
|
||||||
|
padding := clientHello[5+11+1+1184+1088:]
|
||||||
|
rand.Read(padding) // important
|
||||||
|
EncodeHeader(padding, 23, len(padding)-5)
|
||||||
|
nfsAEAD.Seal(padding[:5], clientHello[5:5+11+1], padding[5:len(padding)-16], padding[:5])
|
||||||
|
|
||||||
|
if _, err := c.Conn.Write(clientHello); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// client can send more NFS AEAD paddings / messages if needed
|
||||||
|
|
||||||
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before server hello
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t != 1 {
|
||||||
|
return nil, errors.New("unexpected type ", t, ", expect server hello")
|
||||||
|
}
|
||||||
|
peerServerHello := make([]byte, 1088+21)
|
||||||
|
if l != len(peerServerHello) {
|
||||||
|
return nil, errors.New("unexpected length ", l, " for server hello")
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerServerHello); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encapsulatedPfsKey := peerServerHello[:1088]
|
||||||
|
c.ticket = append(i.hash11[:], peerServerHello[1088:]...)
|
||||||
|
|
||||||
|
pfsKey, err := pfsDKey.Decapsulate(encapsulatedPfsKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.baseKey = append(pfsKey, nfsKey...)
|
||||||
|
|
||||||
|
VLESS, _ := NewAEAD(ClientCipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey).Open(nil, append(i.hash11[:], ClientCipher), c.ticket[11:], pfsEKeyBytes)
|
||||||
|
if !bytes.Equal(VLESS, []byte("VLESS")) {
|
||||||
|
return nil, errors.New("invalid server").AtError()
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.minutes > 0 {
|
||||||
|
i.Lock()
|
||||||
|
i.expire = time.Now().Add(i.minutes)
|
||||||
|
i.baseKey = c.baseKey
|
||||||
|
i.ticket = c.ticket
|
||||||
|
i.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientConn) Write(b []byte) (int, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
var data []byte
|
||||||
|
for n := 0; n < len(b); {
|
||||||
|
b := b[n:]
|
||||||
|
if len(b) > 8192 {
|
||||||
|
b = b[:8192] // for avoiding another copy() in server's Read()
|
||||||
|
}
|
||||||
|
n += len(b)
|
||||||
|
if c.aead == nil {
|
||||||
|
data = make([]byte, 5+32+32+5+len(b)+16)
|
||||||
|
EncodeHeader(data, 0, 32+32)
|
||||||
|
copy(data[5:], c.ticket)
|
||||||
|
c.random = make([]byte, 32)
|
||||||
|
rand.Read(c.random)
|
||||||
|
copy(data[5+32:], c.random)
|
||||||
|
EncodeHeader(data[5+32+32:], 23, len(b)+16)
|
||||||
|
c.aead = NewAEAD(ClientCipher, c.baseKey, c.random, c.ticket)
|
||||||
|
c.nonce = make([]byte, 12)
|
||||||
|
c.aead.Seal(data[:5+32+32+5], c.nonce, b, data[5+32+32:5+32+32+5])
|
||||||
|
} else {
|
||||||
|
data = make([]byte, 5+len(b)+16)
|
||||||
|
EncodeHeader(data, 23, len(b)+16)
|
||||||
|
c.aead.Seal(data[:5], c.nonce, b, data[:5])
|
||||||
|
if bytes.Equal(c.nonce, MaxNonce) {
|
||||||
|
c.aead = NewAEAD(ClientCipher, c.baseKey, data[5:], data[:5])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IncreaseNonce(c.nonce)
|
||||||
|
if _, err := c.Conn.Write(data); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClientConn) Read(b []byte) (int, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
if c.peerAEAD == nil {
|
||||||
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before random hello
|
||||||
|
if err != nil {
|
||||||
|
if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT
|
||||||
|
c.instance.Lock()
|
||||||
|
if bytes.Equal(c.ticket, c.instance.ticket) {
|
||||||
|
c.instance.expire = time.Now() // expired
|
||||||
|
}
|
||||||
|
c.instance.Unlock()
|
||||||
|
return 0, errors.New("new handshake needed")
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if t != 0 {
|
||||||
|
return 0, errors.New("unexpected type ", t, ", expect random hello")
|
||||||
|
}
|
||||||
|
peerRandomHello := make([]byte, 32)
|
||||||
|
if l != len(peerRandomHello) {
|
||||||
|
return 0, errors.New("unexpected length ", l, " for random hello")
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerRandomHello); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if c.random == nil {
|
||||||
|
return 0, errors.New("empty c.random")
|
||||||
|
}
|
||||||
|
c.peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerRandomHello, c.random)
|
||||||
|
c.peerNonce = make([]byte, 12)
|
||||||
|
}
|
||||||
|
if len(c.PeerCache) != 0 {
|
||||||
|
n := copy(b, c.PeerCache)
|
||||||
|
c.PeerCache = c.PeerCache[n:]
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
h, t, l, err := ReadAndDecodeHeader(c.Conn) // l: 17~17000
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if t != 23 {
|
||||||
|
return 0, errors.New("unexpected type ", t, ", expect encrypted data")
|
||||||
|
}
|
||||||
|
peerData := make([]byte, l)
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerData); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
dst := peerData[:l-16]
|
||||||
|
if len(dst) <= len(b) {
|
||||||
|
dst = b[:len(dst)] // avoids another copy()
|
||||||
|
}
|
||||||
|
var peerAEAD cipher.AEAD
|
||||||
|
if bytes.Equal(c.peerNonce, MaxNonce) {
|
||||||
|
peerAEAD = NewAEAD(ClientCipher, c.baseKey, peerData, h)
|
||||||
|
}
|
||||||
|
_, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h)
|
||||||
|
if peerAEAD != nil {
|
||||||
|
c.peerAEAD = peerAEAD
|
||||||
|
}
|
||||||
|
IncreaseNonce(c.peerNonce)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if len(dst) > len(b) {
|
||||||
|
c.PeerCache = dst[copy(b, dst):]
|
||||||
|
dst = b // for len(dst)
|
||||||
|
}
|
||||||
|
return len(dst), nil
|
||||||
|
}
|
100
proxy/vless/encryption/common.go
Normal file
100
proxy/vless/encryption/common.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package encryption
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/hkdf"
|
||||||
|
"crypto/sha3"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
|
)
|
||||||
|
|
||||||
|
var MaxNonce = bytes.Repeat([]byte{255}, 12)
|
||||||
|
|
||||||
|
func EncodeHeader(h []byte, t byte, l int) {
|
||||||
|
switch t {
|
||||||
|
case 1:
|
||||||
|
h[0] = 1
|
||||||
|
h[1] = 1
|
||||||
|
h[2] = 1
|
||||||
|
case 0:
|
||||||
|
h[0] = 0
|
||||||
|
h[1] = 0
|
||||||
|
h[2] = 0
|
||||||
|
case 23:
|
||||||
|
h[0] = 23
|
||||||
|
h[1] = 3
|
||||||
|
h[2] = 3
|
||||||
|
}
|
||||||
|
h[3] = byte(l >> 8)
|
||||||
|
h[4] = byte(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeHeader(h []byte) (t byte, l int, err error) {
|
||||||
|
l = int(h[3])<<8 | int(h[4])
|
||||||
|
if h[0] == 23 && h[1] == 3 && h[2] == 3 {
|
||||||
|
t = 23
|
||||||
|
} else if h[0] == 0 && h[1] == 0 && h[2] == 0 {
|
||||||
|
t = 0
|
||||||
|
} else if h[0] == 1 && h[1] == 1 && h[2] == 1 {
|
||||||
|
t = 1
|
||||||
|
} else {
|
||||||
|
l = 0
|
||||||
|
}
|
||||||
|
if l < 17 || l > 17000 { // TODO: TLSv1.3 max length
|
||||||
|
err = errors.New("invalid header: ", fmt.Sprintf("%v", h[:5])) // DO NOT CHANGE: relied by client's Read()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadAndDecodeHeader(conn net.Conn) (h []byte, t byte, l int, err error) {
|
||||||
|
h = make([]byte, 5)
|
||||||
|
if _, err = io.ReadFull(conn, h); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t, l, err = DecodeHeader(h)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadAndDiscardPaddings(conn net.Conn, aead cipher.AEAD, nonce []byte) (h []byte, t byte, l int, err error) {
|
||||||
|
for {
|
||||||
|
if h, t, l, err = ReadAndDecodeHeader(conn); err != nil || t != 23 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
padding := make([]byte, l)
|
||||||
|
if _, err = io.ReadFull(conn, padding); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if aead != nil {
|
||||||
|
if _, err := aead.Open(nil, nonce, padding, h); err != nil {
|
||||||
|
return h, t, l, err
|
||||||
|
}
|
||||||
|
IncreaseNonce(nonce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAEAD(c byte, secret, salt, info []byte) (aead cipher.AEAD) {
|
||||||
|
key, _ := hkdf.Key(sha3.New256, secret, salt, string(info), 32)
|
||||||
|
if c&1 == 1 {
|
||||||
|
block, _ := aes.NewCipher(key)
|
||||||
|
aead, _ = cipher.NewGCM(block)
|
||||||
|
} else {
|
||||||
|
aead, _ = chacha20poly1305.New(key)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func IncreaseNonce(nonce []byte) {
|
||||||
|
for i := range 12 {
|
||||||
|
nonce[11-i]++
|
||||||
|
if nonce[11-i] != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
311
proxy/vless/encryption/server.go
Normal file
311
proxy/vless/encryption/server.go
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
package encryption
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/ecdh"
|
||||||
|
"crypto/mlkem"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha3"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/crypto"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServerSession struct {
|
||||||
|
expire time.Time
|
||||||
|
cipher byte
|
||||||
|
baseKey []byte
|
||||||
|
randoms sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerInstance struct {
|
||||||
|
sync.RWMutex
|
||||||
|
nfsDKey *mlkem.DecapsulationKey768
|
||||||
|
hash11 [11]byte // no more capacity
|
||||||
|
xorMode uint32
|
||||||
|
xorSKey *ecdh.PrivateKey
|
||||||
|
minutes time.Duration
|
||||||
|
sessions map[[32]byte]*ServerSession
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerConn struct {
|
||||||
|
net.Conn
|
||||||
|
cipher byte
|
||||||
|
baseKey []byte
|
||||||
|
ticket []byte
|
||||||
|
peerRandom []byte
|
||||||
|
peerAEAD cipher.AEAD
|
||||||
|
peerNonce []byte
|
||||||
|
PeerCache []byte
|
||||||
|
aead cipher.AEAD
|
||||||
|
nonce []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *ServerInstance) Init(nfsDKeySeed, xorSKeyBytes []byte, xorMode, minutes uint32) (err error) {
|
||||||
|
if i.nfsDKey != nil {
|
||||||
|
err = errors.New("already initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if xorMode > 0 {
|
||||||
|
i.xorMode = xorMode
|
||||||
|
if i.xorSKey, err = ecdh.X25519().NewPrivateKey(xorSKeyBytes); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hash32 := sha3.Sum256(i.nfsDKey.EncapsulationKey().Bytes())
|
||||||
|
copy(i.hash11[:], hash32[:])
|
||||||
|
}
|
||||||
|
if minutes > 0 {
|
||||||
|
i.minutes = time.Duration(minutes) * time.Minute
|
||||||
|
i.sessions = make(map[[32]byte]*ServerSession)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Minute)
|
||||||
|
i.Lock()
|
||||||
|
if i.closed {
|
||||||
|
i.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
now := time.Now()
|
||||||
|
for ticket, session := range i.sessions {
|
||||||
|
if now.After(session.expire) {
|
||||||
|
delete(i.sessions, ticket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i.Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *ServerInstance) Close() (err error) {
|
||||||
|
i.Lock()
|
||||||
|
i.closed = true
|
||||||
|
i.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) {
|
||||||
|
if i.nfsDKey == nil {
|
||||||
|
return nil, errors.New("uninitialized")
|
||||||
|
}
|
||||||
|
if i.xorMode > 0 {
|
||||||
|
var err error
|
||||||
|
if conn, err = NewXorConn(conn, i.xorMode, nil, i.xorSKey); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := &ServerConn{Conn: conn}
|
||||||
|
|
||||||
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before client/ticket hello
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t == 0 {
|
||||||
|
if i.minutes == 0 {
|
||||||
|
return nil, errors.New("0-RTT is not allowed")
|
||||||
|
}
|
||||||
|
peerTicketHello := make([]byte, 32+32)
|
||||||
|
if l != len(peerTicketHello) {
|
||||||
|
return nil, errors.New("unexpected length ", l, " for ticket hello")
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !bytes.Equal(peerTicketHello[:11], i.hash11[:]) {
|
||||||
|
return nil, errors.New("unexpected hash11: ", fmt.Sprintf("%v", peerTicketHello[:11]))
|
||||||
|
}
|
||||||
|
i.RLock()
|
||||||
|
s := i.sessions[[32]byte(peerTicketHello)]
|
||||||
|
i.RUnlock()
|
||||||
|
if s == nil {
|
||||||
|
noises := make([]byte, crypto.RandBetween(100, 1000))
|
||||||
|
var err error
|
||||||
|
for err == nil {
|
||||||
|
rand.Read(noises)
|
||||||
|
_, _, err = DecodeHeader(noises)
|
||||||
|
}
|
||||||
|
c.Conn.Write(noises) // make client do new handshake
|
||||||
|
return nil, errors.New("expired ticket")
|
||||||
|
}
|
||||||
|
if _, replay := s.randoms.LoadOrStore([32]byte(peerTicketHello[32:]), true); replay {
|
||||||
|
return nil, errors.New("replay detected")
|
||||||
|
}
|
||||||
|
c.cipher = s.cipher
|
||||||
|
c.baseKey = s.baseKey
|
||||||
|
c.ticket = peerTicketHello[:32]
|
||||||
|
c.peerRandom = peerTicketHello[32:]
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
peerClientHello := make([]byte, 11+1+1184+1088)
|
||||||
|
if l != len(peerClientHello) {
|
||||||
|
return nil, errors.New("unexpected length ", l, " for client hello")
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerClientHello); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !bytes.Equal(peerClientHello[:11], i.hash11[:]) {
|
||||||
|
return nil, errors.New("unexpected hash11: ", fmt.Sprintf("%v", peerClientHello[:11]))
|
||||||
|
}
|
||||||
|
c.cipher = peerClientHello[11]
|
||||||
|
pfsEKeyBytes := peerClientHello[11+1 : 11+1+1184]
|
||||||
|
encapsulatedNfsKey := peerClientHello[11+1+1184:]
|
||||||
|
|
||||||
|
pfsEKey, err := mlkem.NewEncapsulationKey768(pfsEKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nfsKey, err := i.nfsDKey.Decapsulate(encapsulatedNfsKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nfsAEAD := NewAEAD(c.cipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey)
|
||||||
|
nfsNonce := append([]byte{}, peerClientHello[:11+1]...)
|
||||||
|
pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate()
|
||||||
|
c.baseKey = append(pfsKey, nfsKey...)
|
||||||
|
pfsAEAD := NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey)
|
||||||
|
pfsNonce := append([]byte{}, peerClientHello[:11+1]...)
|
||||||
|
c.ticket = append(i.hash11[:], pfsAEAD.Seal(nil, pfsNonce, []byte("VLESS"), pfsEKeyBytes)...)
|
||||||
|
IncreaseNonce(pfsNonce)
|
||||||
|
|
||||||
|
serverHello := make([]byte, 5+1088+21+crypto.RandBetween(100, 1000))
|
||||||
|
EncodeHeader(serverHello, 1, 1088+21)
|
||||||
|
copy(serverHello[5:], encapsulatedPfsKey)
|
||||||
|
copy(serverHello[5+1088:], c.ticket[11:])
|
||||||
|
padding := serverHello[5+1088+21:]
|
||||||
|
rand.Read(padding) // important
|
||||||
|
EncodeHeader(padding, 23, len(padding)-5)
|
||||||
|
pfsAEAD.Seal(padding[:5], pfsNonce, padding[5:len(padding)-16], padding[:5])
|
||||||
|
|
||||||
|
if _, err := c.Conn.Write(serverHello); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// server can send more PFS AEAD paddings / messages if needed
|
||||||
|
|
||||||
|
_, t, l, err = ReadAndDiscardPaddings(c.Conn, nfsAEAD, nfsNonce) // allow paddings before ticket hello
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if t != 0 {
|
||||||
|
return nil, errors.New("unexpected type ", t, ", expect ticket hello")
|
||||||
|
}
|
||||||
|
peerTicketHello := make([]byte, 32+32)
|
||||||
|
if l != len(peerTicketHello) {
|
||||||
|
return nil, errors.New("unexpected length ", l, " for ticket hello")
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !bytes.Equal(peerTicketHello[:32], c.ticket) {
|
||||||
|
return nil, errors.New("naughty boy")
|
||||||
|
}
|
||||||
|
c.peerRandom = peerTicketHello[32:]
|
||||||
|
|
||||||
|
if i.minutes > 0 {
|
||||||
|
i.Lock()
|
||||||
|
s := &ServerSession{
|
||||||
|
expire: time.Now().Add(i.minutes),
|
||||||
|
cipher: c.cipher,
|
||||||
|
baseKey: c.baseKey,
|
||||||
|
}
|
||||||
|
s.randoms.Store([32]byte(c.peerRandom), true)
|
||||||
|
i.sessions[[32]byte(c.ticket)] = s
|
||||||
|
i.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerConn) Read(b []byte) (int, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
if c.peerAEAD == nil {
|
||||||
|
c.peerAEAD = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket)
|
||||||
|
c.peerNonce = make([]byte, 12)
|
||||||
|
}
|
||||||
|
if len(c.PeerCache) != 0 {
|
||||||
|
n := copy(b, c.PeerCache)
|
||||||
|
c.PeerCache = c.PeerCache[n:]
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
h, t, l, err := ReadAndDecodeHeader(c.Conn) // l: 17~17000
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if t != 23 {
|
||||||
|
return 0, errors.New("unexpected type ", t, ", expect encrypted data")
|
||||||
|
}
|
||||||
|
peerData := make([]byte, l)
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerData); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
dst := peerData[:l-16]
|
||||||
|
if len(dst) <= len(b) {
|
||||||
|
dst = b[:len(dst)] // avoids another copy()
|
||||||
|
}
|
||||||
|
var peerAEAD cipher.AEAD
|
||||||
|
if bytes.Equal(c.peerNonce, MaxNonce) {
|
||||||
|
peerAEAD = NewAEAD(c.cipher, c.baseKey, peerData, h)
|
||||||
|
}
|
||||||
|
_, err = c.peerAEAD.Open(dst[:0], c.peerNonce, peerData, h)
|
||||||
|
if peerAEAD != nil {
|
||||||
|
c.peerAEAD = peerAEAD
|
||||||
|
}
|
||||||
|
IncreaseNonce(c.peerNonce)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if len(dst) > len(b) {
|
||||||
|
c.PeerCache = dst[copy(b, dst):]
|
||||||
|
dst = b // for len(dst)
|
||||||
|
}
|
||||||
|
return len(dst), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ServerConn) Write(b []byte) (int, error) {
|
||||||
|
if len(b) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
var data []byte
|
||||||
|
for n := 0; n < len(b); {
|
||||||
|
b := b[n:]
|
||||||
|
if len(b) > 8192 {
|
||||||
|
b = b[:8192] // for avoiding another copy() in client's Read()
|
||||||
|
}
|
||||||
|
n += len(b)
|
||||||
|
if c.aead == nil {
|
||||||
|
data = make([]byte, 5+32+5+len(b)+16)
|
||||||
|
EncodeHeader(data, 0, 32)
|
||||||
|
rand.Read(data[5 : 5+32])
|
||||||
|
EncodeHeader(data[5+32:], 23, len(b)+16)
|
||||||
|
c.aead = NewAEAD(c.cipher, c.baseKey, data[5:5+32], c.peerRandom)
|
||||||
|
c.nonce = make([]byte, 12)
|
||||||
|
c.aead.Seal(data[:5+32+5], c.nonce, b, data[5+32:5+32+5])
|
||||||
|
} else {
|
||||||
|
data = make([]byte, 5+len(b)+16)
|
||||||
|
EncodeHeader(data, 23, len(b)+16)
|
||||||
|
c.aead.Seal(data[:5], c.nonce, b, data[:5])
|
||||||
|
if bytes.Equal(c.nonce, MaxNonce) {
|
||||||
|
c.aead = NewAEAD(c.cipher, c.baseKey, data[5:], data[:5])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IncreaseNonce(c.nonce)
|
||||||
|
if _, err := c.Conn.Write(data); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(b), nil
|
||||||
|
}
|
200
proxy/vless/encryption/xor.go
Normal file
200
proxy/vless/encryption/xor.go
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
package encryption
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/ecdh"
|
||||||
|
"crypto/hkdf"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha3"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type XorConn struct {
|
||||||
|
net.Conn
|
||||||
|
Divide bool
|
||||||
|
|
||||||
|
head []byte
|
||||||
|
key []byte
|
||||||
|
ctr cipher.Stream
|
||||||
|
peerCtr cipher.Stream
|
||||||
|
isHeader bool
|
||||||
|
skipNext bool
|
||||||
|
|
||||||
|
out_after0 bool
|
||||||
|
out_header []byte
|
||||||
|
out_skip int
|
||||||
|
|
||||||
|
in_after0 bool
|
||||||
|
in_header []byte
|
||||||
|
in_skip int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCTR(key, iv []byte, isServer bool) cipher.Stream {
|
||||||
|
info := "CLIENT"
|
||||||
|
if isServer {
|
||||||
|
info = "SERVER" // avoids attackers sending traffic back to the client, though the encryption layer has its own protection
|
||||||
|
}
|
||||||
|
key, _ = hkdf.Key(sha3.New256, key, iv, info, 32) // avoids using pKey directly if attackers sent the basepoint, or whaterver they like
|
||||||
|
block, _ := aes.NewCipher(key)
|
||||||
|
return cipher.NewCTR(block, iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewXorConn(conn net.Conn, mode uint32, pKey *ecdh.PublicKey, sKey *ecdh.PrivateKey) (*XorConn, error) {
|
||||||
|
if mode == 0 || (pKey == nil && sKey == nil) || (pKey != nil && sKey != nil) {
|
||||||
|
return nil, errors.New("invalid parameters")
|
||||||
|
}
|
||||||
|
c := &XorConn{
|
||||||
|
Conn: conn,
|
||||||
|
Divide: mode == 1,
|
||||||
|
isHeader: true,
|
||||||
|
out_header: make([]byte, 0, 5), // important
|
||||||
|
in_header: make([]byte, 0, 5), // important
|
||||||
|
}
|
||||||
|
if pKey != nil {
|
||||||
|
c.head = make([]byte, 16+32)
|
||||||
|
rand.Read(c.head)
|
||||||
|
eSKey, _ := ecdh.X25519().NewPrivateKey(c.head[16:])
|
||||||
|
NewCTR(pKey.Bytes(), c.head[:16], false).XORKeyStream(c.head[16:], eSKey.PublicKey().Bytes()) // make X25519 public key distinguishable from random bytes
|
||||||
|
c.key, _ = eSKey.ECDH(pKey)
|
||||||
|
c.ctr = NewCTR(c.key, c.head[:16], false)
|
||||||
|
}
|
||||||
|
if sKey != nil {
|
||||||
|
peerHead := make([]byte, 16+32)
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerHead); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
NewCTR(sKey.PublicKey().Bytes(), peerHead[:16], false).XORKeyStream(peerHead[16:], peerHead[16:]) // we don't use buggy elligator, because we have PSK :)
|
||||||
|
ePKey, err := ecdh.X25519().NewPublicKey(peerHead[16:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key, err := sKey.ECDH(ePKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.peerCtr = NewCTR(key, peerHead[:16], false)
|
||||||
|
c.head = make([]byte, 16)
|
||||||
|
rand.Read(c.head) // make sure the server always replies random bytes even when received replays, though it is not important
|
||||||
|
c.ctr = NewCTR(key, c.head, true) // the same key links the upload & download, though the encryption layer has its own link
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
//chacha20.NewUnauthenticatedCipher()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XorConn) Write(b []byte) (int, error) { // whole one/two records
|
||||||
|
if len(b) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
if !c.out_after0 {
|
||||||
|
t, l, _ := DecodeHeader(b)
|
||||||
|
if t == 23 { // single 23
|
||||||
|
l = 5
|
||||||
|
} else { // 1/0 + 23, or noises only
|
||||||
|
l += 10
|
||||||
|
if t == 0 {
|
||||||
|
c.out_after0 = true
|
||||||
|
if c.Divide {
|
||||||
|
l -= 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b
|
||||||
|
l = len(b)
|
||||||
|
if c.head != nil {
|
||||||
|
b = append(c.head, b...)
|
||||||
|
c.head = nil
|
||||||
|
}
|
||||||
|
if _, err := c.Conn.Write(b); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
if c.Divide {
|
||||||
|
return c.Conn.Write(b)
|
||||||
|
}
|
||||||
|
for p := b; ; { // for XTLS
|
||||||
|
if len(p) <= c.out_skip {
|
||||||
|
c.out_skip -= len(p)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p = p[c.out_skip:]
|
||||||
|
c.out_skip = 0
|
||||||
|
need := 5 - len(c.out_header)
|
||||||
|
if len(p) < need {
|
||||||
|
c.out_header = append(c.out_header, p...)
|
||||||
|
c.ctr.XORKeyStream(p, p)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, c.out_skip, _ = DecodeHeader(append(c.out_header, p[:need]...))
|
||||||
|
c.out_header = c.out_header[:0]
|
||||||
|
c.ctr.XORKeyStream(p[:need], p[:need])
|
||||||
|
p = p[need:]
|
||||||
|
}
|
||||||
|
if _, err := c.Conn.Write(b); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *XorConn) Read(b []byte) (int, error) { // 5-bytes, data, 5-bytes...
|
||||||
|
if len(b) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
if !c.in_after0 || !c.isHeader {
|
||||||
|
if c.peerCtr == nil { // for client
|
||||||
|
peerIv := make([]byte, 16)
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerIv); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
c.peerCtr = NewCTR(c.key, peerIv, true)
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(c.Conn, b); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if c.skipNext {
|
||||||
|
c.skipNext = false
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
c.peerCtr.XORKeyStream(b, b)
|
||||||
|
if c.isHeader { // always 5-bytes
|
||||||
|
if t, _, _ := DecodeHeader(b); t == 23 {
|
||||||
|
c.skipNext = true
|
||||||
|
} else {
|
||||||
|
c.isHeader = false
|
||||||
|
if t == 0 {
|
||||||
|
c.in_after0 = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.isHeader = true
|
||||||
|
}
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
if c.Divide {
|
||||||
|
return c.Conn.Read(b)
|
||||||
|
}
|
||||||
|
n, err := c.Conn.Read(b)
|
||||||
|
for p := b[:n]; ; { // for XTLS
|
||||||
|
if len(p) <= c.in_skip {
|
||||||
|
c.in_skip -= len(p)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p = p[c.in_skip:]
|
||||||
|
c.in_skip = 0
|
||||||
|
need := 5 - len(c.in_header)
|
||||||
|
if len(p) < need {
|
||||||
|
c.peerCtr.XORKeyStream(p, p)
|
||||||
|
c.in_header = append(c.in_header, p...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c.peerCtr.XORKeyStream(p[:need], p[:need])
|
||||||
|
_, c.in_skip, _ = DecodeHeader(append(c.in_header, p[:need]...))
|
||||||
|
c.in_header = c.in_header[:0]
|
||||||
|
p = p[need:]
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
@@ -112,10 +112,10 @@ type Config struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Clients []*protocol.User `protobuf:"bytes,1,rep,name=clients,proto3" json:"clients,omitempty"`
|
Clients []*protocol.User `protobuf:"bytes,1,rep,name=clients,proto3" json:"clients,omitempty"`
|
||||||
// Decryption settings. Only applies to server side, and only accepts "none"
|
Fallbacks []*Fallback `protobuf:"bytes,2,rep,name=fallbacks,proto3" json:"fallbacks,omitempty"`
|
||||||
// for now.
|
Decryption string `protobuf:"bytes,3,opt,name=decryption,proto3" json:"decryption,omitempty"`
|
||||||
Decryption string `protobuf:"bytes,2,opt,name=decryption,proto3" json:"decryption,omitempty"`
|
XorMode uint32 `protobuf:"varint,4,opt,name=xorMode,proto3" json:"xorMode,omitempty"`
|
||||||
Fallbacks []*Fallback `protobuf:"bytes,3,rep,name=fallbacks,proto3" json:"fallbacks,omitempty"`
|
Minutes uint32 `protobuf:"varint,5,opt,name=minutes,proto3" json:"minutes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -155,6 +155,13 @@ func (x *Config) GetClients() []*protocol.User {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetFallbacks() []*Fallback {
|
||||||
|
if x != nil {
|
||||||
|
return x.Fallbacks
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (x *Config) GetDecryption() string {
|
func (x *Config) GetDecryption() string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Decryption
|
return x.Decryption
|
||||||
@@ -162,11 +169,18 @@ func (x *Config) GetDecryption() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetFallbacks() []*Fallback {
|
func (x *Config) GetXorMode() uint32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Fallbacks
|
return x.XorMode
|
||||||
}
|
}
|
||||||
return nil
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetMinutes() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Minutes
|
||||||
|
}
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_proxy_vless_inbound_config_proto protoreflect.FileDescriptor
|
var File_proxy_vless_inbound_config_proto protoreflect.FileDescriptor
|
||||||
@@ -185,25 +199,28 @@ var file_proxy_vless_inbound_config_proto_rawDesc = []byte{
|
|||||||
0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20,
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65,
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65,
|
||||||
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0xa0, 0x01,
|
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0xd4, 0x01,
|
||||||
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65,
|
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x34, 0x0a, 0x07, 0x63, 0x6c, 0x69, 0x65,
|
||||||
0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||||
0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1e,
|
0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x40,
|
||||||
0x0a, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
0x0a, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||||
0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40,
|
|
||||||
0x0a, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
|
||||||
0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76,
|
0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76,
|
||||||
0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, 0x61, 0x6c,
|
0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, 0x61, 0x6c,
|
||||||
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73,
|
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73,
|
||||||
0x42, 0x6a, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
|
0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03,
|
||||||
0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
0x12, 0x18, 0x0a, 0x07, 0x78, 0x6f, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||||
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72,
|
0x0d, 0x52, 0x07, 0x78, 0x6f, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69,
|
||||||
0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
0x6e, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x69, 0x6e,
|
||||||
0x64, 0xaa, 0x02, 0x18, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56,
|
0x75, 0x74, 0x65, 0x73, 0x42, 0x6a, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x6c, 0x65, 0x73, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72,
|
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62,
|
||||||
0x6f, 0x74, 0x6f, 0x33,
|
0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2d, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e,
|
||||||
|
0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x18, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f,
|
||||||
|
0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||||
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -19,8 +19,9 @@ message Fallback {
|
|||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
repeated xray.common.protocol.User clients = 1;
|
repeated xray.common.protocol.User clients = 1;
|
||||||
// Decryption settings. Only applies to server side, and only accepts "none"
|
repeated Fallback fallbacks = 2;
|
||||||
// for now.
|
|
||||||
string decryption = 2;
|
string decryption = 3;
|
||||||
repeated Fallback fallbacks = 3;
|
uint32 xorMode = 4;
|
||||||
|
uint32 minutes = 5;
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
gotls "crypto/tls"
|
gotls "crypto/tls"
|
||||||
|
"encoding/base64"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -29,6 +30,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"github.com/xtls/xray-core/proxy/vless"
|
"github.com/xtls/xray-core/proxy/vless"
|
||||||
"github.com/xtls/xray-core/proxy/vless/encoding"
|
"github.com/xtls/xray-core/proxy/vless/encoding"
|
||||||
|
"github.com/xtls/xray-core/proxy/vless/encryption"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
@@ -67,6 +69,7 @@ type Handler struct {
|
|||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
validator vless.Validator
|
validator vless.Validator
|
||||||
dns dns.Client
|
dns dns.Client
|
||||||
|
decryption *encryption.ServerInstance
|
||||||
fallbacks map[string]map[string]map[string]*Fallback // or nil
|
fallbacks map[string]map[string]map[string]*Fallback // or nil
|
||||||
// regexps map[string]*regexp.Regexp // or nil
|
// regexps map[string]*regexp.Regexp // or nil
|
||||||
}
|
}
|
||||||
@@ -81,6 +84,15 @@ func New(ctx context.Context, config *Config, dc dns.Client, validator vless.Val
|
|||||||
validator: validator,
|
validator: validator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s := strings.Split(config.Decryption, "."); len(s) == 2 {
|
||||||
|
nfsDKeySeed, _ := base64.RawURLEncoding.DecodeString(s[0])
|
||||||
|
xorSKeyBytes, _ := base64.RawURLEncoding.DecodeString(s[1])
|
||||||
|
handler.decryption = &encryption.ServerInstance{}
|
||||||
|
if err := handler.decryption.Init(nfsDKeySeed, xorSKeyBytes, config.XorMode, config.Minutes); err != nil {
|
||||||
|
return nil, errors.New("failed to use mlkem768seed").Base(err).AtError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if config.Fallbacks != nil {
|
if config.Fallbacks != nil {
|
||||||
handler.fallbacks = make(map[string]map[string]map[string]*Fallback)
|
handler.fallbacks = make(map[string]map[string]map[string]*Fallback)
|
||||||
// handler.regexps = make(map[string]*regexp.Regexp)
|
// handler.regexps = make(map[string]*regexp.Regexp)
|
||||||
@@ -159,6 +171,9 @@ func isMuxAndNotXUDP(request *protocol.RequestHeader, first *buf.Buffer) bool {
|
|||||||
|
|
||||||
// Close implements common.Closable.Close().
|
// Close implements common.Closable.Close().
|
||||||
func (h *Handler) Close() error {
|
func (h *Handler) Close() error {
|
||||||
|
if h.decryption != nil {
|
||||||
|
h.decryption.Close()
|
||||||
|
}
|
||||||
return errors.Combine(common.Close(h.validator))
|
return errors.Combine(common.Close(h.validator))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +214,14 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
iConn = statConn.Connection
|
iConn = statConn.Connection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if h.decryption != nil {
|
||||||
|
var err error
|
||||||
|
connection, err = h.decryption.Handshake(connection)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("ML-KEM-768 handshake failed").Base(err).AtInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sessionPolicy := h.policyManager.ForLevel(0)
|
sessionPolicy := h.policyManager.ForLevel(0)
|
||||||
if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
|
if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
|
||||||
return errors.New("unable to set read deadline").Base(err).AtWarning()
|
return errors.New("unable to set read deadline").Base(err).AtWarning()
|
||||||
@@ -462,6 +485,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
// Flow: requestAddons.Flow,
|
// Flow: requestAddons.Flow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var peerCache *[]byte
|
||||||
var input *bytes.Reader
|
var input *bytes.Reader
|
||||||
var rawInput *bytes.Buffer
|
var rawInput *bytes.Buffer
|
||||||
switch requestAddons.Flow {
|
switch requestAddons.Flow {
|
||||||
@@ -474,6 +498,13 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
case protocol.RequestCommandMux:
|
case protocol.RequestCommandMux:
|
||||||
fallthrough // we will break Mux connections that contain TCP requests
|
fallthrough // we will break Mux connections that contain TCP requests
|
||||||
case protocol.RequestCommandTCP:
|
case protocol.RequestCommandTCP:
|
||||||
|
if serverConn, ok := connection.(*encryption.ServerConn); ok {
|
||||||
|
peerCache = &serverConn.PeerCache
|
||||||
|
if xorConn, ok := serverConn.Conn.(*encryption.XorConn); (ok && !xorConn.Divide) || !proxy.IsRAWTransport(iConn) {
|
||||||
|
inbound.CanSpliceCopy = 3 // full-random xorConn / non-RAW transport can not use Linux Splice
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
var t reflect.Type
|
var t reflect.Type
|
||||||
var p uintptr
|
var p uintptr
|
||||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||||
@@ -542,7 +573,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
|
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
|
||||||
clientReader = proxy.NewVisionReader(clientReader, trafficState, true, ctx1)
|
clientReader = proxy.NewVisionReader(clientReader, trafficState, true, ctx1)
|
||||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, true, ctx1)
|
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, peerCache, input, rawInput, trafficState, nil, true, ctx1)
|
||||||
} else {
|
} else {
|
||||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
|
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
|
||||||
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
||||||
|
@@ -4,7 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
gotls "crypto/tls"
|
gotls "crypto/tls"
|
||||||
|
"encoding/base64"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
@@ -24,6 +26,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"github.com/xtls/xray-core/proxy/vless"
|
"github.com/xtls/xray-core/proxy/vless"
|
||||||
"github.com/xtls/xray-core/proxy/vless/encoding"
|
"github.com/xtls/xray-core/proxy/vless/encoding"
|
||||||
|
"github.com/xtls/xray-core/proxy/vless/encryption"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
"github.com/xtls/xray-core/transport/internet/reality"
|
||||||
@@ -43,6 +46,7 @@ type Handler struct {
|
|||||||
serverPicker protocol.ServerPicker
|
serverPicker protocol.ServerPicker
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
cone bool
|
cone bool
|
||||||
|
encryption *encryption.ClientInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new VLess outbound handler.
|
// New creates a new VLess outbound handler.
|
||||||
@@ -64,6 +68,16 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
|||||||
cone: ctx.Value("cone").(bool),
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a := handler.serverPicker.PickServer().PickUser().Account.(*vless.MemoryAccount)
|
||||||
|
if s := strings.Split(a.Encryption, "."); len(s) == 2 {
|
||||||
|
nfsEKeyBytes, _ := base64.RawURLEncoding.DecodeString(s[0])
|
||||||
|
xorPKeyBytes, _ := base64.RawURLEncoding.DecodeString(s[1])
|
||||||
|
handler.encryption = &encryption.ClientInstance{}
|
||||||
|
if err := handler.encryption.Init(nfsEKeyBytes, xorPKeyBytes, a.XorMode, a.Minutes); err != nil {
|
||||||
|
return nil, errors.New("failed to use mlkem768client").Base(err).AtError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +112,14 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
target := ob.Target
|
target := ob.Target
|
||||||
errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination().NetAddr())
|
errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination().NetAddr())
|
||||||
|
|
||||||
|
if h.encryption != nil {
|
||||||
|
var err error
|
||||||
|
conn, err = h.encryption.Handshake(conn)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("ML-KEM-768 handshake failed").Base(err).AtInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
command := protocol.RequestCommandTCP
|
command := protocol.RequestCommandTCP
|
||||||
if target.Network == net.Network_UDP {
|
if target.Network == net.Network_UDP {
|
||||||
command = protocol.RequestCommandUDP
|
command = protocol.RequestCommandUDP
|
||||||
@@ -120,6 +142,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
Flow: account.Flow,
|
Flow: account.Flow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var peerCache *[]byte
|
||||||
var input *bytes.Reader
|
var input *bytes.Reader
|
||||||
var rawInput *bytes.Buffer
|
var rawInput *bytes.Buffer
|
||||||
allowUDP443 := false
|
allowUDP443 := false
|
||||||
@@ -138,6 +161,13 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
case protocol.RequestCommandMux:
|
case protocol.RequestCommandMux:
|
||||||
fallthrough // let server break Mux connections that contain TCP requests
|
fallthrough // let server break Mux connections that contain TCP requests
|
||||||
case protocol.RequestCommandTCP:
|
case protocol.RequestCommandTCP:
|
||||||
|
if clientConn, ok := conn.(*encryption.ClientConn); ok {
|
||||||
|
peerCache = &clientConn.PeerCache
|
||||||
|
if xorConn, ok := clientConn.Conn.(*encryption.XorConn); (ok && !xorConn.Divide) || !proxy.IsRAWTransport(iConn) {
|
||||||
|
ob.CanSpliceCopy = 3 // full-random xorConn / non-RAW transport can not use Linux Splice
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
var t reflect.Type
|
var t reflect.Type
|
||||||
var p uintptr
|
var p uintptr
|
||||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||||
@@ -272,7 +302,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
}
|
}
|
||||||
|
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, input, rawInput, trafficState, ob, false, ctx)
|
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, peerCache, input, rawInput, trafficState, ob, false, ctx)
|
||||||
} else {
|
} else {
|
||||||
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
|
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
|
||||||
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
||||||
|
Reference in New Issue
Block a user