func (v *CacheServer) Get(domain string) []net.IP { if ip, found := v.hosts[domain]; found { return []net.IP{ip} } domain = dnsmsg.Fqdn(domain) ips := v.GetCached(domain) if ips != nil { return ips } for _, server := range v.servers { response := server.QueryA(domain) select { case a, open := <-response: if !open || a == nil { continue } v.Lock() v.records[domain] = &DomainRecord{ A: a, } v.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 (ws *wsconn) pingPong() { pongRcv := make(chan int, 1) ws.wsc.SetPongHandler(func(data string) error { pongRcv <- 0 return nil }) go func() { for !ws.connClosing { ws.wlock.Lock() ws.wsc.WriteMessage(websocket.PingMessage, nil) ws.wlock.Unlock() tick := time.After(time.Second * 3) select { case <-pongRcv: case <-tick: if !ws.connClosing { log.Debug("WS:Closing as ping is not responded~" + ws.wsc.UnderlyingConn().LocalAddr().String() + "-" + ws.wsc.UnderlyingConn().RemoteAddr().String()) } ws.Close() } <-time.After(time.Second * 27) } return }() }
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.ErrCorruptedPacket } buffer.SliceFrom(AuthSize) return buffer, nil }
func (v *Connection) SetState(state State) { current := v.Elapsed() atomic.StoreInt32((*int32)(&v.state), int32(state)) atomic.StoreUint32(&v.stateBeginTime, current) log.Debug("KCP|Connection: #", v.conv, " entering state ", state, " at ", current) switch state { case StateReadyToClose: v.receivingWorker.CloseRead() case StatePeerClosed: v.sendingWorker.CloseWrite() case StateTerminating: v.receivingWorker.CloseRead() v.sendingWorker.CloseWrite() v.pingUpdater.interval = time.Second case StatePeerTerminating: v.sendingWorker.CloseWrite() v.pingUpdater.interval = time.Second case StateTerminated: v.receivingWorker.CloseRead() v.sendingWorker.CloseWrite() v.pingUpdater.interval = time.Second v.dataUpdater.WakeUp() v.pingUpdater.WakeUp() go v.Terminate() } }
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 current-atomic.LoadUint32(&this.lastPingTime) >= 3000 { seg := NewCmdOnlySegment() seg.Conv = this.conv seg.Command = CommandPing seg.ReceivinNext = this.receivingWorker.nextNumber seg.SendingNext = this.sendingWorker.firstUnacknowledged seg.PeerRTO = this.roundTrip.Timeout() if this.State() == StateReadyToClose { seg.Option = SegmentOptionClose } this.output.Write(seg) this.lastPingTime = current seg.Release() } // flash remain segments this.output.Flush() }
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 (v *TimedInboundRay) Release() { log.Debug("UDP Server: Releasing TimedInboundRay: ", v.name) v.Lock() defer v.Unlock() if v.server == nil { return } v.server = nil v.inboundRay.InboundInput().Close() v.inboundRay.InboundOutput().Release() v.inboundRay = nil }
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 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) buffer.Release() return err } } }
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) { p, err := proxy.CreateInboundHandler(ctx, proxyConfig) if err != nil { return nil, err } h := &AlwaysOnInboundHandler{ proxy: p, } nl := p.Network() pr := receiverConfig.PortRange address := receiverConfig.Listen.AsAddress() if address == nil { address = net.AnyIP } for port := pr.From; port <= pr.To; port++ { if nl.HasNetwork(net.Network_TCP) { log.Debug("Proxyman|DefaultInboundHandler: creating tcp worker on ", address, ":", port) worker := &tcpWorker{ address: address, port: net.Port(port), proxy: p, stream: receiverConfig.StreamSettings, recvOrigDest: receiverConfig.ReceiveOriginalDestination, tag: tag, allowPassiveConn: receiverConfig.AllowPassiveConnection, } h.workers = append(h.workers, worker) } if nl.HasNetwork(net.Network_UDP) { worker := &udpWorker{ tag: tag, proxy: p, address: address, port: net.Port(port), recvOrigDest: receiverConfig.ReceiveOriginalDestination, } h.workers = append(h.workers, worker) } } return h, nil }
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 }
func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn internet.Connection) error { log.Debug("Dokodemo: processing connection from: ", conn.RemoteAddr()) conn.SetReusable(false) ctx = proxy.ContextWithDestination(ctx, net.Destination{ Network: network, Address: d.address, Port: d.port, }) inboundRay := d.packetDispatcher.DispatchToOutbound(ctx) requestDone := signal.ExecuteAsync(func() error { defer inboundRay.InboundInput().Close() timedReader := net.NewTimeOutReader(d.config.Timeout, conn) chunkReader := buf.NewReader(timedReader) if err := buf.PipeUntilEOF(chunkReader, inboundRay.InboundInput()); err != nil { log.Info("Dokodemo: Failed to transport request: ", err) return err } return nil }) responseDone := signal.ExecuteAsync(func() error { v2writer := buf.NewWriter(conn) if err := buf.PipeUntilEOF(inboundRay.InboundOutput(), v2writer); err != nil { log.Info("Dokodemo: Failed to transport response: ", err) return err } return nil }) if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { inboundRay.InboundInput().CloseError() inboundRay.InboundOutput().CloseError() log.Info("Dokodemo: Connection ends with ", err) return err } return nil }
func (v *Dispatcher) Dispatch(ctx context.Context, destination v2net.Destination, payload *buf.Buffer, callback ResponseCallback) { // TODO: Add user to destString destString := destination.String() log.Debug("UDP|Server: Dispatch request: ", destString) inboundRay, existing := v.getInboundRay(ctx, destination) outputStream := inboundRay.InboundInput() if outputStream != nil { if err := outputStream.Write(payload); err != nil { v.RemoveRay(destString) } } if !existing { go func() { handleInput(inboundRay.InboundOutput(), callback) v.RemoveRay(destString) }() } }
func (v *Connection) flush() { current := v.Elapsed() if v.State() == StateTerminated { return } if v.State() == StateActive && current-atomic.LoadUint32(&v.lastIncomingTime) >= 30000 { v.Close() } if v.State() == StateReadyToClose && v.sendingWorker.IsEmpty() { v.SetState(StateTerminating) } if v.State() == StateTerminating { log.Debug("KCP|Connection: #", v.conv, " sending terminating cmd.") v.Ping(current, CommandTerminate) v.output.Flush() if current-atomic.LoadUint32(&v.stateBeginTime) > 8000 { v.SetState(StateTerminated) } return } if v.State() == StatePeerTerminating && current-atomic.LoadUint32(&v.stateBeginTime) > 4000 { v.SetState(StateTerminating) } if v.State() == StateReadyToClose && current-atomic.LoadUint32(&v.stateBeginTime) > 15000 { v.SetState(StateTerminating) } // flush acknowledges v.receivingWorker.Flush(current) v.sendingWorker.Flush(current) if current-atomic.LoadUint32(&v.lastPingTime) >= 3000 { v.Ping(current, CommandPing) } // flash remain segments v.output.Flush() }
// Private: Visible for testing. func (v *UDPNameServer) HandleResponse(payload *buf.Buffer) { msg := new(dns.Msg) err := msg.Unpack(payload.Bytes()) 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()) v.Lock() request, found := v.requests[id] if !found { v.Unlock() return } delete(v.requests, id) v.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 (v *ConnectionCache) Get(dest string) net.Conn { v.Lock() defer v.Unlock() list, found := v.cache[dest] if !found { return nil } firstValid := FindFirstValid(list) if firstValid == -1 { delete(v.cache, dest) return nil } res := list[firstValid].conn list = list[firstValid+1:] v.cache[dest] = list log.Debug("WS:Conn Cache used.") return res }
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: Visible for testing. func (v *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 { var id uint16 v.Lock() if len(v.requests) > CleanupThreshold && v.nextCleanup.Before(time.Now()) { v.nextCleanup = time.Now().Add(CleanupInterval) go v.Cleanup() } for { id = uint16(dice.Roll(65536)) if _, found := v.requests[id]; found { continue } log.Debug("DNS: Add pending request id ", id) v.requests[id] = &PendingRequest{ expire: time.Now().Add(time.Second * 8), response: response, } break } v.Unlock() return id }
func (this *UDPServer) Dispatch(session *proxy.SessionInfo, payload *alloc.Buffer, callback UDPResponseCallback) { source := session.Source destination := session.Destination // TODO: Add user to destString 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(session) 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 *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.RequestHeader, error) { buffer := make([]byte, 512) _, err := io.ReadFull(reader, buffer[:protocol.IDBytesLen]) if err != nil { log.Info("Raw: Failed to read request header: ", err) return nil, io.EOF } user, timestamp, valid := this.userValidator.Get(buffer[:protocol.IDBytesLen]) if !valid { return nil, protocol.ErrInvalidUser } timestampHash := md5.New() timestampHash.Write(hashTimestamp(timestamp)) iv := timestampHash.Sum(nil) account := user.Account.(*vmess.Account) aesStream := crypto.NewAesDecryptionStream(account.ID.CmdKey(), iv) decryptor := crypto.NewCryptionReader(aesStream, reader) nBytes, err := io.ReadFull(decryptor, buffer[: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[0], } if request.Version != Version { log.Info("Raw: Invalid protocol version ", request.Version) return nil, protocol.ErrInvalidVersion } this.requestBodyIV = append([]byte(nil), buffer[1:17]...) // 16 bytes this.requestBodyKey = append([]byte(nil), buffer[17:33]...) // 16 bytes this.responseHeader = buffer[33] // 1 byte request.Option = protocol.RequestOption(buffer[34]) // 1 byte + 2 bytes reserved request.Command = protocol.RequestCommand(buffer[37]) request.Port = v2net.PortFromBytes(buffer[38:40]) switch buffer[40] { case AddrTypeIPv4: nBytes, err = io.ReadFull(decryptor, buffer[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[41:45]) case AddrTypeIPv6: nBytes, err = io.ReadFull(decryptor, buffer[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[41:57]) case AddrTypeDomain: nBytes, err = io.ReadFull(decryptor, buffer[41:42]) if err != nil { log.Debug("VMess: Failed to read target domain (", nBytes, " bytes): ", nBytes, err) return nil, err } domainLength := int(buffer[41]) if domainLength == 0 { return nil, transport.ErrCorruptedPacket } nBytes, err = io.ReadFull(decryptor, buffer[42:42+domainLength]) if err != nil { log.Debug("VMess: Failed to read target domain (", nBytes, " bytes): ", nBytes, err) return nil, err } bufferLen += 1 + domainLength request.Address = v2net.DomainAddress(string(buffer[42 : 42+domainLength])) } nBytes, err = io.ReadFull(decryptor, buffer[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[:bufferLen]) actualHash := fnv1a.Sum32() expectedHash := serial.BytesToUint32(buffer[bufferLen : bufferLen+4]) if actualHash != expectedHash { return nil, transport.ErrCorruptedPacket } return request, nil }