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 }