Hi. I'm a long-time Linux and OpenBSD user. Used Linux for my router/firewall for a long time, then switched to OpenBSD 2.6 with IPF. I moved up to OpenBSD 3.4 with PF and ALTQ when it was new, and am still running it.

My firewall/router works great, but successful traffic shaping has eluded me for some time.

I bought Jacek Artymiak's book to try to get a grasp on it, and have read FAQs, examples and man pages until I'm blue in the face.


Setup:

I have a Cisco 678 DSL modem with 1.5Mb down and 672K up with one static IP. It NATs and forwards all traffic on to the OBSD box right behind it. That machine has four interfaces, WAN (to the Cisco), LAN (to my local net, workstations, mail/SSH/DNS server), DMZ (to my Web/FTP server) and VOIP (to my VOIP phones).

I've tried to implement traffic shaping with queues (using priq for now until I get it working, then maybe move up to CBQ). However, everytime I think I get it figured out, I realize I'm overlooking something. Chris 'Xenon' Hanson <[EMAIL PROTECTED]>

I understand that queues are only effective for throttling traffic going outbound on an interface, for obvious reasons. But, by throttling the traffic leaving the router towards my inside machines, I effectively throttle the ACKs going back out, and therefore the new traffic coming in.

  This makes sense. There's some things I can't seem to get a grip on:

I need an outbound queue that is limited to my upstream bandwidth (672K). Outgoing traffic needs to be put into the prioritized queues here. I've been told that queuing only works on pass out rules, but that doesn't make any sense. Sometimes the only place to identify which outbound queue the traffic needs to go into is at the pass in rule on the inbound interface. For example, my VOIP gear is all on a subnet and interface of its own. I want it to end up in the high-priority queue on the outbound interface. So, I need to do something like

pass in quick on $phone_if keep state queue(up_phone)

Is that right though? The up_phone queue is on the $ext_if, and the pass in rule is referring to the $phone_if. It looks to me (from the traffic counters in pfctl -vvsq) that no traffic is ending up in the outbound up_phone queue, so it must not be right. There are lots of examples that show queue assignment on a pass in rule. I assumed that if I marked it for a given queue, that when it ended up going out on the interface that had that queue that it would end up in that queue.

I also need an inbound queue to limit my downstream speed so we don't choke out. Most examples assume you have one $ext_if and one $int_if, and they create the outbound queue on $ext_if and the inbound queue on $int_if and all is happy.

But I have three internal interfaces, WAN, DMZ and VOIP. I don't want to create a 1.5Mb queue on each, because together they _share_ 1.5Mb of bandwidth coming from the DSL line. Where do I create this queue?

Thirdly, if I create a 1.5Mb queue on the inbound interfaces to keep by DSL line from getting swamped, it's going to throttle all traffic exiting the internal interface, right? So, if I try to copy a large file from my LAN to the DMZ webserver, I'm gonna be choked down to some fraction of 1.5Mbps when it's a wide-open 100Mbps link.

As I understand, if I do queuing on an interface, one of the queues on that interface is always the default and traffic not explicitly assigned to a queue goes into the default.

Finally, I'm not clear on how NAT works with ALTQ. Jacek's book says (p218):

What you can do, is add ALTQ queues and pass out rules for interfaces connection the firewall host to the internal network segments. However, these limits will only work for connections initiated by external hosts.
Connections initiated by inside hosts and NAT-ed will not match those pass out rules, because they will be passed without checking thanks to the state mechanism invoked by the NAT rules (nat, binat, or rdr). This is why some users will be able to use all of
the available bandwidth even if you set hard limits, these limits apply to outbound packets, not inbound ones. The solution is to put a router before the firewall ... and implement ALTQ/filtering rules on the interface connecting

.. to the firewall.

So, despite all of my clever traffic shaping, if I fire up a web browser on a machine on the LAN and start a big HTTP download (NATed through the firewall) it'll just go ahead and eat all of my bandwidth anyway? And the only solution is to add a second router?





I'm guessing I just have an inaccurate picture of how this is all supposed to work.

I'd be happy to post my pf.conf, but I know it's completely bogus as far as traffic control goes, so I'm not sure how much good it would be until I make some major changes. Also, I'm not sure what sanitizing it might need.


My goal is to make sure that my real-time and interactive services (VOIP, SSH) take priority over my bulk data (web, mail, FTP, etc). Doesn't seem like it ought to be as hard as I'm making it...



Thanks in advance for any advice. I'd be happy to post my finished pf.conf as an example for others, once it works, because I haven't ever found a good example of what I'm trying to do.



I also have an interest in your setup.. I only have a mail server and a voip phone..

My setup only has 2 NICs (InteNetPCs only have 1 PCI slot so my mailserver (linux) and
voip phone are on my local lan)
I too have done quite bit of reading and still can't seem to get my "head" around it..
Agree with you about not being very many examples on the internet.. believe me I too
have looked..
This hasn't really changed in the past 2 years that I have been away from OpenBSD.. on
the other hand.. the Linux world has exploded.. sorry off topic..


oh what the hell.. here is my pf.conf.. maybe you can get some ideas from it..
the rules for my mailserver work.. but the ssh from the outside does not.. not sure why..


also.. the altq rules seem to have improved my voip phone's clarity (read: no more echo) but
again not sure if they are correct (based them off examples from the internet and openbsd's site)


hth
charles

pf.conf (OpenBSD 3.3) soon to be OpenBSD 3.7..
******************************************
# ---------------------
# Generic configuration
# ---------------------

set limit { states 2500, frags 5000 }
set optimization aggressive
# Enabling the block-policy return show "closed ports" http://scan.sygatetech.com/quickscan.html
# set block-policy return
set fingerprints "/etc/pf.os"


# --------------------
# Variable definitions
# --------------------

 ext_if = "fxp0"
 int_if = "xl0"
 mail = "192.168.1.2"
 voipbox = "192.168.1.7"
 voip_tcp   = "5060"
 voip_udp   = "{ 5060, 4569, 5036, 9999 >< 20001, 2727 }"
 tcp_services = "{ 22, 113 }"
 smtp2 = "2525"

# read the pf-howto for details.
# TCP_OPTIONS = "flags S/SAFR keep state"
 TCP_OPTIONS = "flags S/SA keep state"

# http://www.iana.org/assignments/ipv4-address-space
# http://rfc.net/rfc1918.html
 reserved = " {
 0.0.0.0/8,      10.0.0.0/8,     20.20.20.0/24,  127.0.0.0/8,
 169.254.0.0/16, 172.16.0.0/12,  192.0.2.0/24,   192.168.0.0/16,
 224.0.0.0/3  } "

#Tables
 table <blacklists> persist file "/etc/tables/blacklists"

# -----------
# scrub rules
# -----------

# scrub in all # borks with linux nfs
 scrub in on $ext_if all

# ----------
# altq rules
# ----------

# These are very simple altq rules.
# All they do is give priority to outgoing voip traffic.
 altq on $ext_if cbq bandwidth 380Kb \
       queue { std_out, voip_out, voip_in, ack_out}

 queue std_out            cbq(red default)
 queue voip_out priority 4 cbq(red)
 queue voip_in priority 4 cbq(red)
 queue ack_out priority 6 cbq(red)

# ---------
# Nat and Rdr rules
# ---------

 nat on $ext_if inet from $int_if/24 to any -> ($ext_if)

# Redirect to Mailserver
 rdr on $ext_if proto tcp from any to $ext_if port $smtp2 -> $mail
 rdr on $ext_if proto tcp from any to $ext_if port https -> $mail

# --------
# pf rules
# --------

# Default policy.
# remove the log-keyword if you ever get ddossed.
 block in  log on $ext_if all

# ---------------
# SPOOFERS
# ---------------

# Block spoofing.
 block in  quick on $ext_if from $reserved to any
 block out quick on $ext_if from $reserved to any

# antispoof _has_ to be preceeded with pass in quick on lo0 all.
 pass in quick on { lo0, lo1 } all
 antispoof for { lo0, $int_if, $ext_if }

# ----
# ICMP
# ----

# The inet keyword means ipv4 so ipv6 pings will be blocked.
pass out on $ext_if inet proto icmp all icmp-type 8 code 0 keep state queue std_out
# pass in on $ext_if inet proto icmp all icmp-type 8 code 0 keep state



# --- # UDP # ---

# outgoing UDP
 pass out quick on $ext_if proto udp all keep state queue std_out


# Outgoing Voip always gets the highest priority. pass out quick on $ext_if proto udp from any to any port $voip_udp \ keep state queue ( voip_out, ack_out )

# ---
# TCP
# ---

# Incoming TCP

# First the nat'ed traffic

# The rest of all this trafic should be aimed at $ext_if so We can cut
# of the rest. Broadcasts and other garbage. Saves a lot of fubar in
# the logs

 block in on $ext_if inet from any to ! ($ext_if)

# ssh
pass in on $ext_if inet proto tcp from any to any port ssh \
      $TCP_OPTIONS

# Pass rule for Mailserver

pass in quick on $ext_if inet proto tcp from any to any port $smtp2 \
      $TCP_OPTIONS
pass in quick on $ext_if inet proto tcp from any to any port https \
      $TCP_OPTIONS

# Outgoing TCP

# Outgoing Voip always gets the highest priority.
 pass out quick on $ext_if proto tcp from any to any port $voip_tcp \
      keep state queue ( voip_out, ack_out )

 pass out quick on $ext_if proto tcp all keep state \
      queue std_out







Reply via email to