On Tue, Jun 21, 2016 at 16:08 +0200, Alexander Bluhm wrote:
> On Tue, Jun 21, 2016 at 02:45:42PM +0200, Mike Belopuhov wrote:
> > You're testing the sequence number
> > of the new state with an existing one which has seen some
> > traffic.. Are you sure this is correct?
>
> This is exactly what the stack does to distinguish between packets
> that belong to an old connection and between a new one.
>
Right, I've found it, but how can you tell that this is a new
connection if iss changes a lot and you just test if it's greater
than? The actual test should be if it's ouside of the window,
isn't it?
> > But
> > since they don't belong to the same connection, this is
> > inherently incorrect.
>
> Here is my logical error. The receiving TCP stack only thinks it
> is a reuse of an existing connection. In this case, the sender is
> reponsible to increase the initial sequence number. But the sender
> has a different port or even a different IP. It is only NAT reusing
> the port and address which confuses the stack.
>
Yep.
> So my diff fixes it because now pf state key attach and tcp reuse
> are confused in the same way.
>
Rather a bit sloppy, but yeah.
> > Unless I'm wrong, I have to retract my OK and ask you to fix
> > the sport bit instead.
>
> Yes, fixing it in pf_get_sport() is more correct. I will try
> to make a diff.
>
Cool.
> It would help a lot debugging such problems, if we would have more
> log messages. So extend the existing log to the reuse case in
> pf_state_key_attach() ?
>
> ok?
>
Sure.
> bluhm
>
> Index: net/pf.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
> retrieving revision 1.977
> diff -u -p -r1.977 pf.c
> --- net/pf.c 15 Jun 2016 11:49:34 -0000 1.977
> +++ net/pf.c 21 Jun 2016 13:50:01 -0000
> @@ -669,34 +669,34 @@ pf_state_key_attach(struct pf_state_key
> si->s->key[PF_SK_STACK]->af &&
> sk->af == si->s->key[PF_SK_STACK]->af &&
> si->s->direction != s->direction))) {
> + int reuse = 0;
> +
> if (sk->proto == IPPROTO_TCP &&
> si->s->src.state >= TCPS_FIN_WAIT_2 &&
> - si->s->dst.state >= TCPS_FIN_WAIT_2) {
> + si->s->dst.state >= TCPS_FIN_WAIT_2)
> + reuse = 1;
> + if (pf_status.debug >= LOG_NOTICE) {
> + log(LOG_NOTICE,
> + "pf: %s key attach %s on %s: ",
> + (idx == PF_SK_WIRE) ?
> + "wire" : "stack",
> + reuse ? "reuse" : "failed",
> + s->kif->pfik_name);
> + pf_print_state_parts(s,
> + (idx == PF_SK_WIRE) ? sk : NULL,
> + (idx == PF_SK_STACK) ? sk : NULL);
> + addlog(", existing: ");
> + pf_print_state_parts(si->s,
> + (idx == PF_SK_WIRE) ? sk : NULL,
> + (idx == PF_SK_STACK) ? sk : NULL);
> + addlog("\n");
> + }
> + if (reuse) {
> si->s->src.state = si->s->dst.state =
> TCPS_CLOSED;
> /* remove late or sks can go away */
> olds = si->s;
> } else {
> - if (pf_status.debug >= LOG_NOTICE) {
> - log(LOG_NOTICE,
> - "pf: %s key attach "
> - "failed on %s: ",
> - (idx == PF_SK_WIRE) ?
> - "wire" : "stack",
> - s->kif->pfik_name);
> - pf_print_state_parts(s,
> - (idx == PF_SK_WIRE) ?
> - sk : NULL,
> - (idx == PF_SK_STACK) ?
> - sk : NULL);
> - addlog(", existing: ");
> - pf_print_state_parts(si->s,
> - (idx == PF_SK_WIRE) ?
> - sk : NULL,
> - (idx == PF_SK_STACK) ?
> - sk : NULL);
> - addlog("\n");
> - }
> pool_put(&pf_state_key_pl, sk);
> return (-1); /* collision! */
> }