Bug 223208 - [pf] pf.conf syntax (:peer) rules load incorrectly
Summary: [pf] pf.conf syntax (:peer) rules load incorrectly
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 11.1-RELEASE
Hardware: amd64 Any
: --- Affects Some People
Assignee: freebsd-pf (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-10-24 12:37 UTC by Felix Z.
Modified: 2017-11-30 21:34 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Felix Z. 2017-10-24 12:37:33 UTC
Reproduced on amd64:
===================

ifconfig tun0 create
ifconfig tun0 10.0.0.1 10.0.0.2

1.
echo "pass in quick on lo0 route-to (tun0 10.0.0.2) inet" | pfctl -f -
pfctl -sr

pass in quick on lo0 route-to (tun0 10.0.0.2) inet all flags S/SA keep state

2. Problem:
echo "pass in quick on lo0 route-to (tun0 tun0:peer) inet" | pfctl -f -
pfctl -sr

pass in quick on lo0 route-to ( 10.0.0.2) inet all flags S/SA keep state


In second case PF silently drops the packets.
Comment 1 Kristof Provost freebsd_committer freebsd_triage 2017-10-25 20:46:51 UTC
I can't reproduce this on stable/11.

I see this:
% echo "pass in quick on lo0 route-to (tun0 tun0:peer) inet" | sudo pfctl -f -
% sudo pfctl -sr
pass in quick on lo0 route-to (tun0 10.0.0.2) inet all flags S/SA keep state
Comment 2 Felix Z. 2017-10-26 05:29:29 UTC
Hi Kristof.

Good news. And I checked once again:

root@:~ # uname -a
FreeBSD  11.1-RELEASE FreeBSD 11.1-RELEASE #0 r321309: Fri Jul 21 02:08:28 UTC 2017     root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64
root@:~ # echo "pass in quick on lo0 route-to (tun0 tun0:peer) inet" | pfctl -f -
root@:~ # pfctl -sr
pass in quick on lo0 route-to ( 10.0.0.2) inet all flags S/SA keep state
root@:~ #


root@:~ # uname -a
FreeBSD  11.1-STABLE FreeBSD 11.1-STABLE #0 r324751: Thu Oct 19 16:54:21 UTC 2017     root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64
root@:~ # echo "pass in quick on lo0 route-to (tun0 tun0:peer) inet" | pfctl -f -
root@:~ # pfctl -sr
pass in quick on lo0 route-to (tun0 10.0.0.2) inet all flags S/SA keep state

I want to believe the future versions will not have this bug.
Thanks.
Comment 3 Kristof Provost freebsd_committer freebsd_triage 2017-10-26 19:18:56 UTC
(In reply to Felix Z. from comment #2)
This is very strange though. I don't see any obvious changes in pf or pfctl or if_tun that would explain this and got included in 11.1.

Were the two results you posted from different machines, or the same one after an update?
Comment 4 Felix Z. 2017-10-30 15:39:43 UTC
I have found this bug on the hardware server (11.1-REL) and I have reproduced it on the VMWare VM (11.1-REL).

11.1-STABLE - live-CD on the same VM.
Comment 5 Kristof Provost freebsd_committer freebsd_triage 2017-11-03 13:27:07 UTC
I've tested 11.1 (r321309), and there too things work as expected.
There must be something else going on, but everything I've tried to reproduce this (no ip on tun0, deleting tun0, ...) fails to produce your symptoms.
Comment 6 Felix Z. 2017-11-05 09:37:05 UTC
Kristof, can you try add IPv6 prefix before IPv4? And check this again.

ifconfig tun0 create
ifconfig tun0 inet6 fe80::1%tun0/64
ifconfig tun0 10.0.0.1 10.0.0.2
Comment 7 Kristof Provost freebsd_committer freebsd_triage 2017-11-07 03:48:32 UTC
(In reply to Felix Z. from comment #6)
Yes, that seems to provoke it, even on CURRENT.
Hopefully I'll have the time to dig into this in a couple of days.
Comment 8 Kristof Provost freebsd_committer freebsd_triage 2017-11-12 02:32:33 UTC
(In reply to Kristof Provost from comment #7)
I still don't fully understand why this happens only if the tun0 interface has an IPv6 address assigned, but this fixes it.

diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index a47dfd04103..d9abd9a0610 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1392,6 +1396,7 @@ ifa_lookup(const char *ifa_name, int flags)
                                set_ipmask(n, 128);
                }
                n->ifindex = p->ifindex;
+               n->ifname = strdup(p->ifname);

                n->next = NULL;
                n->tail = n;
Comment 9 Felix Z. 2017-11-14 07:59:29 UTC
(In reply to Kristof Provost from comment #8)

Thanks!
It is interesting, what is a problem root?
Comment 10 Kristof Provost freebsd_committer freebsd_triage 2017-11-14 08:05:19 UTC
(In reply to Felix Z. from comment #9)
As I said, I still don't fully understand the problem.
I suspect this actually papers over the issue rather than fully fixing it. The pfctl code is ... complex, and I'm going to need more time to work this out.
Comment 11 Kristof Provost freebsd_committer freebsd_triage 2017-11-14 08:36:55 UTC
(In reply to Kristof Provost from comment #10)
Can you try this one instead?

diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 5652845d419..64015c7894b 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -4390,8 +4390,11 @@ route_host       : STRING                        {
                        $$->tail = $$;
                }
                | '(' STRING host ')'           {
+                       struct node_host *n;
+
                        $$ = $3;
-                       $$->ifname = $2;
+                       for (n = $3; n != NULL; n = n->next)
+                               n->ifname = strdup($2);
                }
                ;


The route_host parsing code set the interface name, but only for the first node_host in the list. If that one happened to be the inet6 address (given an inet rule) it'd get removed by remove_invalid_hosts() later on, and we'd have no interface name.
Comment 12 Felix Z. 2017-11-14 13:38:56 UTC
(In reply to Kristof Provost from comment #11)

Thank you very much! Everything works perfectly.

My investigation has ended around the parser.y, because I badly understand his work. But it was very interesting to me.
Comment 13 commit-hook freebsd_committer freebsd_triage 2017-11-15 12:27:24 UTC
A commit references this bug:

Author: kp
Date: Wed Nov 15 12:27:02 UTC 2017
New revision: 325850
URL: https://svnweb.freebsd.org/changeset/base/325850

Log:
  pfctl: teach route-to to deal with interfaces with multiple addresses

  The route_host parsing code set the interface name, but only for the first
  node_host in the list. If that one happened to be the inet6 address and the
  rule wanted an inet address it'd get removed by remove_invalid_hosts() later
  on, and we'd have no interface name.

  We must set the interface name for all node_host entries in the list, not just
  the first one.

  PR:		223208
  MFC after:	2 weeks

Changes:
  head/sbin/pfctl/parse.y
Comment 14 commit-hook freebsd_committer freebsd_triage 2017-11-30 21:22:20 UTC
A commit references this bug:

Author: kp
Date: Thu Nov 30 21:21:23 UTC 2017
New revision: 326413
URL: https://svnweb.freebsd.org/changeset/base/326413

Log:
  MFC r325850: pfctl: teach route-to to deal with interfaces with multiple addresses

  The route_host parsing code set the interface name, but only for the first
  node_host in the list. If that one happened to be the inet6 address and the
  rule wanted an inet address it'd get removed by remove_invalid_hosts() later
  on, and we'd have no interface name.

  We must set the interface name for all node_host entries in the list, not just
  the first one.

  PR:		223208

Changes:
_U  stable/11/
  stable/11/sbin/pfctl/parse.y
Comment 15 commit-hook freebsd_committer freebsd_triage 2017-11-30 21:33:34 UTC
A commit references this bug:

Author: kp
Date: Thu Nov 30 21:32:29 UTC 2017
New revision: 326414
URL: https://svnweb.freebsd.org/changeset/base/326414

Log:
  MFC r325850: pfctl: teach route-to to deal with interfaces with multiple addresses

  The route_host parsing code set the interface name, but only for the first
  node_host in the list. If that one happened to be the inet6 address and the
  rule wanted an inet address it'd get removed by remove_invalid_hosts() later
  on, and we'd have no interface name.

  We must set the interface name for all node_host entries in the list, not just
  the first one.

  PR:		223208

Changes:
_U  stable/10/
  stable/10/sbin/pfctl/parse.y