Skip to content

Commit

Permalink
Stream: don't flush empty buffers created for read errors.
Browse files Browse the repository at this point in the history
When we generate the last_buf buffer for an UDP upstream recv error, it does
not contain any data from the wire. ngx_stream_write_filter attempts to forward
it anyways, which is incorrect (e.g., UDP upstream ECONNREFUSED will be
translated to an empty packet).

This happens because we mark the buffer as both 'flush' and 'last_buf', and
ngx_stream_write_filter has special handling for flush with certain types of
connections (see d127837c714f, 32b0ba4855a6).  The flags are meant to be
mutually exclusive, so the fix is to ensure that flush and last_buf are not set
at the same time.

Reproduction:

stream {
    upstream unreachable {
        server     127.0.0.1:8880;
    }
    server {
        listen     127.0.0.1:8998 udp;
        proxy_pass unreachable;
    }
}

1 0.000000000    127.0.0.1 → 127.0.0.1    UDP 47 45588 → 8998 Len=5
2 0.000166300    127.0.0.1 → 127.0.0.1    UDP 47 51149 → 8880 Len=5
3 0.000172600    127.0.0.1 → 127.0.0.1    ICMP 75 Destination unreachable (Port
unreachable)
4 0.000202400    127.0.0.1 → 127.0.0.1    UDP 42 8998 → 45588 Len=0

Fixes d127837c714f.
  • Loading branch information
bavshin-f5 committed May 23, 2022
1 parent 80fc2dd commit d7994be
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion src/stream/ngx_stream_proxy_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -1737,7 +1737,7 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream,

cl->buf->temporary = (n ? 1 : 0);
cl->buf->last_buf = src->read->eof;
cl->buf->flush = 1;
cl->buf->flush = !src->read->eof;

(*packets)++;
*received += n;
Expand Down

0 comments on commit d7994be

Please sign in to comment.