func (server *SocksServer) handleSocks4(reader io.Reader, writer io.Writer, auth protocol.Socks4AuthenticationRequest) error { result := protocol.Socks4RequestGranted if auth.Command == protocol.CmdBind { result = protocol.Socks4RequestRejected } socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth.Port, auth.IP[:]) responseBuffer := alloc.NewSmallBuffer().Clear() socks4Response.Write(responseBuffer) writer.Write(responseBuffer.Value) responseBuffer.Release() if result == protocol.Socks4RequestRejected { log.Warning("Unsupported socks 4 command %d", auth.Command) return UnsupportedSocksCommand } dest := v2net.NewTCPDestination(v2net.IPAddress(auth.IP[:], auth.Port)) data, err := v2net.ReadFrom(reader, nil) if err != nil { return err } packet := v2net.NewPacket(dest, data, true) server.transport(reader, writer, packet) return nil }
func (this *Server) handleConnection(conn internet.Connection) { defer conn.Close() timedReader := v2net.NewTimeOutReader(this.config.Timeout, conn) reader := bufio.NewReaderSize(timedReader, 2048) request, err := http.ReadRequest(reader) if err != nil { if err != io.EOF { log.Warning("HTTP: Failed to read http request: ", err) } return } log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("HTTP: Malformed proxy host (", host, "): ", err) return } log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "") if strings.ToUpper(request.Method) == "CONNECT" { this.handleConnect(request, dest, reader, conn) } else { this.handlePlainHTTP(request, dest, reader, conn) } }
func (handler *VMessInboundHandler) AcceptPackets(conn *net.UDPConn) { for { buffer := make([]byte, bufferSize) nBytes, addr, err := conn.ReadFromUDP(buffer) if err != nil { log.Error("VMessIn failed to read UDP packets: %v", err) continue } reader := bytes.NewReader(buffer[:nBytes]) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(reader) if err != nil { log.Warning("VMessIn: Invalid request from (%s): %v", addr.String(), err) continue } cryptReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader) if err != nil { log.Error("VMessIn: Failed to create decrypt reader: %v", err) continue } data := make([]byte, bufferSize) nBytes, err = cryptReader.Read(data) if err != nil { log.Warning("VMessIn: Unable to decrypt data: %v", err) continue } packet := v2net.NewPacket(request.Destination(), data[:nBytes], false) go handler.handlePacket(conn, request, packet, addr) } }
func (this *VMessOutboundHandler) handleCommand(dest v2net.Destination, cmdId byte, data []byte) { if len(data) < 4 { return } fnv1hash := fnv.New32a() fnv1hash.Write(data[4:]) actualHashValue := fnv1hash.Sum32() expectedHashValue := serial.BytesLiteral(data[:4]).Uint32Value() if actualHashValue != expectedHashValue { return } data = data[4:] cmd, err := command.CreateResponseCommand(cmdId) if err != nil { log.Warning("VMessOut: Unknown response command (", cmdId, "): ", err) return } if err := cmd.Unmarshal(data); err != nil { log.Warning("VMessOut: Failed to parse response command: ", err) return } switch typedCommand := cmd.(type) { case *command.SwitchAccount: if typedCommand.Host == nil { typedCommand.Host = dest.Address() } this.handleSwitchAccount(typedCommand) default: } }
func (this *HttpProxyServer) handleConnection(conn *hub.TCPConn) { defer conn.Close() reader := bufio.NewReader(conn) request, err := http.ReadRequest(reader) if err != nil { log.Warning("Failed to read http request: ", err) return } log.Info("Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]") defaultPort := v2net.Port(80) if strings.ToLower(request.URL.Scheme) == "https" { defaultPort = v2net.Port(443) } host := request.Host if len(host) == 0 { host = request.URL.Host } dest, err := parseHost(host, defaultPort) if err != nil { log.Warning("Malformed proxy host (", host, "): ", err) return } if strings.ToUpper(request.Method) == "CONNECT" { this.handleConnect(request, dest, reader, conn) } else { this.handlePlainHTTP(request, dest, reader, conn) } }
func ReadVMessUDP(buffer []byte, userset user.UserSet) (*VMessUDP, error) { userHash := buffer[:user.IDBytesLen] userId, timeSec, valid := userset.GetUser(userHash) if !valid { return nil, errors.NewAuthenticationError(userHash) } buffer = buffer[user.IDBytesLen:] aesCipher, err := aes.NewCipher(userId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec)) aesStream.XORKeyStream(buffer, buffer) fnvHash := binary.BigEndian.Uint32(buffer[:4]) fnv1a := fnv.New32a() fnv1a.Write(buffer[4:]) fnvHashActual := fnv1a.Sum32() if fnvHash != fnvHashActual { log.Warning("Unexpected fhv hash %d, should be %d", fnvHashActual, fnvHash) return nil, errors.NewCorruptedPacketError() } buffer = buffer[4:] vmess := &VMessUDP{ user: *userId, version: buffer[0], token: binary.BigEndian.Uint16(buffer[1:3]), } // buffer[3] is reserved port := binary.BigEndian.Uint16(buffer[4:6]) addrType := buffer[6] var address v2net.Address switch addrType { case addrTypeIPv4: address = v2net.IPAddress(buffer[7:11], port) buffer = buffer[11:] case addrTypeIPv6: address = v2net.IPAddress(buffer[7:23], port) buffer = buffer[23:] case addrTypeDomain: domainLength := buffer[7] domain := string(buffer[8 : 8+domainLength]) address = v2net.DomainAddress(domain, port) buffer = buffer[8+domainLength:] default: log.Warning("Unexpected address type %d", addrType) return nil, errors.NewCorruptedPacketError() } vmess.address = address vmess.data = buffer return vmess, nil }
func handleResponse(conn net.Conn, request *protocol.VMessRequest, output chan<- []byte, finish *sync.Mutex, isUDP bool) { defer finish.Unlock() defer close(output) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn) if err != nil { log.Error("VMessOut: Failed to create decrypt reader: %v", err) return } buffer := make([]byte, 2*1024) nBytes, err := decryptResponseReader.Read(buffer) if err != nil { //log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", nBytes, err) return } if !bytes.Equal(buffer[:4], request.ResponseHeader[:]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } output <- buffer[4:nBytes] if !isUDP { v2net.ReaderToChan(output, decryptResponseReader) } return }
func ListenTCP(address v2net.Address, port v2net.Port, callback ConnectionHandler, settings *StreamSettings) (*TCPHub, error) { var listener Listener var err error switch { case settings.IsCapableOf(StreamConnectionTypeTCP): listener, err = TCPListenFunc(address, port) case settings.IsCapableOf(StreamConnectionTypeKCP): listener, err = KCPListenFunc(address, port) case settings.IsCapableOf(StreamConnectionTypeRawTCP): listener, err = RawTCPListenFunc(address, port) default: log.Error("Internet|Listener: Unknown stream type: ", settings.Type) err = ErrUnsupportedStreamType } if err != nil { log.Warning("Internet|Listener: Failed to listen on ", address, ":", port) return nil, err } var tlsConfig *tls.Config if settings.Security == StreamSecurityTypeTLS { tlsConfig = settings.TLSSettings.GetTLSConfig() } hub := &TCPHub{ listener: listener, connCallback: callback, tlsConfig: tlsConfig, } go hub.start() return hub, nil }
func handleResponse(conn *net.TCPConn, request *protocol.VMessRequest, output chan<- []byte, finish *sync.Mutex) { defer finish.Unlock() defer close(output) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn) if err != nil { log.Error("VMessOut: Failed to create decrypt reader: %v", err) return } response := protocol.VMessResponse{} nBytes, err := decryptResponseReader.Read(response[:]) if err != nil { log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", nBytes, err) log.Error(InfoTimeNotSync) return } if !bytes.Equal(response[:], request.ResponseHeader[:]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } v2net.ReaderToChan(output, decryptResponseReader) return }
func (this *Server) handleConnection(connection internet.Connection) { defer connection.Close() timedReader := v2net.NewTimeOutReader(this.config.Timeout, connection) reader := v2io.NewBufferedReader(timedReader) defer reader.Release() writer := v2io.NewBufferedWriter(connection) defer writer.Release() auth, auth4, err := protocol.ReadAuthentication(reader) if err != nil && err != protocol.Socks4Downgrade { if err != io.EOF { log.Warning("Socks: failed to read authentication: ", err) } return } clientAddr := connection.RemoteAddr().String() if err != nil && err == protocol.Socks4Downgrade { this.handleSocks4(clientAddr, reader, writer, auth4) } else { this.handleSocks5(clientAddr, reader, writer, auth) } }
func (this *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.ResponseHeader, error) { aesStream := crypto.NewAesDecryptionStream(this.responseBodyKey, this.responseBodyIV) this.responseReader = crypto.NewCryptionReader(aesStream, reader) buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err := io.ReadFull(this.responseReader, buffer.Value[:4]) if err != nil { log.Error("Raw: Failed to read response header: ", err) return nil, err } if buffer.Value[0] != this.responseHeader { log.Warning("Raw: Unexpected response header. Expecting %d, but actually %d", this.responseHeader, buffer.Value[0]) return nil, transport.ErrorCorruptedPacket } header := new(protocol.ResponseHeader) if buffer.Value[2] != 0 { cmdId := buffer.Value[2] dataLen := int(buffer.Value[3]) _, err := io.ReadFull(this.responseReader, buffer.Value[:dataLen]) if err != nil { log.Error("Raw: Failed to read response command: ", err) return nil, err } data := buffer.Value[:dataLen] command, err := UnmarshalCommand(cmdId, data) header.Command = command } return header, nil }
func (this *VMessOutboundHandler) handleResponse(session *raw.ClientSession, conn net.Conn, request *proto.RequestHeader, dest v2net.Destination, output chan<- *alloc.Buffer, finish *sync.Mutex) { defer finish.Unlock() defer close(output) reader := v2io.NewBufferedReader(conn) header, err := session.DecodeResponseHeader(reader) if err != nil { log.Warning("VMessOut: Failed to read response: ", err) return } go this.handleCommand(dest, header.Command) reader.SetCached(false) decryptReader := session.DecodeResponseBody(conn) var bodyReader v2io.Reader if request.Option.IsChunkStream() { bodyReader = vmessio.NewAuthChunkReader(decryptReader) } else { bodyReader = v2io.NewAdaptiveReader(decryptReader) } v2io.ReaderToChan(output, bodyReader) return }
// Start starts the Point server, and return any error during the process. // In the case of any errors, the state of the server is unpredicatable. func (this *Point) Start() error { if this.port <= 0 { log.Error("Invalid port ", this.port) return BadConfiguration } err := retry.Timed(100 /* times */, 100 /* ms */).On(func() error { err := this.ich.Listen(this.port) if err != nil { return err } log.Warning("Point server started on port ", this.port) return nil }) if err != nil { return err } for _, detourHandler := range this.idh { err := detourHandler.Start() if err != nil { return err } } return nil }
func ReadUDPRequest(packet []byte) (request Socks5UDPRequest, err error) { // packet[0] and packet[1] are reserved request.Fragment = packet[2] addrType := packet[3] var dataBegin int switch addrType { case AddrTypeIPv4: ip := packet[4:8] port := binary.BigEndian.Uint16(packet[8:10]) request.Address = v2net.IPAddress(ip, port) dataBegin = 10 case AddrTypeIPv6: ip := packet[4:20] port := binary.BigEndian.Uint16(packet[20:22]) request.Address = v2net.IPAddress(ip, port) dataBegin = 22 case AddrTypeDomain: domainLength := int(packet[4]) domain := string(packet[5 : 5+domainLength]) port := binary.BigEndian.Uint16(packet[5+domainLength : 5+domainLength+2]) request.Address = v2net.DomainAddress(domain, port) dataBegin = 5 + domainLength + 2 default: log.Warning("Unknown address type %d", addrType) err = ErrorUnknownAddressType return } request.Data = make([]byte, len(packet)-dataBegin) copy(request.Data, packet[dataBegin:]) return }
func handleResponse(conn net.Conn, request *protocol.VMessRequest, output chan<- *alloc.Buffer, finish *sync.Mutex, isUDP bool) { defer finish.Unlock() defer close(output) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn) if err != nil { log.Error("VMessOut: Failed to create decrypt reader: %v", err) return } buffer, err := v2net.ReadFrom(decryptResponseReader, nil) if err != nil { log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", buffer.Len(), err) return } if buffer.Len() < 4 || !bytes.Equal(buffer.Value[:4], request.ResponseHeader[:]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } log.Info("VMessOut received %d bytes from %s", buffer.Len()-4, conn.RemoteAddr().String()) buffer.SliceFrom(4) output <- buffer if !isUDP { v2net.ReaderToChan(output, decryptResponseReader) } return }
func (server *SocksServer) AcceptPackets(conn *net.UDPConn) error { for { buffer := alloc.NewBuffer() nBytes, addr, err := conn.ReadFromUDP(buffer.Value) if err != nil { log.Error("Socks failed to read UDP packets: %v", err) buffer.Release() continue } log.Info("Client UDP connection from %v", addr) request, err := protocol.ReadUDPRequest(buffer.Value[:nBytes]) buffer.Release() if err != nil { log.Error("Socks failed to parse UDP request: %v", err) request.Data.Release() continue } if request.Fragment != 0 { log.Warning("Dropping fragmented UDP packets.") // TODO handle fragments request.Data.Release() continue } udpPacket := v2net.NewPacket(request.Destination(), request.Data, false) log.Info("Send packet to %s with %d bytes", udpPacket.Destination().String(), request.Data.Len()) go server.handlePacket(conn, udpPacket, addr, request.Address) } }
func (this *VMessOutboundHandler) handleCommand(cmdId byte, data []byte) { cmd, err := command.CreateResponseCommand(cmdId) if err != nil { log.Warning("VMessOut: Unknown response command (", cmdId, "): ", err) return } if err := cmd.Unmarshal(data); err != nil { log.Warning("VMessOut: Failed to parse response command: ", err) return } switch typedCommand := cmd.(type) { case *command.SwitchAccount: this.handleSwitchAccount(typedCommand) default: } }
func (this *Server) handlePlainHTTP(request *http.Request, dest v2net.Destination, reader *bufio.Reader, writer io.Writer) { if len(request.URL.Host) <= 0 { response := this.GenerateResponse(400, "Bad Request") response.Write(writer) return } request.Host = request.URL.Host StripHopByHopHeaders(request) ray := this.packetDispatcher.DispatchToOutbound(dest) defer ray.InboundInput().Close() defer ray.InboundOutput().Release() var finish sync.WaitGroup finish.Add(1) go func() { defer finish.Done() requestWriter := v2io.NewBufferedWriter(v2io.NewChainWriter(ray.InboundInput())) err := request.Write(requestWriter) if err != nil { log.Warning("HTTP: Failed to write request: ", err) return } requestWriter.Flush() }() finish.Add(1) go func() { defer finish.Done() responseReader := bufio.NewReader(v2io.NewChanReader(ray.InboundOutput())) response, err := http.ReadResponse(responseReader, request) if err != nil { log.Warning("HTTP: Failed to read response: ", err) response = this.GenerateResponse(503, "Service Unavailable") } responseWriter := v2io.NewBufferedWriter(writer) err = response.Write(responseWriter) if err != nil { log.Warning("HTTP: Failed to write response: ", err) return } responseWriter.Flush() }() finish.Wait() }
func (this *Point) GetHandler(context app.Context, tag string) (proxy.InboundHandler, int) { handler, found := this.taggedIdh[tag] if !found { log.Warning("Point: Unable to find an inbound handler with tag: ", tag) return nil, 0 } return handler.GetConnectionHandler() }
func (this *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(16, connection) requestReader := protocol.NewVMessRequestReader(this.clients) request, err := requestReader.Read(connReader) if err != nil { log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, err.Error()) log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "") log.Debug("VMessIn: Received request for %s", request.Address.String()) ray := this.space.PacketDispatcher().DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() userSettings := vmess.GetUserSettings(request.User.Level) connReader.SetTimeOut(userSettings.PayloadReadTimeout) go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey) responseIV := md5.Sum(request.RequestIV) aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:]) if err != nil { log.Error("VMessIn: Failed to create AES decryption stream: %v", err) close(input) return err } responseWriter := v2crypto.NewCryptionWriter(aesStream, connection) // Optimize for small response packet buffer := alloc.NewLargeBuffer().Clear() defer buffer.Release() buffer.AppendBytes(request.ResponseHeader[0] ^ request.ResponseHeader[1]) buffer.AppendBytes(request.ResponseHeader[2] ^ request.ResponseHeader[3]) buffer.AppendBytes(byte(0), byte(0)) if data, open := <-output; open { buffer.Append(data.Value) data.Release() responseWriter.Write(buffer.Value) go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } connection.CloseWrite() readFinish.Lock() return nil }
func ReadAuthentication(reader io.Reader) (auth Socks5AuthenticationRequest, auth4 Socks4AuthenticationRequest, err error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() nBytes, err := reader.Read(buffer.Value) if err != nil { return } if nBytes < 2 { log.Warning("Socks: expected 2 bytes read, but only ", nBytes, " bytes read") err = transport.ErrCorruptedPacket return } if buffer.Value[0] == socks4Version { auth4.Version = buffer.Value[0] auth4.Command = buffer.Value[1] auth4.Port = v2net.PortFromBytes(buffer.Value[2:4]) copy(auth4.IP[:], buffer.Value[4:8]) err = Socks4Downgrade return } auth.version = buffer.Value[0] if auth.version != socksVersion { log.Warning("Socks: Unknown protocol version ", auth.version) err = proxy.ErrInvalidProtocolVersion return } auth.nMethods = buffer.Value[1] if auth.nMethods <= 0 { log.Warning("Socks: Zero length of authentication methods") err = proxy.ErrInvalidAuthentication return } if nBytes-2 != int(auth.nMethods) { log.Warning("Socks: Unmatching number of auth methods, expecting ", auth.nMethods, ", but got ", nBytes) err = proxy.ErrInvalidAuthentication return } copy(auth.authMethods[:], buffer.Value[2:nBytes]) return }
func (handler *VMessInboundHandler) AcceptPackets(conn *net.UDPConn) { for { buffer := alloc.NewBuffer() nBytes, addr, err := conn.ReadFromUDP(buffer.Value) if err != nil { log.Error("VMessIn failed to read UDP packets: %v", err) buffer.Release() continue } reader := bytes.NewReader(buffer.Value[:nBytes]) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(reader) if err != nil { log.Access(addr.String(), "", log.AccessRejected, err.Error()) log.Warning("VMessIn: Invalid request from (%s): %v", addr.String(), err) buffer.Release() continue } log.Access(addr.String(), request.Address.String(), log.AccessAccepted, "") cryptReader, err := v2io.NewAesDecryptReader(request.RequestKey, request.RequestIV, reader) if err != nil { log.Error("VMessIn: Failed to create decrypt reader: %v", err) buffer.Release() continue } data := alloc.NewBuffer() nBytes, err = cryptReader.Read(data.Value) buffer.Release() if err != nil { log.Warning("VMessIn: Unable to decrypt data: %v", err) data.Release() continue } data.Slice(0, nBytes) packet := v2net.NewPacket(request.Destination(), data, false) go handler.handlePacket(conn, request, packet, addr) } }
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) { if len(packet) < 5 { return nil, transport.CorruptedPacket } request := new(Socks5UDPRequest) // packet[0] and packet[1] are reserved request.Fragment = packet[2] addrType := packet[3] var dataBegin int switch addrType { case AddrTypeIPv4: if len(packet) < 10 { return nil, transport.CorruptedPacket } ip := packet[4:8] request.Port = v2net.PortFromBytes(packet[8:10]) request.Address = v2net.IPAddress(ip) dataBegin = 10 case AddrTypeIPv6: if len(packet) < 22 { return nil, transport.CorruptedPacket } ip := packet[4:20] request.Port = v2net.PortFromBytes(packet[20:22]) request.Address = v2net.IPAddress(ip) dataBegin = 22 case AddrTypeDomain: domainLength := int(packet[4]) if len(packet) < 5+domainLength+2 { return nil, transport.CorruptedPacket } domain := string(packet[5 : 5+domainLength]) request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2]) maybeIP := net.ParseIP(domain) if maybeIP != nil { request.Address = v2net.IPAddress(maybeIP) } else { request.Address = v2net.DomainAddress(domain) } dataBegin = 5 + domainLength + 2 default: log.Warning("Unknown address type ", addrType) return nil, ErrorUnknownAddressType } if len(packet) > dataBegin { request.Data = alloc.NewBuffer().Clear().Append(packet[dataBegin:]) } return request, nil }
func (dest *Destination) Network() string { switch dest.network { case NetTCP: return "tcp" case NetUDP: return "udp" default: log.Warning("Unknown network %d", dest.network) return "tcp" } }
func (this *VMessOutboundHandler) handleRequest(conn net.Conn, request *protocol.VMessRequest, firstPacket v2net.Packet, input <-chan *alloc.Buffer, finish *sync.Mutex) { defer finish.Unlock() aesStream, err := v2crypto.NewAesEncryptionStream(request.RequestKey[:], request.RequestIV[:]) if err != nil { log.Error("VMessOut: Failed to create AES encryption stream: ", err) return } encryptRequestWriter := v2crypto.NewCryptionWriter(aesStream, conn) buffer := alloc.NewBuffer().Clear() defer buffer.Release() buffer, err = request.ToBytes(protocol.NewRandomTimestampGenerator(protocol.Timestamp(time.Now().Unix()), 30), buffer) if err != nil { log.Error("VMessOut: Failed to serialize VMess request: ", err) return } // Send first packet of payload together with request, in favor of small requests. firstChunk := firstPacket.Chunk() moreChunks := firstPacket.MoreChunks() for firstChunk == nil && moreChunks { firstChunk, moreChunks = <-input } if firstChunk == nil && !moreChunks { log.Warning("VMessOut: Nothing to send. Existing...") return } if request.IsChunkStream() { vmessio.Authenticate(firstChunk) } aesStream.XORKeyStream(firstChunk.Value, firstChunk.Value) buffer.Append(firstChunk.Value) firstChunk.Release() _, err = conn.Write(buffer.Value) if err != nil { log.Error("VMessOut: Failed to write VMess request: ", err) return } if moreChunks { var streamWriter v2io.Writer streamWriter = v2io.NewAdaptiveWriter(encryptRequestWriter) if request.IsChunkStream() { streamWriter = vmessio.NewAuthChunkWriter(streamWriter) } v2io.ChanToWriter(streamWriter, input) } return }
func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(16, connection) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(connReader) if err != nil { log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, err.Error()) log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "") log.Debug("VMessIn: Received request for %s", request.Address.String()) ray := handler.dispatcher.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() connReader.SetTimeOut(120) go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey) responseIV := md5.Sum(request.RequestIV) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { log.Error("VMessIn: Failed to create encrypt writer: %v", err) return err } // Optimize for small response packet buffer := alloc.NewLargeBuffer().Clear() buffer.Append(request.ResponseHeader) if data, open := <-output; open { buffer.Append(data.Value) data.Release() responseWriter.Write(buffer.Value) buffer.Release() go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } connection.CloseWrite() readFinish.Lock() return nil }
func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err = io.ReadFull(reader, buffer.Value[:4]) if err != nil { return } request = &Socks5Request{ Version: buffer.Value[0], Command: buffer.Value[1], // buffer[2] is a reserved field AddrType: buffer.Value[3], } switch request.AddrType { case AddrTypeIPv4: _, err = io.ReadFull(reader, request.IPv4[:]) if err != nil { return } case AddrTypeDomain: _, err = io.ReadFull(reader, buffer.Value[0:1]) if err != nil { return } domainLength := buffer.Value[0] _, err = io.ReadFull(reader, buffer.Value[:domainLength]) if err != nil { return } request.Domain = string(append([]byte(nil), buffer.Value[:domainLength]...)) case AddrTypeIPv6: _, err = io.ReadFull(reader, request.IPv6[:]) if err != nil { return } default: log.Warning("Socks: Unexpected address type ", request.AddrType) err = transport.ErrCorruptedPacket return } _, err = io.ReadFull(reader, buffer.Value[:2]) if err != nil { return } request.Port = v2net.PortFromBytes(buffer.Value[:2]) return }
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error { defer connection.Close() reader := protocol.NewVMessRequestReader(handler.clients) // Timeout 4 seconds to prevent DoS attack connection.SetReadDeadline(time.Now().Add(requestReadTimeOut)) request, err := reader.Read(connection) if err != nil { log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err) return err } log.Debug("VMessIn: Received request for %s", request.Address.String()) // Clear read timeout connection.SetReadDeadline(zeroTime) ray := handler.vPoint.NewInboundConnectionAccepted(request.Destination()) input := ray.InboundInput() output := ray.InboundOutput() readFinish := make(chan bool) writeFinish := make(chan bool) go handleInput(request, connection, input, readFinish) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) response := protocol.NewVMessResponse(request) responseWriter, err := v2io.NewAesEncryptWriter(responseKey[:], responseIV[:], connection) if err != nil { return log.Error("VMessIn: Failed to create encrypt writer: %v", err) } // Optimize for small response packet buffer := make([]byte, 0, 1024) buffer = append(buffer, response[:]...) if data, open := <-output; open { buffer = append(buffer, data...) responseWriter.Write(buffer) go handleOutput(request, responseWriter, output, writeFinish) <-writeFinish } if tcpConn, ok := connection.(*net.TCPConn); ok { tcpConn.CloseWrite() } <-readFinish return nil }
func (this *TCPListener) start() { this.accepting = true for this.accepting { conn, err := this.listener.AcceptTCP() if err != nil { log.Warning("Listener: Failed to accept new TCP connection: ", err) continue } go this.connCallback(&TCPConn{ conn: conn, listener: this, }) } }
func (this *VMessOutboundHandler) handleResponse(conn net.Conn, request *protocol.VMessRequest, dest v2net.Destination, output chan<- *alloc.Buffer, finish *sync.Mutex) { defer finish.Unlock() defer close(output) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) aesStream, err := v2crypto.NewAesDecryptionStream(responseKey[:], responseIV[:]) if err != nil { log.Error("VMessOut: Failed to create AES encryption stream: ", err) return } decryptResponseReader := v2crypto.NewCryptionReader(aesStream, conn) buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err = io.ReadFull(decryptResponseReader, buffer.Value[:4]) if err != nil { log.Error("VMessOut: Failed to read VMess response (", buffer.Len(), " bytes): ", err) return } if !headerMatch(request, buffer.Value[0]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } if buffer.Value[2] != 0 { command := buffer.Value[2] dataLen := int(buffer.Value[3]) _, err := io.ReadFull(decryptResponseReader, buffer.Value[:dataLen]) if err != nil { log.Error("VMessOut: Failed to read response command: ", err) return } data := buffer.Value[:dataLen] go this.handleCommand(dest, command, data) } var reader v2io.Reader if request.IsChunkStream() { reader = vmessio.NewAuthChunkReader(decryptResponseReader) } else { reader = v2io.NewAdaptiveReader(decryptResponseReader) } v2io.ReaderToChan(output, reader) return }