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