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.
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
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.
(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?
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.
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.
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
(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.
(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;
(In reply to Kristof Provost from comment #8) Thanks! It is interesting, what is a problem root?
(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.
(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.
(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.
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
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
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