func (this *CacheServer) Get(domain string) []net.IP { if ip, found := this.hosts[domain]; found { return []net.IP{ip} } domain = dns.Fqdn(domain) ips := this.GetCached(domain) if ips != nil { return ips } for _, server := range this.servers { response := server.QueryA(domain) select { case a, open := <-response: if !open || a == nil { continue } this.Lock() this.records[domain] = &DomainRecord{ A: a, } this.Unlock() log.Debug("DNS: Returning ", len(a.IPs), " IPs for domain ", domain) return a.IPs case <-time.After(QueryTimeout): } } log.Debug("DNS: Returning nil for domain ", domain) return nil }
func (this *ChunkReader) Read() (*alloc.Buffer, error) { buffer := alloc.NewLargeBuffer() if _, err := io.ReadFull(this.reader, buffer.Value[:2]); err != nil { buffer.Release() return nil, err } // There is a potential buffer overflow here. Large buffer is 64K bytes, // while uin16 + 10 will be more than that length := serial.BytesToUint16(buffer.Value[:2]) + AuthSize if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil { buffer.Release() return nil, err } buffer.Slice(0, int(length)) authBytes := buffer.Value[:AuthSize] payload := buffer.Value[AuthSize:] actualAuthBytes := this.auth.Authenticate(nil, payload) if !bytes.Equal(authBytes, actualAuthBytes) { buffer.Release() log.Debug("AuthenticationReader: Unexpected auth: ", authBytes) return nil, transport.ErrorCorruptedPacket } buffer.Value = payload return buffer, nil }
func (this *Connection) flush() { current := this.Elapsed() if this.State() == StateTerminated { return } if this.State() == StateActive && current-atomic.LoadUint32(&this.lastIncomingTime) >= 30000 { this.Close() } if this.State() == StateReadyToClose && this.sendingWorker.IsEmpty() { this.SetState(StateTerminating) } if this.State() == StateTerminating { log.Debug("KCP|Connection: #", this.conv, " sending terminating cmd.") seg := NewCmdOnlySegment() defer seg.Release() seg.Conv = this.conv seg.Command = CommandTerminate this.output.Write(seg) this.output.Flush() if current-atomic.LoadUint32(&this.stateBeginTime) > 8000 { this.SetState(StateTerminated) } return } if this.State() == StatePeerTerminating && current-atomic.LoadUint32(&this.stateBeginTime) > 4000 { this.SetState(StateTerminating) } if this.State() == StateReadyToClose && current-atomic.LoadUint32(&this.stateBeginTime) > 15000 { this.SetState(StateTerminating) } // flush acknowledges this.receivingWorker.Flush(current) this.sendingWorker.Flush(current) if this.sendingWorker.PingNecessary() || this.receivingWorker.PingNecessary() || current-atomic.LoadUint32(&this.lastPingTime) >= 5000 { seg := NewCmdOnlySegment() seg.Conv = this.conv seg.Command = CommandPing seg.ReceivinNext = this.receivingWorker.nextNumber seg.SendingNext = this.sendingWorker.firstUnacknowledged if this.State() == StateReadyToClose { seg.Option = SegmentOptionClose } this.output.Write(seg) this.lastPingTime = current this.sendingWorker.MarkPingNecessary(false) this.receivingWorker.MarkPingNecessary(false) seg.Release() } // flash remain segments this.output.Flush() }
func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange) ([]byte, error) { buffer := make([]byte, 0, 300) counter := randomRangeInt64(time.Now().UTC().Unix(), 30) hash := idHash.Hash(request.UserId.Bytes, counter) log.Debug("Writing userhash: %v", hash) buffer = append(buffer, hash...) encryptionBegin := len(buffer) randomLength := mrand.Intn(32) + 1 randomContent := make([]byte, randomLength) _, err := rand.Read(randomContent) if err != nil { return nil, err } buffer = append(buffer, byte(randomLength)) buffer = append(buffer, randomContent...) buffer = append(buffer, request.Version) buffer = append(buffer, request.RequestIV[:]...) buffer = append(buffer, request.RequestKey[:]...) buffer = append(buffer, request.ResponseHeader[:]...) buffer = append(buffer, request.Command) buffer = append(buffer, request.Address.PortBytes()...) switch { case request.Address.IsIPv4(): buffer = append(buffer, addrTypeIPv4) buffer = append(buffer, request.Address.IP()...) case request.Address.IsIPv6(): buffer = append(buffer, addrTypeIPv6) buffer = append(buffer, request.Address.IP()...) case request.Address.IsDomain(): buffer = append(buffer, addrTypeDomain) buffer = append(buffer, byte(len(request.Address.Domain()))) buffer = append(buffer, []byte(request.Address.Domain())...) } paddingLength := mrand.Intn(32) + 1 paddingBuffer := make([]byte, paddingLength) _, err = rand.Read(paddingBuffer) if err != nil { return nil, err } buffer = append(buffer, byte(paddingLength)) buffer = append(buffer, paddingBuffer...) encryptionEnd := len(buffer) aesCipher, err := aes.NewCipher(request.UserId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter)) aesStream.XORKeyStream(buffer[encryptionBegin:encryptionEnd], buffer[encryptionBegin:encryptionEnd]) return buffer, nil }
func JsonConfigLoader(newConfig func() interface{}) func(data []byte) (interface{}, error) { return func(data []byte) (interface{}, error) { obj := newConfig() log.Debug("Unmarshalling JSON: %s", string(data)) err := json.Unmarshal(data, obj) return obj, err } }
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 (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id ID) { idHash := NewTimeHash(HMACHash{}) for lastSec < nowSec+cacheDurationSec { idHash := idHash.Hash(id.Bytes, lastSec) log.Debug("Valid User Hash: %v", idHash) us.userHash.Set(string(idHash), indexTimePair{idx, lastSec}, lastSec+2*cacheDurationSec) lastSec++ } }
func (server *SocksServer) Listen(port uint16) error { listener, err := net.Listen("tcp", ":"+strconv.Itoa(int(port))) if err != nil { log.Error("Error on listening port %d: %v", port, err) return err } log.Debug("Working on tcp:%d", port) server.accepting = true go server.AcceptConnections(listener) return nil }
// ToBytes returns a VMessRequest in the form of byte array. func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer []byte) ([]byte, error) { if buffer == nil { buffer = make([]byte, 0, 300) } counter := randomRangeInt64(time.Now().UTC().Unix(), 30) hash := idHash.Hash(request.UserId.Bytes[:], counter) log.Debug("Writing userhash: %v", hash) buffer = append(buffer, hash...) encryptionBegin := len(buffer) buffer = append(buffer, request.Version) buffer = append(buffer, request.RequestIV[:]...) buffer = append(buffer, request.RequestKey[:]...) buffer = append(buffer, request.ResponseHeader[:]...) buffer = append(buffer, request.Command) buffer = append(buffer, request.Address.PortBytes()...) switch { case request.Address.IsIPv4(): buffer = append(buffer, addrTypeIPv4) buffer = append(buffer, request.Address.IP()...) case request.Address.IsIPv6(): buffer = append(buffer, addrTypeIPv6) buffer = append(buffer, request.Address.IP()...) case request.Address.IsDomain(): buffer = append(buffer, addrTypeDomain) buffer = append(buffer, byte(len(request.Address.Domain()))) buffer = append(buffer, []byte(request.Address.Domain())...) } encryptionEnd := len(buffer) fnv1a := fnv.New32a() fnv1a.Write(buffer[encryptionBegin:encryptionEnd]) fnvHash := fnv1a.Sum32() buffer = append(buffer, byte(fnvHash>>24)) buffer = append(buffer, byte(fnvHash>>16)) buffer = append(buffer, byte(fnvHash>>8)) buffer = append(buffer, byte(fnvHash)) encryptionEnd += 4 aesCipher, err := aes.NewCipher(request.UserId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter)) aesStream.XORKeyStream(buffer[encryptionBegin:encryptionEnd], buffer[encryptionBegin:encryptionEnd]) return buffer, nil }
func Pipe(reader Reader, writer Writer) error { for { buffer, err := reader.Read() if err != nil { log.Debug("IO: Pipe exits as ", err) return err } if buffer.IsEmpty() { buffer.Release() continue } err = writer.Write(buffer) if err != nil { log.Debug("IO: Pipe exits as ", err) return err } } }
func (us *TimedUserSet) generateNewHashes(lastSec, nowSec int64, idx int, id ID) { idHash := NewTimeHash(HMACHash{}) for lastSec < nowSec+cacheDurationSec { idHash := idHash.Hash(id.Bytes, lastSec) log.Debug("Valid User Hash: %v", idHash) heap.Push(&us.hash2Remove, &hashEntry{string(idHash), lastSec}) us.userHashes[string(idHash)] = indexTimePair{idx, lastSec} lastSec++ } }
func (this *TimedInboundRay) Release() { log.Debug("UDP Server: Releasing TimedInboundRay: ", this.name) this.Lock() defer this.Unlock() if this.server == nil { return } this.server = nil this.inboundRay.InboundInput().Close() this.inboundRay.InboundOutput().Release() this.inboundRay = nil }
func (this *Listener) Remove(dest string) { if !this.running { return } this.Lock() defer this.Unlock() if !this.running { return } log.Debug("KCP|Listener: Removing session ", dest) delete(this.sessions, dest) }
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 (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 (this *HttpProxyServer) handlePlainHTTP(request *http.Request, dest v2net.Destination, reader *bufio.Reader, writer io.Writer) { if len(request.URL.Host) <= 0 { hdr := http.Header(make(map[string][]string)) hdr.Set("Connection", "close") response := &http.Response{ Status: "400 Bad Request", StatusCode: 400, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Header: hdr, Body: nil, ContentLength: 0, Close: false, } buffer := alloc.NewSmallBuffer().Clear() response.Write(buffer) writer.Write(buffer.Value) buffer.Release() return } request.Host = request.URL.Host stripHopByHopHeaders(request) requestBuffer := alloc.NewBuffer().Clear() // Don't release this buffer as it is passed into a Packet. request.Write(requestBuffer) log.Debug("Request to remote:\n", serial.BytesLiteral(requestBuffer.Value)) packet := v2net.NewPacket(dest, requestBuffer, true) ray := this.packetDispatcher.DispatchToOutbound(packet) defer close(ray.InboundInput()) var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() responseReader := bufio.NewReader(NewChanReader(ray.InboundOutput())) response, err := http.ReadResponse(responseReader, request) if err != nil { return } responseBuffer := alloc.NewBuffer().Clear() defer responseBuffer.Release() response.Write(responseBuffer) writer.Write(responseBuffer.Value) response.Body.Close() }() wg.Wait() }
func (handler *VMessInboundHandler) HandleConnection(connection net.Conn) error { defer connection.Close() connReader := v2net.NewTimeOutReader(4, connection) requestReader := protocol.NewVMessRequestReader(handler.clients) request, err := requestReader.Read(connReader) 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()) ray := handler.vPoint.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() go handleInput(request, connReader, 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, 2*1024) buffer = append(buffer, response[:]...) if data, open := <-output; open { buffer = append(buffer, data...) responseWriter.Write(buffer) go handleOutput(request, responseWriter, output, &writeFinish) writeFinish.Lock() } if tcpConn, ok := connection.(*net.TCPConn); ok { tcpConn.CloseWrite() } readFinish.Lock() return nil }
func (this *Listener) OnReceive(payload *alloc.Buffer, src v2net.Destination) { defer payload.Release() if valid := this.block.Open(payload); !valid { log.Info("KCP|Listener: discarding invalid payload from ", src) return } if !this.running { return } this.Lock() defer this.Unlock() if !this.running { return } if payload.Len() < 4 { return } conv := serial.BytesToUint16(payload.Value) cmd := Command(payload.Value[2]) sourceId := src.NetAddr() + "|" + serial.Uint16ToString(conv) conn, found := this.sessions[sourceId] if !found { if cmd == CommandTerminate { return } log.Debug("KCP|Listener: Creating session with id(", sourceId, ") from ", src) writer := &Writer{ id: sourceId, hub: this.hub, dest: src, listener: this, } srcAddr := &net.UDPAddr{ IP: src.Address().IP(), Port: int(src.Port()), } conn = NewConnection(conv, writer, this.localAddr, srcAddr, this.block) select { case this.awaitingConns <- conn: case <-time.After(time.Second * 5): conn.Close() return } this.sessions[sourceId] = conn } conn.Input(payload.Value) }
func (this *UDPServer) locateExistingAndDispatch(name string, payload *alloc.Buffer) bool { log.Debug("UDP Server: Locating existing connection for ", name) this.RLock() defer this.RUnlock() if entry, found := this.conns[name]; found { outputStream := entry.InboundInput() if outputStream == nil { return false } err := outputStream.Write(payload) if err != nil { go entry.Release() return false } return true } return false }
// @Private func (this *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc.Buffer) { msg := new(dns.Msg) err := msg.Unpack(payload.Value) if err != nil { log.Warning("DNS: Failed to parse DNS response: ", err) return } record := &ARecord{ IPs: make([]net.IP, 0, 16), } id := msg.Id ttl := DefaultTTL log.Debug("DNS: Handling response for id ", id, " content: ", msg.String()) this.Lock() request, found := this.requests[id] if !found { this.Unlock() return } delete(this.requests, id) this.Unlock() for _, rr := range msg.Answer { switch rr := rr.(type) { case *dns.A: record.IPs = append(record.IPs, rr.A) if rr.Hdr.Ttl < ttl { ttl = rr.Hdr.Ttl } case *dns.AAAA: record.IPs = append(record.IPs, rr.AAAA) if rr.Hdr.Ttl < ttl { ttl = rr.Hdr.Ttl } } } record.Expire = time.Now().Add(time.Second * time.Duration(ttl)) request.response <- record close(request.response) }
func (this *UDPServer) Dispatch(source v2net.Destination, destination v2net.Destination, payload *alloc.Buffer, callback UDPResponseCallback) { destString := source.String() + "-" + destination.String() log.Debug("UDP Server: Dispatch request: ", destString) if this.locateExistingAndDispatch(destString, payload) { return } log.Info("UDP Server: establishing new connection for ", destString) inboundRay := this.packetDispatcher.DispatchToOutbound(destination) timedInboundRay := NewTimedInboundRay(destString, inboundRay, this) outputStream := timedInboundRay.InboundInput() if outputStream != nil { outputStream.Write(payload) } this.Lock() this.conns[destString] = timedInboundRay this.Unlock() go this.handleConnection(timedInboundRay, source, callback) }
func (this *Connection) SetState(state State) { current := this.Elapsed() atomic.StoreInt32((*int32)(&this.state), int32(state)) atomic.StoreUint32(&this.stateBeginTime, current) log.Debug("KCP|Connection: #", this.conv, " entering state ", state, " at ", current) switch state { case StateReadyToClose: this.receivingWorker.CloseRead() case StatePeerClosed: this.sendingWorker.CloseWrite() case StateTerminating: this.receivingWorker.CloseRead() this.sendingWorker.CloseWrite() case StatePeerTerminating: this.sendingWorker.CloseWrite() case StateTerminated: this.receivingWorker.CloseRead() this.sendingWorker.CloseWrite() } }
// @Private func (this *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 { var id uint16 this.Lock() if len(this.requests) > CleanupThreshold && this.nextCleanup.Before(time.Now()) { this.nextCleanup = time.Now().Add(CleanupInterval) go this.Cleanup() } for { id = uint16(dice.Roll(65536)) if _, found := this.requests[id]; found { continue } log.Debug("DNS: Add pending request id ", id) this.requests[id] = &PendingRequest{ expire: time.Now().Add(time.Second * 8), response: response, } break } this.Unlock() return id }
func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { buffer := make([]byte, 256) nBytes, err := reader.Read(buffer[:user.IDBytesLen]) if err != nil { return nil, err } log.Debug("Read user hash: %v", buffer[:nBytes]) userId, timeSec, valid := r.vUserSet.GetUser(buffer[:nBytes]) if !valid { return nil, ErrorInvalidUser } aesCipher, err := aes.NewCipher(userId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec)) decryptor := v2io.NewCryptionReader(aesStream, reader) if err != nil { return nil, err } nBytes, err = decryptor.Read(buffer[0:1]) if err != nil { return nil, err } randomLength := buffer[0] if randomLength <= 0 || randomLength > 32 { return nil, fmt.Errorf("Unexpected random length %d", randomLength) } _, err = decryptor.Read(buffer[:randomLength]) if err != nil { return nil, err } nBytes, err = decryptor.Read(buffer[0:1]) if err != nil { return nil, err } request := &VMessRequest{ UserId: *userId, Version: buffer[0], } if request.Version != Version { log.Error("Unknown VMess version %d", request.Version) return nil, ErrorInvalidVerion } // TODO: check number of bytes returned _, err = decryptor.Read(request.RequestIV[:]) if err != nil { return nil, err } _, err = decryptor.Read(request.RequestKey[:]) if err != nil { return nil, err } _, err = decryptor.Read(request.ResponseHeader[:]) if err != nil { return nil, err } _, err = decryptor.Read(buffer[0:1]) if err != nil { return nil, err } request.Command = buffer[0] _, err = decryptor.Read(buffer[0:2]) if err != nil { return nil, err } port := binary.BigEndian.Uint16(buffer[0:2]) _, err = decryptor.Read(buffer[0:1]) if err != nil { return nil, err } switch buffer[0] { case addrTypeIPv4: _, err = decryptor.Read(buffer[1:5]) if err != nil { return nil, err } request.Address = v2net.IPAddress(buffer[1:5], port) case addrTypeIPv6: _, err = decryptor.Read(buffer[1:17]) if err != nil { return nil, err } request.Address = v2net.IPAddress(buffer[1:17], port) case addrTypeDomain: _, err = decryptor.Read(buffer[1:2]) if err != nil { return nil, err } domainLength := buffer[1] _, err = decryptor.Read(buffer[2 : 2+domainLength]) if err != nil { return nil, err } request.Address = v2net.DomainAddress(string(buffer[2:2+domainLength]), port) } _, err = decryptor.Read(buffer[0:1]) if err != nil { return nil, err } randomLength = buffer[0] _, err = decryptor.Read(buffer[:randomLength]) if err != nil { return nil, err } return request, nil }
// Read reads a VMessRequest from a byte stream. func (this *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() nBytes, err := io.ReadFull(reader, buffer.Value[:proto.IDBytesLen]) if err != nil { log.Debug("VMess: Failed to read request ID (", nBytes, " bytes): ", err) return nil, err } userObj, timeSec, valid := this.vUserSet.GetUser(buffer.Value[:nBytes]) if !valid { return nil, proxy.ErrorInvalidAuthentication } timestampHash := TimestampHash() timestampHash.Write(timeSec.HashBytes()) iv := timestampHash.Sum(nil) aesStream, err := v2crypto.NewAesDecryptionStream(userObj.ID.CmdKey(), iv) if err != nil { log.Debug("VMess: Failed to create AES stream: ", err) return nil, err } decryptor := v2crypto.NewCryptionReader(aesStream, reader) nBytes, err = io.ReadFull(decryptor, buffer.Value[:41]) if err != nil { log.Debug("VMess: Failed to read request header (", nBytes, " bytes): ", err) return nil, err } bufferLen := nBytes request := &VMessRequest{ User: userObj, Version: buffer.Value[0], } if request.Version != Version { log.Warning("VMess: Invalid protocol version ", request.Version) return nil, proxy.ErrorInvalidProtocolVersion } request.RequestIV = append([]byte(nil), buffer.Value[1:17]...) // 16 bytes request.RequestKey = append([]byte(nil), buffer.Value[17:33]...) // 16 bytes request.ResponseHeader = buffer.Value[33] // 1 byte request.Option = buffer.Value[34] // 1 byte + 2 bytes reserved request.Command = buffer.Value[37] request.Port = v2net.PortFromBytes(buffer.Value[38:40]) switch buffer.Value[40] { case addrTypeIPv4: nBytes, err = io.ReadFull(decryptor, buffer.Value[41:45]) // 4 bytes bufferLen += 4 if err != nil { log.Debug("VMess: Failed to read target IPv4 (", nBytes, " bytes): ", err) return nil, err } request.Address = v2net.IPAddress(buffer.Value[41:45]) case addrTypeIPv6: nBytes, err = io.ReadFull(decryptor, buffer.Value[41:57]) // 16 bytes bufferLen += 16 if err != nil { log.Debug("VMess: Failed to read target IPv6 (", nBytes, " bytes): ", nBytes, err) return nil, err } request.Address = v2net.IPAddress(buffer.Value[41:57]) case addrTypeDomain: nBytes, err = io.ReadFull(decryptor, buffer.Value[41:42]) if err != nil { log.Debug("VMess: Failed to read target domain (", nBytes, " bytes): ", nBytes, err) return nil, err } domainLength := int(buffer.Value[41]) if domainLength == 0 { return nil, transport.ErrorCorruptedPacket } nBytes, err = io.ReadFull(decryptor, buffer.Value[42:42+domainLength]) if err != nil { log.Debug("VMess: Failed to read target domain (", nBytes, " bytes): ", nBytes, err) return nil, err } bufferLen += 1 + domainLength domainBytes := append([]byte(nil), buffer.Value[42:42+domainLength]...) request.Address = v2net.DomainAddress(string(domainBytes)) } nBytes, err = io.ReadFull(decryptor, buffer.Value[bufferLen:bufferLen+4]) if err != nil { log.Debug("VMess: Failed to read checksum (", nBytes, " bytes): ", nBytes, err) return nil, err } fnv1a := fnv.New32a() fnv1a.Write(buffer.Value[:bufferLen]) actualHash := fnv1a.Sum32() expectedHash := binary.BigEndian.Uint32(buffer.Value[bufferLen : bufferLen+4]) if actualHash != expectedHash { return nil, transport.ErrorCorruptedPacket } return request, nil }
// Read reads a VMessRequest from a byte stream. func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { buffer := make([]byte, 256) nBytes, err := reader.Read(buffer[:user.IDBytesLen]) if err != nil { return nil, err } log.Debug("Read user hash: %v", buffer[:nBytes]) userId, timeSec, valid := r.vUserSet.GetUser(buffer[:nBytes]) if !valid { return nil, errors.NewAuthenticationError(buffer[:nBytes]) } aesCipher, err := aes.NewCipher(userId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec)) decryptor := v2io.NewCryptionReader(aesStream, reader) if err != nil { return nil, err } nBytes, err = decryptor.Read(buffer[:41]) if err != nil { return nil, err } bufferLen := nBytes request := &VMessRequest{ UserId: *userId, Version: buffer[0], } if request.Version != Version { return nil, errors.NewProtocolVersionError(int(request.Version)) } copy(request.RequestIV[:], buffer[1:17]) // 16 bytes copy(request.RequestKey[:], buffer[17:33]) // 16 bytes copy(request.ResponseHeader[:], buffer[33:37]) // 4 bytes request.Command = buffer[37] port := binary.BigEndian.Uint16(buffer[38:40]) switch buffer[40] { case addrTypeIPv4: _, err = decryptor.Read(buffer[41:45]) // 4 bytes bufferLen += 4 if err != nil { return nil, err } request.Address = v2net.IPAddress(buffer[41:45], port) case addrTypeIPv6: _, err = decryptor.Read(buffer[41:57]) // 16 bytes bufferLen += 16 if err != nil { return nil, err } request.Address = v2net.IPAddress(buffer[41:57], port) case addrTypeDomain: _, err = decryptor.Read(buffer[41:42]) if err != nil { return nil, err } domainLength := int(buffer[41]) _, err = decryptor.Read(buffer[42 : 42+domainLength]) if err != nil { return nil, err } bufferLen += 1 + domainLength request.Address = v2net.DomainAddress(string(buffer[42:42+domainLength]), port) } _, err = decryptor.Read(buffer[bufferLen : bufferLen+4]) if err != nil { return nil, err } fnv1a := fnv.New32a() fnv1a.Write(buffer[:bufferLen]) actualHash := fnv1a.Sum32() expectedHash := binary.BigEndian.Uint32(buffer[bufferLen : bufferLen+4]) if actualHash != expectedHash { return nil, errors.NewCorruptedPacketError() } return request, nil }
func (server *SocksServer) dumpOutput(writer io.Writer, output <-chan []byte, finish chan<- bool) { v2net.ChanToWriter(writer, output) log.Debug("Socks output closed") finish <- true }
func (server *SocksServer) dumpInput(reader io.Reader, input chan<- []byte, finish chan<- bool) { v2net.ReaderToChan(input, reader) close(input) log.Debug("Socks input closed") finish <- true }
func (this *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err := io.ReadFull(reader, buffer.Value[:protocol.IDBytesLen]) if err != nil { log.Error("Raw: Failed to read request header: ", err) return nil, err } user, timestamp, valid := this.userValidator.Get(buffer.Value[:protocol.IDBytesLen]) if !valid { return nil, protocol.ErrorInvalidUser } timestampHash := md5.New() timestampHash.Write(hashTimestamp(timestamp)) iv := timestampHash.Sum(nil) aesStream := crypto.NewAesDecryptionStream(user.ID.CmdKey(), iv) decryptor := crypto.NewCryptionReader(aesStream, reader) nBytes, err := io.ReadFull(decryptor, buffer.Value[:41]) if err != nil { log.Debug("Raw: Failed to read request header (", nBytes, " bytes): ", err) return nil, err } bufferLen := nBytes request := &protocol.RequestHeader{ User: user, Version: buffer.Value[0], } if request.Version != Version { log.Warning("Raw: Invalid protocol version ", request.Version) return nil, protocol.ErrorInvalidVersion } this.requestBodyIV = append([]byte(nil), buffer.Value[1:17]...) // 16 bytes this.requestBodyKey = append([]byte(nil), buffer.Value[17:33]...) // 16 bytes this.responseHeader = buffer.Value[33] // 1 byte request.Option = protocol.RequestOption(buffer.Value[34]) // 1 byte + 2 bytes reserved request.Command = protocol.RequestCommand(buffer.Value[37]) request.Port = v2net.PortFromBytes(buffer.Value[38:40]) switch buffer.Value[40] { case AddrTypeIPv4: nBytes, err = io.ReadFull(decryptor, buffer.Value[41:45]) // 4 bytes bufferLen += 4 if err != nil { log.Debug("VMess: Failed to read target IPv4 (", nBytes, " bytes): ", err) return nil, err } request.Address = v2net.IPAddress(buffer.Value[41:45]) case AddrTypeIPv6: nBytes, err = io.ReadFull(decryptor, buffer.Value[41:57]) // 16 bytes bufferLen += 16 if err != nil { log.Debug("VMess: Failed to read target IPv6 (", nBytes, " bytes): ", nBytes, err) return nil, err } request.Address = v2net.IPAddress(buffer.Value[41:57]) case AddrTypeDomain: nBytes, err = io.ReadFull(decryptor, buffer.Value[41:42]) if err != nil { log.Debug("VMess: Failed to read target domain (", nBytes, " bytes): ", nBytes, err) return nil, err } domainLength := int(buffer.Value[41]) if domainLength == 0 { return nil, transport.ErrorCorruptedPacket } nBytes, err = io.ReadFull(decryptor, buffer.Value[42:42+domainLength]) if err != nil { log.Debug("VMess: Failed to read target domain (", nBytes, " bytes): ", nBytes, err) return nil, err } bufferLen += 1 + domainLength domainBytes := append([]byte(nil), buffer.Value[42:42+domainLength]...) request.Address = v2net.DomainAddress(string(domainBytes)) } nBytes, err = io.ReadFull(decryptor, buffer.Value[bufferLen:bufferLen+4]) if err != nil { log.Debug("VMess: Failed to read checksum (", nBytes, " bytes): ", nBytes, err) return nil, err } fnv1a := fnv.New32a() fnv1a.Write(buffer.Value[:bufferLen]) actualHash := fnv1a.Sum32() expectedHash := serial.BytesLiteral(buffer.Value[bufferLen : bufferLen+4]).Uint32Value() if actualHash != expectedHash { return nil, transport.ErrorCorruptedPacket } return request, nil }
func ReadRequest(reader io.Reader, auth *Authenticator, udp bool) (*Request, error) { buffer := alloc.NewSmallBuffer() defer buffer.Release() _, err := io.ReadFull(reader, buffer.Value[:1]) if err != nil { log.Error("Shadowsocks: Failed to read address type: ", err) return nil, transport.ErrorCorruptedPacket } lenBuffer := 1 request := new(Request) addrType := (buffer.Value[0] & 0x0F) if (buffer.Value[0] & 0x10) == 0x10 { request.OTA = true } switch addrType { case AddrTypeIPv4: _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+4]) if err != nil { log.Error("Shadowsocks: Failed to read IPv4 address: ", err) return nil, transport.ErrorCorruptedPacket } request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+4]) lenBuffer += 4 case AddrTypeIPv6: _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+16]) if err != nil { log.Error("Shadowsocks: Failed to read IPv6 address: ", err) return nil, transport.ErrorCorruptedPacket } request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+16]) lenBuffer += 16 case AddrTypeDomain: _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+1]) if err != nil { log.Error("Shadowsocks: Failed to read domain lenth: ", err) return nil, transport.ErrorCorruptedPacket } domainLength := int(buffer.Value[lenBuffer]) lenBuffer++ _, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+domainLength]) if err != nil { log.Error("Shadowsocks: Failed to read domain: ", err) return nil, transport.ErrorCorruptedPacket } request.Address = v2net.DomainAddress(string(buffer.Value[lenBuffer : lenBuffer+domainLength])) lenBuffer += domainLength default: log.Error("Shadowsocks: Unknown address type: ", addrType) return nil, transport.ErrorCorruptedPacket } _, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+2]) if err != nil { log.Error("Shadowsocks: Failed to read port: ", err) return nil, transport.ErrorCorruptedPacket } request.Port = v2net.PortFromBytes(buffer.Value[lenBuffer : lenBuffer+2]) lenBuffer += 2 var authBytes []byte if udp { nBytes, err := reader.Read(buffer.Value[lenBuffer:]) if err != nil { log.Error("Shadowsocks: Failed to read UDP payload: ", err) return nil, transport.ErrorCorruptedPacket } buffer.Slice(0, lenBuffer+nBytes) if request.OTA { authBytes = buffer.Value[lenBuffer+nBytes-AuthSize:] request.UDPPayload = alloc.NewSmallBuffer().Clear().Append(buffer.Value[lenBuffer : lenBuffer+nBytes-AuthSize]) lenBuffer = lenBuffer + nBytes - AuthSize } else { request.UDPPayload = alloc.NewSmallBuffer().Clear().Append(buffer.Value[lenBuffer:]) } } else { if request.OTA { authBytes = buffer.Value[lenBuffer : lenBuffer+AuthSize] _, err = io.ReadFull(reader, authBytes) if err != nil { log.Error("Shadowsocks: Failed to read OTA: ", err) return nil, transport.ErrorCorruptedPacket } } } if request.OTA { actualAuth := auth.Authenticate(nil, buffer.Value[0:lenBuffer]) if !serial.BytesLiteral(actualAuth).Equals(serial.BytesLiteral(authBytes)) { log.Debug("Shadowsocks: Invalid OTA. Expecting ", actualAuth, ", but got ", authBytes) log.Warning("Shadowsocks: Invalid OTA.") return nil, proxy.ErrorInvalidAuthentication } } return request, nil }