github.com/v2fly/v2ray-core/v4@v4.45.2/proxy/mtproto/server.go (about)

     1  //go:build !confonly
     2  // +build !confonly
     3  
     4  package mtproto
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"time"
    10  
    11  	core "github.com/v2fly/v2ray-core/v4"
    12  	"github.com/v2fly/v2ray-core/v4/common"
    13  	"github.com/v2fly/v2ray-core/v4/common/buf"
    14  	"github.com/v2fly/v2ray-core/v4/common/crypto"
    15  	"github.com/v2fly/v2ray-core/v4/common/net"
    16  	"github.com/v2fly/v2ray-core/v4/common/protocol"
    17  	"github.com/v2fly/v2ray-core/v4/common/session"
    18  	"github.com/v2fly/v2ray-core/v4/common/signal"
    19  	"github.com/v2fly/v2ray-core/v4/common/task"
    20  	"github.com/v2fly/v2ray-core/v4/features/policy"
    21  	"github.com/v2fly/v2ray-core/v4/features/routing"
    22  	"github.com/v2fly/v2ray-core/v4/transport/internet"
    23  )
    24  
    25  var dcList = []net.Address{
    26  	net.ParseAddress("149.154.175.50"),
    27  	net.ParseAddress("149.154.167.51"),
    28  	net.ParseAddress("149.154.175.100"),
    29  	net.ParseAddress("149.154.167.91"),
    30  	net.ParseAddress("149.154.171.5"),
    31  }
    32  
    33  type Server struct {
    34  	user    *protocol.User
    35  	account *Account
    36  	policy  policy.Manager
    37  }
    38  
    39  func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
    40  	if len(config.User) == 0 {
    41  		return nil, newError("no user configured.")
    42  	}
    43  
    44  	user := config.User[0]
    45  	rawAccount, err := config.User[0].GetTypedAccount()
    46  	if err != nil {
    47  		return nil, newError("invalid account").Base(err)
    48  	}
    49  	account, ok := rawAccount.(*Account)
    50  	if !ok {
    51  		return nil, newError("not a MTProto account")
    52  	}
    53  
    54  	v := core.MustFromContext(ctx)
    55  
    56  	return &Server{
    57  		user:    user,
    58  		account: account,
    59  		policy:  v.GetFeature(policy.ManagerType()).(policy.Manager),
    60  	}, nil
    61  }
    62  
    63  func (s *Server) Network() []net.Network {
    64  	return []net.Network{net.Network_TCP}
    65  }
    66  
    67  var (
    68  	ctype1 = []byte{0xef, 0xef, 0xef, 0xef}
    69  	ctype2 = []byte{0xee, 0xee, 0xee, 0xee}
    70  )
    71  
    72  func isValidConnectionType(c [4]byte) bool {
    73  	if bytes.Equal(c[:], ctype1) {
    74  		return true
    75  	}
    76  	if bytes.Equal(c[:], ctype2) {
    77  		return true
    78  	}
    79  	return false
    80  }
    81  
    82  func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error {
    83  	sPolicy := s.policy.ForLevel(s.user.Level)
    84  
    85  	if err := conn.SetDeadline(time.Now().Add(sPolicy.Timeouts.Handshake)); err != nil {
    86  		newError("failed to set deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))
    87  	}
    88  	auth, err := ReadAuthentication(conn)
    89  	if err != nil {
    90  		return newError("failed to read authentication header").Base(err)
    91  	}
    92  	defer putAuthenticationObject(auth)
    93  
    94  	if err := conn.SetDeadline(time.Time{}); err != nil {
    95  		newError("failed to clear deadline").Base(err).WriteToLog(session.ExportIDToError(ctx))
    96  	}
    97  
    98  	auth.ApplySecret(s.account.Secret)
    99  
   100  	decryptor := crypto.NewAesCTRStream(auth.DecodingKey[:], auth.DecodingNonce[:])
   101  	decryptor.XORKeyStream(auth.Header[:], auth.Header[:])
   102  
   103  	ct := auth.ConnectionType()
   104  	if !isValidConnectionType(ct) {
   105  		return newError("invalid connection type: ", ct)
   106  	}
   107  
   108  	dcID := auth.DataCenterID()
   109  	if dcID >= uint16(len(dcList)) {
   110  		return newError("invalid datacenter id: ", dcID)
   111  	}
   112  
   113  	dest := net.Destination{
   114  		Network: net.Network_TCP,
   115  		Address: dcList[dcID],
   116  		Port:    net.Port(443),
   117  	}
   118  
   119  	ctx, cancel := context.WithCancel(ctx)
   120  	timer := signal.CancelAfterInactivity(ctx, cancel, sPolicy.Timeouts.ConnectionIdle)
   121  	ctx = policy.ContextWithBufferPolicy(ctx, sPolicy.Buffer)
   122  
   123  	sc := SessionContext{
   124  		ConnectionType: ct,
   125  		DataCenterID:   dcID,
   126  	}
   127  	ctx = ContextWithSessionContext(ctx, sc)
   128  
   129  	link, err := dispatcher.Dispatch(ctx, dest)
   130  	if err != nil {
   131  		return newError("failed to dispatch request to: ", dest).Base(err)
   132  	}
   133  
   134  	request := func() error {
   135  		defer timer.SetTimeout(sPolicy.Timeouts.DownlinkOnly)
   136  
   137  		reader := buf.NewReader(crypto.NewCryptionReader(decryptor, conn))
   138  		return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
   139  	}
   140  
   141  	response := func() error {
   142  		defer timer.SetTimeout(sPolicy.Timeouts.UplinkOnly)
   143  
   144  		encryptor := crypto.NewAesCTRStream(auth.EncodingKey[:], auth.EncodingNonce[:])
   145  		writer := buf.NewWriter(crypto.NewCryptionWriter(encryptor, conn))
   146  		return buf.Copy(link.Reader, writer, buf.UpdateActivity(timer))
   147  	}
   148  
   149  	responseDoneAndCloseWriter := task.OnSuccess(response, task.Close(link.Writer))
   150  	if err := task.Run(ctx, request, responseDoneAndCloseWriter); err != nil {
   151  		common.Interrupt(link.Reader)
   152  		common.Interrupt(link.Writer)
   153  		return newError("connection ends").Base(err)
   154  	}
   155  
   156  	return nil
   157  }
   158  
   159  func init() {
   160  	common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   161  		return NewServer(ctx, config.(*ServerConfig))
   162  	}))
   163  }