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:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user