Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 05 Jul 2010 15:26:07 +0400
From:      =?UTF-8?B?0JDQu9C10LrRgdC10Lkg0JPRg9GB0YzQutC+0LI=?= <adg@a-real.ru>
To:        freebsd-pf@freebsd.org
Subject:   pf route-to breaks pfil processing order
Message-ID:  <4C31C14F.9090001@a-real.ru>

next in thread | raw e-mail | index | archive | help
  Hello everyone.

Here's the problem: I need to forward some outgoing traffic to some 
local service. Traffic goes from my machine, not from local network, so 
i cannot use pf rdr rule, because it handles only incoming traffic. So, 
i'm using ipfw fwd rule for that:

# ipfw add 100 fwd 192.168.1.1,3127 ip from me to any 80 out

Here i redirect all outgoing traffic to another local proxy. (Nope, i 
can not use parent proxy). Everything is fine and works ok until I turn 
on pf and create route-to rule:

pass out on le0 out route-to (le0 192.168.1.254) from any to yandex.ru

Besides i'm using dummynet pipes for traffic shaping, so i need ipfw to 
process incoming packets before pf (and after pf for outgoing packets):

# ipfw disable firewall
# ipfw enable firewall

So, the problem goes here:

Here's the path of the outgoing packet inside the kernel:
ip_output() -> ... -> pfil_run_hooks() -> ... -> pf_test()

pf_test checks the packets, searches for state etc. Finally it checks if 
the packet should be redirected by "route-to", "reply-to" or "dup-to" 
options

pf.c, line 7125, pf_test():
------
   if (r->rt)
         /* pf_route can free the mbuf causing *m0 to become NULL */
         pf_route(m0, r, dir, ifp, s, &pd);

pf_route() itself performs some routing actions, rewrites nexthop and 
if, and (sic!) sends the packet _directly_ to the specified interface:

pf.c, line 6239, pf_route()
----
   PF_UNLOCK();
   error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro->ro_rt);
   PF_LOCK();

Original packet is deleted as if it's been blocked by firewall. So, any 
packet that is processed by pf_route would not then be processed with 
ipfw, would not be diverted into pipes etc. (actually i believe it 
wouldn't also be processed by altq). For example in my case the tcp 
connection wouldn't be redirected by ipfw.

So' heres the questions:
1) for what purpose pf_route invokes if_output by itself?
2) why rewritten packets can't be left intact so they would be normally 
processed by ipfw, altq etc and send to interfaces by uip_output()? I'm 
asking that because when ipfw redirects packets they are processed this 
way and nothing bad happens.

Thanks

--
Alexey Guskov
Areal company




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4C31C14F.9090001>