Fix UDP conn stuck on sniff

This change only avoids permanent hangs. We need to implement read deadlines for UDP conns in 1.10 for server inbounds.
This commit is contained in:
世界
2024-08-18 11:27:12 +08:00
parent 34a0281915
commit c8d8c56f87

View File

@@ -951,34 +951,57 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
}*/ }*/
if metadata.InboundOptions.SniffEnabled || metadata.Destination.Addr.IsUnspecified() { if metadata.InboundOptions.SniffEnabled || metadata.Destination.Addr.IsUnspecified() {
buffer := buf.NewPacket() var (
destination, err := conn.ReadPacket(buffer) buffer = buf.NewPacket()
destination M.Socksaddr
done = make(chan struct{})
err error
)
go func() {
sniffTimeout := C.ReadPayloadTimeout
if metadata.InboundOptions.SniffTimeout > 0 {
sniffTimeout = time.Duration(metadata.InboundOptions.SniffTimeout)
}
conn.SetReadDeadline(time.Now().Add(sniffTimeout))
destination, err = conn.ReadPacket(buffer)
conn.SetReadDeadline(time.Time{})
close(done)
}()
select {
case <-done:
case <-ctx.Done():
conn.Close()
return ctx.Err()
}
if err != nil { if err != nil {
buffer.Release() buffer.Release()
return err if !errors.Is(err, os.ErrDeadlineExceeded) {
} return err
if metadata.Destination.Addr.IsUnspecified() { }
metadata.Destination = destination } else {
} if metadata.Destination.Addr.IsUnspecified() {
if metadata.InboundOptions.SniffEnabled { metadata.Destination = destination
sniffMetadata, _ := sniff.PeekPacket(ctx, buffer.Bytes(), sniff.DomainNameQuery, sniff.QUICClientHello, sniff.STUNMessage) }
if sniffMetadata != nil { if metadata.InboundOptions.SniffEnabled {
metadata.Protocol = sniffMetadata.Protocol sniffMetadata, _ := sniff.PeekPacket(ctx, buffer.Bytes(), sniff.DomainNameQuery, sniff.QUICClientHello, sniff.STUNMessage)
metadata.Domain = sniffMetadata.Domain if sniffMetadata != nil {
if metadata.InboundOptions.SniffOverrideDestination && M.IsDomainName(metadata.Domain) { metadata.Protocol = sniffMetadata.Protocol
metadata.Destination = M.Socksaddr{ metadata.Domain = sniffMetadata.Domain
Fqdn: metadata.Domain, if metadata.InboundOptions.SniffOverrideDestination && M.IsDomainName(metadata.Domain) {
Port: metadata.Destination.Port, metadata.Destination = M.Socksaddr{
Fqdn: metadata.Domain,
Port: metadata.Destination.Port,
}
}
if metadata.Domain != "" {
r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
} else {
r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol)
} }
} }
if metadata.Domain != "" {
r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
} else {
r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol)
}
} }
conn = bufio.NewCachedPacketConn(conn, buffer, destination)
} }
conn = bufio.NewCachedPacketConn(conn, buffer, destination)
} }
if r.dnsReverseMapping != nil && metadata.Domain == "" { if r.dnsReverseMapping != nil && metadata.Domain == "" {
domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr) domain, loaded := r.dnsReverseMapping.Query(metadata.Destination.Addr)