[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-misc
Subject:    Re: PF + ATLQ on openbsd 4.4
From:       Can Erkin Acar <canacar () openbsd ! org>
Date:       2008-11-27 7:32:43
Message-ID: 492E4D1B.90203 () openbsd ! org
[Download RAW message or body]

"Damian Higgins" wrote:
> Hi Stuart,
> 
> First off, thank you for the feedback you provided. Unfortunately, you
> misunderstood the issue I'm encountering because you haven't read my
> entire post. So, I'll try to make a brief post of the previous
> message, to make it easier to read, and hope you will have the
> patience to read it this time :).

Perhaps you are misunderstanding how pf works. Instead of trying to 
solve *your* problem, I will try to describe how pf+altq works, and it 
will be up to you to figure out how to accomplish what you want to do.


> First, some concepts of queueing/policing I learned from my previous
> experience in other environments(correct me if I'm wrong) :

First forget about other environments, especially Linux. I have deleted 
the rest of your post, since it does not really matter what you or other 
environments think about how traffic shaping should be done. If you are 
using OpenBSD, try to understand how it is done with pf+altq.


Here are the basic rules for pf. You may already know some of them, but 
please bear with me. You may learn something new:

# Filtering is stateful in pf, and it is strongly recommended to keep it 
that way (ie. use 'no state' only if you really know what you are 
doing). The S/SA flags being default also have strong reasons.

# Think of 'state' as a 'connection'. This is especially true for TCP. 
Use systat(1) or pftop (from ports) to see the states. A state *sees* 
packets in *both* directions that belong to a particular traffic.

# If a packet matches a state, no rules are evaluated *hint*

# If a packet does not match an existing state but matches a rule, a 
state is created. Further packets of this 'connection' will just match 
the state, and bypass ruleset evaluation.

# Loading pf rules with 'pfctl -f pf.conf' does not clear existing 
states (unless you also use the proper flush command line switch) *hint*

# A connection that traverses an OpenBSD router usually enters pf twice 
(at inbound and outbound interface) and provided there are appropriate 
pass rules, it will create states on both interfaces. That is, every 
packet of a connection both inbound and outbound will have two states 
associated with it.

# A connection that originates from or terminates on an OpenBSD box will 
have a single state associated with it.

# NAT/RDR rules are evaluated before filter rules, and address 
translation happens *before* rules are evaluated, so rules are always 
checked against translated packets (NAT on incoming, RDR on outgoing).


And the basic rules for altq:

#  altq *only* filters *outbound* packets on an interface. This is 
usually not related to the direction of the connection itself.

## Example: if you want to restrict internal hosts HTTP downloads from 
outside servers, these *incoming* HTTP payloads have to be filtered at 
the interface facing the hosts. This also means there is no way to apply 
altq to limit downloads that are initiated from the OpenBSD gateway itself.

## Example: if you want to increase the priority of the e-mails that 
your mail server sends, use the interface facing your ISP.

# Each packet, as it passes through the network stack can be assigned a 
'queue-id'. This queue id determines which queue the packet is placed as 
it *leaves* the box. If a packet has no queue-id, then it is assigned to 
the default queue.

# The queue ids are mapped to queue names, that is, queues that carry 
the same name have the same id.


And this is how PF assigns packets to queues:

# Each rule has two queue ids, one for normal one for high-priority 
packets as specified by the rule definition (see pf.conf for details). 
If you specified a single queue in your rule definition, that means both 
ids are equal.

# By default the packet has no queue-id assigned.

# If a packet matches a rule, and that rule specifies a queue, the 
packet queue-id is replaced by the queue id specified by the rule. If 
the rule has no queue specified, the packet queue-id is not changed 
(does not revert back to default).

# If a packet matches a state, the rule that created the state is 
consulted (as above).

# Since a packet can match up to two rules/states as it traverses a 
router, the last assigned queue wins (as the queues only take effect as 
the packet exits the router).

# Note that, since a state matches packets in both directions, packets 
in both directions will be assigned queue ids by a given state.  That 
makes it possible to create a state with a rule on one interface, and 
have the reply packets assigned to the same queue specified by that rule 
on a different interface.


Finally, here are some additional things to think about or investigate:

# You can do a lot of creative and flexible stuff with 'tag' and 
'tagged' keywords in your ruleset. Assigning queues by 'pass quick 
tagged XYZZY queue MAGIC' type of rules is much easier to keep track of.

# What happens if you change the ruleset while traffic is flowing? 
Hint: existing states will point to a default 'empty' rule.

# What happens when states are synchronized by pfsync(4) between two 
carp(4)'ed firewalls?  Hint: The mapping used to get lost, so if the 
firewall failed over queues would not work for 'synced' states although 
they would work nor new states. How this is handled now in -current is 
left as an exercise.


Now, armed with the above, you should be able to explain the behaviour 
you see, and design a filter that does what you want.

Have fun ...


Can



PS: pflog, tcpdump and pftop/systat are your friends.

PPS: You can always look at the source code to see how things work.

PPPS: When asking questions, give as much context information as possible.

PPPPS: Some of the above rules may have changed slightly after the 
recent overhaul of pf state handling. There may also be bugs and/or 
regressions, so a good bug report really helps a lot. A report that says 
"it works with 4.3 but not with 4.4 or -current" goes a long way to 
point out a regression.

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic