mirror of
https://github.com/v2fly/v2ray-core.git
synced 2026-08-04 14:10:54 -04:00
finish rtt enrollment
This commit is contained in:
committed by
Xiaokang Wang (Shelikhoo)
parent
85fd420745
commit
9aeffbef6b
@@ -88,3 +88,7 @@ type ConnectionEnrollmentConfirmationServerInstanceConfig struct {
|
||||
type ConnectionEnrollmentConfirmationServerInstanceConfigReceiver interface {
|
||||
OnConnectionEnrollmentConfirmationServerInstanceConfigReady(ConnectionEnrollmentConfirmationServerInstanceConfig)
|
||||
}
|
||||
|
||||
type ConnectionLoopbackPrevention struct {
|
||||
Key string
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package mirrorcommon
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror"
|
||||
)
|
||||
|
||||
func SetLoopbackProtectionFlagForContext(ctx context.Context, enrollmentID []byte) context.Context {
|
||||
loopbackProtectionKey := tlsmirror.ConnectionLoopbackPrevention{Key: string(enrollmentID)}
|
||||
return context.WithValue(ctx, loopbackProtectionKey, true)
|
||||
}
|
||||
|
||||
func IsLoopbackProtectionEnabled(ctx context.Context, enrollmentID []byte) bool {
|
||||
loopbackProtectionKey := tlsmirror.ConnectionLoopbackPrevention{Key: string(enrollmentID)}
|
||||
val := ctx.Value(loopbackProtectionKey)
|
||||
enabled, ok := val.(bool)
|
||||
return ok && enabled
|
||||
}
|
||||
@@ -4,11 +4,13 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/environment"
|
||||
"github.com/v2fly/v2ray-core/v5/common/environment/envctx"
|
||||
v2net "github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/serial"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror/mirrorcommon"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror/mirrorenrollment/httpenrollmentconfirmation"
|
||||
)
|
||||
|
||||
@@ -78,7 +80,9 @@ func (c *EnrollmentConfirmationClient) init() error {
|
||||
return nil, newError("failed to parse destination address").Base(err).AtError()
|
||||
}
|
||||
dest.Network = v2net.Network_TCP
|
||||
return dialer(c.ctx, dest, c.config.PrimaryEgressOutbound)
|
||||
|
||||
loopbackProtectedCtx := mirrorcommon.SetLoopbackProtectionFlagForContext(c.ctx, c.serverIdentity)
|
||||
return dialer(loopbackProtectedCtx, dest, c.config.PrimaryEgressOutbound)
|
||||
}, c.serverIdentity)
|
||||
if err != nil {
|
||||
return newError("failed to create HTTP round tripper for enrollment confirmation").Base(err).AtError()
|
||||
@@ -93,7 +97,14 @@ func (c *EnrollmentConfirmationClient) init() error {
|
||||
if err != nil {
|
||||
return newError("failed to get instance of bootstrap enrollment confirmation config").Base(err).AtError()
|
||||
}
|
||||
enrollmentConfirmation, ok := enrollment.(tlsmirror.ConnectionEnrollmentConfirmation)
|
||||
|
||||
loopbackProtectedCtx := mirrorcommon.SetLoopbackProtectionFlagForContext(c.ctx, c.serverIdentity)
|
||||
enrollmentInst, err := common.CreateObject(loopbackProtectedCtx, enrollment)
|
||||
if err != nil {
|
||||
return newError("failed to create bootstrap enrollment confirmation config").Base(err).AtError()
|
||||
}
|
||||
|
||||
enrollmentConfirmation, ok := enrollmentInst.(tlsmirror.ConnectionEnrollmentConfirmation)
|
||||
if !ok {
|
||||
return newError("bootstrap enrollment confirmation config is not a valid ConnectionEnrollmentConfirmation")
|
||||
|
||||
|
||||
@@ -37,10 +37,14 @@ func (c *client) VerifyConnectionEnrollment(req *tlsmirror.EnrollmentConfirmatio
|
||||
return nil, newError("failed to create HTTP request").Base(err)
|
||||
}
|
||||
httpResp, err := c.httpRoundTripper.RoundTrip(httpReq)
|
||||
defer func() {
|
||||
if httpResp != nil && httpResp.Body != nil {
|
||||
httpResp.Body.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return nil, newError("failed to send HTTP request").Base(err)
|
||||
}
|
||||
defer httpResp.Body.Close()
|
||||
if httpResp.StatusCode != http.StatusOK {
|
||||
return nil, newError("unexpected HTTP response status: ", httpResp.StatusCode)
|
||||
}
|
||||
|
||||
+4
-2
@@ -52,17 +52,19 @@ func (c *clientRoundtripper) RoundTrip(request *http.Request) (*http.Response, e
|
||||
resp, err := c.currentConn.RoundTrip(request)
|
||||
if err != nil {
|
||||
defer func() {
|
||||
c.currentConnLock.RUnlock()
|
||||
c.currentConnLock.Lock()
|
||||
defer c.currentConnLock.Unlock()
|
||||
if c.currentConn != nil {
|
||||
c.currentConnInnerConn.Close()
|
||||
c.currentConnInnerConn = nil
|
||||
c.currentConn = nil
|
||||
}
|
||||
c.currentConnLock.Unlock()
|
||||
c.currentConnLock.RLock()
|
||||
}()
|
||||
return nil, newError("unable to roundtrip for enrollment verification").Base(err)
|
||||
}
|
||||
return resp, err
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *clientRoundtripper) createNewConnection() error {
|
||||
|
||||
+6
-1
@@ -26,11 +26,16 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
return nil, newError("config cannot be nil")
|
||||
}
|
||||
|
||||
rttClientI, err := serial.GetInstanceOf(config.RoundTripperClient)
|
||||
rttClientConfig, err := serial.GetInstanceOf(config.RoundTripperClient)
|
||||
if err != nil {
|
||||
return nil, newError("failed to get instance of RoundTripperClient").Base(err)
|
||||
}
|
||||
|
||||
rttClientI, err := common.CreateObject(ctx, rttClientConfig)
|
||||
if err != nil {
|
||||
return nil, newError("failed to create RoundTripperClient").Base(err)
|
||||
}
|
||||
|
||||
rttClient, ok := rttClientI.(request.RoundTripperClient)
|
||||
if !ok {
|
||||
return nil, newError("RoundTripperClient is not a valid request.RoundTripperClient")
|
||||
|
||||
+39
-3
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common/serial"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
@@ -14,12 +15,16 @@ import (
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror"
|
||||
)
|
||||
|
||||
func NewServer(ctx context.Context, config *ServerConfig) *Server {
|
||||
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||
s := &Server{
|
||||
ctx: ctx,
|
||||
config: config,
|
||||
}
|
||||
return s
|
||||
|
||||
if err := s.init(); err != nil {
|
||||
return nil, newError("failed to initialize RoundTripperEnrollmentConfirmation server").Base(err).AtError()
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
@@ -29,6 +34,10 @@ type Server struct {
|
||||
rttServer request.RoundTripperServer
|
||||
}
|
||||
|
||||
func (s *Server) OnConnectionEnrollmentConfirmationServerInstanceConfigReady(config tlsmirror.ConnectionEnrollmentConfirmationServerInstanceConfig) {
|
||||
s.enrollmentProcessor = config.EnrollmentProcessor
|
||||
}
|
||||
|
||||
func (s *Server) Listen(ctx context.Context) (v2net.Listener, error) {
|
||||
transportEnvironment := envctx.EnvironmentFromContext(s.ctx).(environment.TransportEnvironment)
|
||||
listener := transportEnvironment.Listener()
|
||||
@@ -75,8 +84,35 @@ func (s *Server) AutoImplListener() request.Listener {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Server) init() error {
|
||||
if s.config == nil {
|
||||
return newError("nil ServerConfig")
|
||||
}
|
||||
if s.config.RoundTripperServer == nil {
|
||||
return newError("nil RoundTripperServer in ServerConfig")
|
||||
}
|
||||
RoundTripperServerConfig, err := serial.GetInstanceOf(s.config.RoundTripperServer)
|
||||
if err != nil {
|
||||
return newError("failed to get instance of RoundTripperServer").Base(err).AtError()
|
||||
}
|
||||
RoundTripperServerObj, err := common.CreateObject(s.ctx, RoundTripperServerConfig)
|
||||
if err != nil {
|
||||
return newError("failed to create RoundTripperServer").Base(err).AtError()
|
||||
}
|
||||
RoundTripperServerTyped, ok := RoundTripperServerObj.(request.RoundTripperServer)
|
||||
if !ok {
|
||||
return newError("RoundTripperServer is not a valid request.RoundTripperServer")
|
||||
}
|
||||
s.rttServer = RoundTripperServerTyped
|
||||
s.rttServer.OnTransportServerAssemblyReady(s)
|
||||
if err := s.rttServer.Start(); err != nil {
|
||||
return newError("failed to start RoundTripperServer").Base(err).AtError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewServer(ctx, config.(*ServerConfig)), nil
|
||||
return NewServer(ctx, config.(*ServerConfig))
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/serial"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror/mirrorenrollment/httpenrollmentconfirmation"
|
||||
@@ -36,6 +37,10 @@ func NewEnrollmentConfirmationServer(ctx context.Context, config *Config, enroll
|
||||
primaryIngressConnectionHandler: primaryIngressConnectionHandler,
|
||||
}
|
||||
|
||||
if err = s.init(); err != nil {
|
||||
return nil, newError("failed to initialize enrollment confirmation server").Base(err).AtError()
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -59,21 +64,25 @@ func (s *EnrollmentConfirmationServer) HandlePrimaryIngressConnection(ctx contex
|
||||
}
|
||||
|
||||
func (s *EnrollmentConfirmationServer) init() error {
|
||||
for _, handler := range s.config.BootstrapEgressConfig {
|
||||
for _, handler := range s.config.BootstrapIngressConfig {
|
||||
bootstrapEnrollmentHandler, err := serial.GetInstanceOf(handler)
|
||||
if err != nil {
|
||||
return newError("failed to get instance of bootstrap enrollment handler").Base(err).AtError()
|
||||
}
|
||||
bootstrapEnrollmentHandlerTyped, ok := bootstrapEnrollmentHandler.(tlsmirror.ConnectionEnrollmentConfirmationServerInstanceConfigReceiver)
|
||||
bootstrapEnrollmentHandlerObj, err := common.CreateObject(s.ctx, bootstrapEnrollmentHandler)
|
||||
if err != nil {
|
||||
return newError("failed to create bootstrap enrollment handler").Base(err).AtError()
|
||||
}
|
||||
bootstrapEnrollmentHandlerObjTyped, ok := bootstrapEnrollmentHandlerObj.(tlsmirror.ConnectionEnrollmentConfirmationServerInstanceConfigReceiver)
|
||||
if !ok {
|
||||
return newError("bootstrap enrollment handler is not a valid ConnectionEnrollmentConfirmationServerInstanceConfigReceiver")
|
||||
}
|
||||
|
||||
bootstrapEnrollmentHandlerTyped.OnConnectionEnrollmentConfirmationServerInstanceConfigReady(
|
||||
bootstrapEnrollmentHandlerObjTyped.OnConnectionEnrollmentConfirmationServerInstanceConfigReady(
|
||||
tlsmirror.ConnectionEnrollmentConfirmationServerInstanceConfig{
|
||||
EnrollmentProcessor: s.enrollmentProcessor,
|
||||
})
|
||||
s.bootstrapIngressConnectionHandlers = append(s.bootstrapIngressConnectionHandlers, bootstrapEnrollmentHandlerTyped)
|
||||
s.bootstrapIngressConnectionHandlers = append(s.bootstrapIngressConnectionHandlers, bootstrapEnrollmentHandlerObjTyped)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror/mirrorcommon"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
@@ -58,6 +59,8 @@ type persistentMirrorTLSDialer struct {
|
||||
explicitNonceCiphersuiteLookup *ciphersuiteLookuper
|
||||
|
||||
enrollmentConfirmationClient *mirrorenrollment.EnrollmentConfirmationClient
|
||||
|
||||
enrollmentServerIdentifier []byte
|
||||
}
|
||||
|
||||
func (d *persistentMirrorTLSDialer) init(ctx context.Context, config *Config) error {
|
||||
@@ -147,6 +150,7 @@ func (d *persistentMirrorTLSDialer) init(ctx context.Context, config *Config) er
|
||||
if err != nil {
|
||||
return newError("failed to derive enrollment server identifier").Base(err).AtError()
|
||||
}
|
||||
d.enrollmentServerIdentifier = enrollmentServerIdentifier
|
||||
d.enrollmentConfirmationClient, err = mirrorenrollment.NewEnrollmentConfirmationClient(d.ctx, d.config.ConnectionEnrolment, enrollmentServerIdentifier)
|
||||
if err != nil {
|
||||
return newError("failed to create enrollment confirmation client").Base(err).AtError()
|
||||
@@ -259,6 +263,12 @@ func (d *persistentMirrorTLSDialer) handleIncomingReadyConnection(conn internet.
|
||||
func (d *persistentMirrorTLSDialer) Dial(ctx context.Context,
|
||||
dest net.Destination, settings *internet.MemoryStreamConfig,
|
||||
) (internet.Connection, error) {
|
||||
if d.enrollmentServerIdentifier != nil && len(d.enrollmentServerIdentifier) > 0 {
|
||||
if mirrorcommon.IsLoopbackProtectionEnabled(ctx, d.enrollmentServerIdentifier) {
|
||||
return nil, newError("loopback protection: refusing to dial to self")
|
||||
}
|
||||
}
|
||||
|
||||
var recvConn net.Conn
|
||||
select {
|
||||
case conn := <-d.incomingConnections:
|
||||
|
||||
Reference in New Issue
Block a user