Re: Odd ipfw behavior with UDP query on the same host

From: Rodney W. Grimes <freebsd-rwg_at_gndrsh.dnsmgr.net>
Date: Thu, 08 Jun 2023 16:16:18 UTC
> > 
> > 
> > > On Jun 4, 2023, at 12:07 PM, Rodney W. Grimes <freebsd-rwg@gndrsh.dnsmgr.net> wrote:
> > > 
> > >> Hey ipfw folks ? Im skipping questions@ and asking this directly here,
> > >> 
> > >> FreeBSD 12.4 (amd64)
> > >> 
> > >> Assume a partial firewall ruleset like this:
> > >> 
> > >> 00300  0   0 allow ip from any to any via lo0
> > >> 00400  0   0 allow ip from any to any via lo1
> > >> 00500  0   0 deny ip from any to 127.0.0.0/8 in
> > >> 00600  0   0 deny ip from any to ::/64 in
> > >> 01600  1 174 allow ip from any to me 53 in // DNS queries
> > > 
> > > 1650 x x allow ip from me 53 to me in // DNS local answers
> 
> I strongly suggest this is a correct fix, as it does not
> depend on any routing entries.

On second thought, thats wrong, that opens a spoof ability
by allowing an external packet to enter via em0 that is
from our address.

> 
> > >> 01700  1 293 allow ip from me 53 to any out // DNS responses
> > >> 03000  0   0 reset log ip from any to any
> > >> 65535  0   0 allow ip from any to any
> > >> 
> > >> For some reason, with the above, I?m able to query a DNS server living on my own (public) ipv6 interface, i,e:
> > >> 
> > >> dig @2001:b00b:6b:2::53 version.bind CH TXT:
> > >> ;communications error to 2001:b00b:6b:2::53#53: timed out
> > >> 
> > >> This is not a bind config problem.  Bind answers from outside and everywhere else but itself.
> > > 
> > > We can argue about that, but given the below log entries your not using ::1
> > > for local ipv6 dns, but your using your interface ipv6 address.
> > > What is in your /etc/resolv.conf file?
> > 
> > That doesn?t matter, this isn?t the box?s local resolver, it?s an authoritative server that we?re sending test queries against to make sure it?s answering.  They work from off-box but not on-box.
> 
> Ok, that simplifies things.
> 
> > 
> > I?m posting from my personal account, but you could say my day job is very familiar with dig and bind. :)
> > 
> > >> ==
> > >> 
> > >> If I change rule 1600 to simply be "allow ip from any to me 53? it works.  
> > >> 
> > >> If I do ipfw disable firewall it works.  
> > >> 
> > >> Localhost always works.
> > > As long as ipv4 is done first, if you flip the order of preference for
> > > ipv4 and ipv6 it probably stops working.
> > 
> > It does not.  See below, I test all iterations of tcp/udp ipv4/ipv6 box ip/localhost ? the only failing one is interface-ip, ipv6, udp
> 
> Since your using dig and expicityly giving an IP address it elminates this source of potential problems.
> 
> > > 
> > >> 
> > >> Using the ipv4 address works.
> > >> 
> > >> ==
> > >> 
> > >> It?s only when using an ipv6 interface ip on the same box that this breaks.  TCP also works, this only seems to be a UDP issue.
> > > 
> > > How are you testing the TCP?
> > 
> > Same as we?re testing the UDP.  With dig.
> > 
> > dig +short @boxname version.bind CH TXT
> > ;; communications error to 2001:b00b:1:f::88#53: timed out
> > ;; communications error to 2001:b00b:1:f::88#53: timed out
> > ;; communications error to 2001:b00b:1:f::88#53: timed out

Can we get verbose ipfw logging during this set of transactions,
both allow and deny. 

> > "9.16.40"
> > $ dig +short @localhost version.bind CH TXT
> > "9.16.40"
> > $ dig +short +tcp @localhost version.bind CH TXT
> > "9.16.40"
> > $ dig +short +tcp @boxname version.bind CH TXT
> > "9.16.40"
> > $ dig -4 +short +tcp @boxname version.bind CH TXT
> > "9.16.40"
> > $ dig -4 +short @boxname version.bind CH TXT
> > "9.16.40"
> > $ dig -4 +short @localhost version.bind CH TXT
> > "9.16.40"
> > $ dig -4 +short +tcp @localhost version.bind CH TXT
> > "9.16.40"
> 
> Has bind opened a socket on 2001:b00b:1:f::88#53?
> netstat -an
> 
> > 
> > > 
> > >> My best guess is something about the ?inbound/outbound? determination logic is weird in ipv6.
> > >> 
> > >> My log rule shows: 
> > >> Jun  3 23:44:35 box kernel: ipfw: 3000 Deny UDP [2001:b00b:6b:2::53]:53 [2001:b00b:6b:2::53]:26588 in via em0
> > >> Jun  3 23:44:40 box kernel: ipfw: 3000 Deny UDP [2001:b00b:6b:2::53]:53 [2001:b00b:6b:2::53]:32389 in via em0
> > > 
> > > The clue as to what is wrong is right here ----------------------------------------------------------^^^^^^^^^^
> > > 
> > > The src and dst IP address of those packets is the same, and I am going to assume that it is the
> > > interface address of em0.  Nothing in your rule allows these packets through, which are local
> > > answers from DNS to local queries made to that interface IP address.
> > 
> > Given the routing table below (which is for a different box with a similar route), why was this not sent via lo0?
> 
> That is a good question, given your added data I would think it should be via lo0.
> I would again just suggest adding
> allow UDP from me 53 to me any 
> 
> > 
> > > 
> > >> 
> > >> ipv4 doesn?t show this problem.  Subnet masks and the like are correct.
> > > 
> > > ipv4 has a special loopback route on lo0 that does not exist for ipv6.
> > > Look at:
> > > 	netstat -rn
> > 
> > Here you go, annotations mine.  I?m not seeing it.
> > 
> > Internet:
> > Destination        Gateway            Flags     Netif Expire
> > default            149.99.1.1         UGS        igb0 (A)
> > 127.0.0.1          link#3             UH          lo0 (B)
> > 149.99.1.0/25      link#1             U          igb0 (C)
> > 149.99.1.88        link#1             UHS         lo0 (D)
> > 
> > Internet6:
> > Destination                       Gateway                       Flags     Netif Expire
> > ::/96                             ::1                           UGRS        lo0 (no v4 equivalent)
> > default                           2001:b00b:1:f::1               UGS        igb0 (A)
> > ::1                               link#3                        UH          lo0 (B)
> > ::ffff:0.0.0.0/96                 ::1                           UGRS        lo0 (No v4 equivalent)
> > 2001:b00b:1:f::/64                 link#1                        U          igb0 (C)
> > 2001:b00b:1:f::88                  link#1                        UHS         lo0 (D)
> > (plus a bunch of fe80 stuff)
> > fe80::/10                         ::1                           UGRS        lo0
> > fe80::%igb0/64                    link#1                        U          igb0
> > fe80::ae1f:6bff:fe83:2380%igb0    link#1                        UHS         lo0
> > fe80::%lo0/64                     link#3                        U           lo0
> > fe80::1%lo0                       link#3                        UHS         lo0
> > ff02::/16                         ::1                           UGRS        lo0
> > 
> > 
> > A: default route (statically configured, main interface)
> > B: Loopback (yes, v6 land has an additional loopback subne, lo0t)
> > C: route for the interface block (which shows as the interface name)
> > D: route for my own ip (which shows as lo0)
> > 
> > Now, if BIND is doing something wrong with the interface selection logic, I?d love to know about that too, but it should just be honoring the kernel routing table.
> > 
> > The keyword ?in? seems to be problematic, and the manpage doesn?t cover what constitutes an ?inbound? or ?outbound? rule in this case (where it?s the same box).  Trying to search the manpage for ?in? is not helpful, but this is all I see.
> 
> Ahhh... umm.... yea.. lightbulbs going off now.  There is something screwy about in/out and loopback interfaces, and though there is a loopback route to the ipv6 address I think the actual path through the kernel well cause these packets to appear as if they come from the em0 device.
> 
> 
> > 
> > In cases like this, do these rules go through ipfw twice?
> > 
> >     in | out
> >              Matches incoming or outgoing packets, respectively.  in and out
> >              are mutually exclusive (in fact, out is implemented as not in).
> > 
> > 
> > -Dan
> > 
> > 
> > 
> 
> -- 
> Rod Grimes                                                 rgrimes@freebsd.org
> 

-- 
Rod Grimes                                                 rgrimes@freebsd.org