func (this *SimpleAuthenticator) Open(buffer *alloc.Buffer) bool { len := buffer.Len() xtra := 4 - len%4 if xtra != 0 { buffer.Slice(0, len+xtra) } xorbkd(buffer.Value) if xtra != 0 { buffer.Slice(0, len) } fnvHash := fnv.New32a() fnvHash.Write(buffer.Value[4:]) if serial.BytesToUint32(buffer.Value[:4]) != fnvHash.Sum32() { return false } length := serial.BytesToUint16(buffer.Value[4:6]) if buffer.Len()-6 != int(length) { return false } buffer.SliceFrom(6) return true }
func Authenticate(buffer *alloc.Buffer) { fnvHash := fnv.New32a() fnvHash.Write(buffer.Value) buffer.PrependHash(fnvHash) buffer.PrependUint16(uint16(buffer.Len())) }
func (this *ChunkWriter) Write(payload *alloc.Buffer) error { totalLength := payload.Len() payload.SliceBack(AuthSize) this.auth.Authenticate(payload.Value[:0], payload.Value[AuthSize:]) payload.PrependUint16(uint16(totalLength)) _, err := this.writer.Write(payload.Bytes()) return err }
func (this *Listener) OnReceive(payload *alloc.Buffer, session *proxy.SessionInfo) { defer payload.Release() src := session.Source if valid := this.authenticator.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), } auth, err := this.config.GetAuthenticator() if err != nil { log.Error("KCP|Listener: Failed to create authenticator: ", err) } conn = NewConnection(conv, writer, this.Addr().(*net.UDPAddr), srcAddr, auth, this.config) select { case this.awaitingConns <- conn: case <-time.After(time.Second * 5): conn.Close() return } this.sessions[sourceId] = conn } conn.Input(payload.Value) }
func (this *Server) handleUDPPayload(payload *alloc.Buffer, session *proxy.SessionInfo) { source := session.Source log.Info("Socks: Client UDP connection from ", source) request, err := protocol.ReadUDPRequest(payload.Value) payload.Release() if err != nil { log.Error("Socks: Failed to parse UDP request: ", err) return } if request.Data.Len() == 0 { request.Data.Release() return } if request.Fragment != 0 { log.Warning("Socks: Dropping fragmented UDP packets.") // TODO handle fragments request.Data.Release() return } log.Info("Socks: Send packet to ", request.Destination(), " with ", request.Data.Len(), " bytes") log.Access(source, request.Destination, log.AccessAccepted, "") this.udpServer.Dispatch(&proxy.SessionInfo{Source: source, Destination: request.Destination()}, request.Data, func(destination v2net.Destination, payload *alloc.Buffer) { response := &protocol.Socks5UDPRequest{ Fragment: 0, Address: request.Destination().Address(), Port: request.Destination().Port(), Data: payload, } log.Info("Socks: Writing back UDP response with ", payload.Len(), " bytes to ", destination) udpMessage := alloc.NewLocalBuffer(2048).Clear() response.Write(udpMessage) this.udpMutex.RLock() if !this.accepting { this.udpMutex.RUnlock() return } nBytes, err := this.udpHub.WriteTo(udpMessage.Value, destination) this.udpMutex.RUnlock() udpMessage.Release() response.Data.Release() if err != nil { log.Error("Socks: failed to write UDP message (", nBytes, " bytes) to ", destination, ": ", err) } }) }
func (this *SimpleAuthenticator) Seal(buffer *alloc.Buffer) { buffer.PrependUint16(uint16(buffer.Len())) fnvHash := fnv.New32a() fnvHash.Write(buffer.Value) buffer.PrependHash(fnvHash) len := buffer.Len() xtra := 4 - len%4 if xtra != 0 { buffer.Slice(0, len+xtra) } xorfwd(buffer.Value) if xtra != 0 { buffer.Slice(0, len) } }
func DecodeUDPPacket(user *protocol.User, payload *alloc.Buffer) (*protocol.RequestHeader, *alloc.Buffer, error) { rawAccount, err := user.GetTypedAccount() if err != nil { return nil, nil, errors.New("Shadowsocks|UDP: Failed to parse account: " + err.Error()) } account := rawAccount.(*ShadowsocksAccount) ivLen := account.Cipher.IVSize() iv := payload.Value[:ivLen] payload.SliceFrom(ivLen) stream, err := account.Cipher.NewDecodingStream(account.Key, iv) if err != nil { return nil, nil, errors.New("Shadowsocks|UDP: Failed to initialize decoding stream: " + err.Error()) } stream.XORKeyStream(payload.Value, payload.Value) authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) request := &protocol.RequestHeader{ Version: Version, User: user, Command: protocol.RequestCommandUDP, } addrType := (payload.Value[0] & 0x0F) if (payload.Value[0] & 0x10) == 0x10 { request.Option |= RequestOptionOneTimeAuth } if request.Option.Has(RequestOptionOneTimeAuth) { payloadLen := payload.Len() - AuthSize authBytes := payload.Value[payloadLen:] actualAuth := authenticator.Authenticate(nil, payload.Value[0:payloadLen]) if !bytes.Equal(actualAuth, authBytes) { return nil, nil, errors.New("Shadowsocks|UDP: Invalid OTA.") } payload.Slice(0, payloadLen) } payload.SliceFrom(1) switch addrType { case AddrTypeIPv4: request.Address = v2net.IPAddress(payload.Value[:4]) payload.SliceFrom(4) case AddrTypeIPv6: request.Address = v2net.IPAddress(payload.Value[:16]) payload.SliceFrom(16) case AddrTypeDomain: domainLength := int(payload.Value[0]) request.Address = v2net.DomainAddress(string(payload.Value[1 : 1+domainLength])) payload.SliceFrom(1 + domainLength) default: return nil, nil, errors.New("Shadowsocks|UDP: Unknown address type") } request.Port = v2net.PortFromBytes(payload.Value[:2]) payload.SliceFrom(2) return request, payload, nil }
func (this *AuthChunkReader) Read() (*alloc.Buffer, error) { var buffer *alloc.Buffer if this.last != nil { buffer = this.last this.last = nil } else { buffer = alloc.NewBufferWithSize(4096).Clear() } if this.chunkLength == -1 { for buffer.Len() < 6 { _, err := buffer.FillFrom(this.reader) if err != nil { buffer.Release() return nil, io.ErrUnexpectedEOF } } length := serial.BytesToUint16(buffer.Value[:2]) this.chunkLength = int(length) - 4 this.validator = NewValidator(serial.BytesToUint32(buffer.Value[2:6])) buffer.SliceFrom(6) if buffer.Len() < this.chunkLength && this.chunkLength <= 2048 { _, err := buffer.FillFrom(this.reader) if err != nil { buffer.Release() return nil, io.ErrUnexpectedEOF } } } else if buffer.Len() < this.chunkLength { _, err := buffer.FillFrom(this.reader) if err != nil { buffer.Release() return nil, io.ErrUnexpectedEOF } } if this.chunkLength == 0 { buffer.Release() return nil, io.EOF } if buffer.Len() < this.chunkLength { this.validator.Consume(buffer.Value) this.chunkLength -= buffer.Len() } else { this.validator.Consume(buffer.Value[:this.chunkLength]) if !this.validator.Validate() { buffer.Release() return nil, transport.ErrCorruptedPacket } leftLength := buffer.Len() - this.chunkLength if leftLength > 0 { this.last = alloc.NewBufferWithSize(leftLength + 4096).Clear() this.last.Append(buffer.Value[this.chunkLength:]) buffer.Slice(0, this.chunkLength) } this.chunkLength = -1 this.validator = nil } return buffer, nil }