Can Erkin Acar wrote: > "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.
Great post, I guess many more people will benefit from this!