On Wed, Jul 02, 2003 at 04:59:10PM +0100, Steve Kersley wrote: > rdr on $INTERNAL proto tcp from <blocked> to any port 80 -> $web port 80
It depends on whether $web is on the internal or external network. If it is on the internal network, you're trying to 'bounce' or 'reflect' the connection out through the interface it arrived on, which has its own catches (see http://www.openbsd.org/faq/pf/rdr.html#reflect). If $web is on the external network, the student's connections must pass the internal and external interfaces. You're filtering on both, so you need a state entry on both interfaces. First, the connection arrives on the internal interface. It gets translated first (destination is replaced with $web), then filtered on the internal interface. > pass in quick on $INTERNAL proto tcp from <blocked> to port 80 flags S/SA keep state This is the first matching rule, and it has 'quick', so the connection passes the internal interface and creates state (covering the replies going back out through the internal interface). Now the connection (already translated) passes out through the external interface. > pass out on $EXTERNAL proto tcp flags S/SA keep state Matches, but no quick, so evaluation continues. But no further rules match, so this becomes the last matching rule. The connection passes and creates state. So, it should work. But rdr (like nat) has limits on a bridge. For instance, the bridge will decide what interface to send a frame out through based on the destination MAC address. In your case, that should be the MAC address of the default gateway (assuming the student tries to access an external web server). Then pf changes the destination IP address to $web. Then bridge sends the frame out through the interface it decided already, to the unchanged destination MAC address (and not $web's MAC address). The gateway might not forward the IP packet to $web (because it's on the same local network, for instance), and generate ICMP redirects instead. If this is what happens, there are several possible workarounds, like redirecting to 127.0.0.1 and either serving the page from there, or proxying from there to $web. You can also try to use 'fastroute' on the 'pass out on $EXTERNAL ...' rule that covers those redirected connections. This makes pf dispatch the the packet internally (creating a new ethernet header, with the right destination MAC address), instead of handing it back to the bridge code. 'route-to' should have a similar effect. To make sure, can you - tcpdump -nvvve on both interfaces and try to establish a connection from a blocked student host to an external web server? What do you see on the internal interface, what on the external? If you can limit the output to the packet related to one connection (and icmp errors), that would be great. - add 'log' to all block rules, repeat the first step, show us the blocked packets logged by pflogd(8)? - enable debug logging (pfctl -xm) and check /var/log/messages? Daniel
