The following file is an example of my OpenBSD's pf configuration file. If you don't know pf is the firewall (packet filter) created by the OpenBSD team. The file is commented pretty well so I'm going to let it speak for itself. Incoming services redirected or local are ssh, http, https, smtp, and pop3s. All are filtered by ip except for http and smtp. Local services are redirected to localhost on which they are listening. This is in case pf gets disabled somehow. If it did the services would not be left unfiltered. They just can't be contacted.
I use HFSC for prioritizing my traffic. Tcp ack's get the highest priority so we don't saturate our download bandwidth. Ssh interactive gets the next priority so there is no lag on typing. Then http and smtp are next in that priority order. Next any other traffic that is not specified goes into the next queue which is the default queue. Next to last is music streaming and then bittorrent is dead last. Bittorrent gets any bandwidth that is leftover from all other queues since they share any unused bandwidth. Higher pritoriy queues pull bandwidth from lower queues.
# Required order: options, normalization, queueing, translation, filtering. # Note that translation rules are first match while filter rules are last match. # See pf.conf5) for syntax and examples ################ Macros ################################### # use a macro for the interface name, so it can be changed easily ext_if = "fxp0" int_if = "fxp1" ### Stateful Tracking Options ### TorSTO = "(max 375, source-track rule, max-src-conn 1, max-src-nodes 375, tcp.established 60)" ################ Tables #################################### table <trustedhostsstatic> const {1.1.1.1,trusted.host.domain} table <blackliststatic> const {5.5.5.5} table <trustedhostsdynamic> persist ################ Options ################################## # Timeout Options set optimization aggressive set loginterface $ext_if set block-policy drop set require-order yes ################ Normaliztation ############################ # normalize all incoming traffic. Set ttl to 254 to limit possible mapping of hosts behind firewall. # Also set random-id to help with the same. Set mss to ATM network frame size for easy splitting upstream. scrub on $ext_if all random-id min-ttl 254 max-mss 1452 reassemble tcp fragment reassemble ################ Queueing ################################## # Use a queuing to prioritize empty (no payload) TCP ACKs, # This dramatically improves throughput on (asymmetric) links when the # reverse direction is saturated. The empty ACKs use an insignificant # part of the bandwidth, but if they get delayed, downloads suffer # badly, so prioritize them. # Example: 512/128 kbps ADSL. Download is 50 kB/s. When a concurrent # upload saturates the uplink, download drops to 7 kB/s. With the # priority queue below, download drops only to 48 kB/s. # For a 512/128 kbps ADSL with PPPoE link, using "bandwidth 100Kb" # is optimal. Some experimentation might be needed to find the best # value. If it's set too high, the priority queue is not effective, and # if it's set too low, the available bandwidth is not fully used. # A good starting point would be real_uplink_bandwidth * .90 # My ISP's says bandwidth upload is 1000kbps. In reality # its ~984kbps (123Kbps). Tested this by uploading multiple files # to servers to try and saturate upload bandwidth. # Note: For 768kbps up 744kbps looks like it works well for me. # Note: For 384kbps up 368kbps looks like it works well for me. altq on $ext_if bandwidth 984Kb hfsc queue { q_pri, q_def, q_mus, q_tor } queue q_pri bandwidth 49% priority 7 hfsc queue q_def bandwidth 49% priority 5 hfsc (linkshare 49%) {q_smtp,q_http,ssh_login,q_def1} queue ssh_login bandwidth 96% priority 5 hfsc queue q_http bandwidth 1% priority 4 hfsc queue q_smtp bandwidth 1% priority 4 hfsc queue q_def1 bandwidth 1% priority 3 hfsc (default) queue q_mus bandwidth 1% qlimit 200 priority 4 hfsc queue q_tor bandwidth 1% qlimit 25 priority 3 hfsc (upperlimit 272Kb) ################ Translation ############################### # Translation rules are first match # NAT internal hosts nat on $ext_if from !($ext_if) to any -> ($ext_if:0) # Redirect Bit Torrent traffic to internal machine rdr on $ext_if proto tcp from any to any port 7381 -> 192.168.0.41 # Redirect for MythTV webserver rdr on $ext_if proto tcp from any to any port 443 -> 192.168.0.30 # Redirect for mp3 streaming music (edna) rdr on $ext_if proto tcp from any to any port 993 -> 192.168.0.40 # Postfix Mail Server (internal and external) rdr on $int_if proto tcp from any to $int_if port smtp -> lo0 port smtp rdr on $ext_if proto tcp from any to ($ext_if) port smtp -> lo0 port smtp # Dovecot pop3s/imap Server (internal interface) redirect for internal hosts. rdr on $int_if proto tcp from any to $int_if port pop3s -> lo0 port pop3s # DENY rouge redirections no rdr ################ Filtering ################################# # loopback antispoof log quick for lo0 inet pass quick on lo0 all # block inet6 block in quick inet6 #blacklisted ips block in quick on $ext_if from <blackliststatic> to any flags S/SA # silently drop broadcasts cable modem noise block in quick on $ext_if from any to 255.255.255.255 # block and log everything by default block log on $ext_if all # block anything coming from source we have no back routes for block in from no-route to any # Block and log outgoing packets that don't have our address as source, # they are either spoofed or something is misconfigured NAT disabled, # (for instance), we want to be nice and don't send out garbage. block out log quick on $ext_if from ! $ext_if to any # pass VPN traffic. Turn on if needed. # pass in quick proto gre all # pass out quick proto gre all # TCP # pass out all TCP connections and modulate state pass out on $ext_if proto tcp from ($ext_if) to any flags S/SA modulate state queue (q_def1,q_pri) # Tag all packets on the internal interface from the bittorrent machine's ip (alias) pass in on $int_if from 192.168.0.41 to any tag TORRENT modulate state # Put all packets tagged TORRENT in the torrent queue. pass out on $ext_if proto tcp from ($ext_if) to any port > 1024 flags S/SA tagged TORRENT modulate state queue (q_tor) pass out on $ext_if proto udp from ($ext_if) to any port > 1024 tagged TORRENT keep state queue (q_tor) # UDP # pass out all UDP connections and keep state pass out on $ext_if proto udp from ($ext_if) to any keep state queue (q_def1) # pass out all ICMP connections and keep state pass out on $ext_if inet proto icmp from ($ext_if) to any keep state # Allow only specific block of trusted ip's to ssh to the firewall. pass in quick on $ext_if inet proto tcp from { <trustedhostsstatic>,<trustedhostsdynamic> } to ($ext_if) port 22 flags S/SA keep state queue (q_def1,ssh_login) # Allow Bit Torrent traffic to internal machine ip (alias) pass in on $ext_if proto tcp from any to 192.168.0.41 port 7381 flags S/SA synproxy state $TorSTO queue q_tor pass in on $ext_if proto udp from any to 192.168.0.41 port 7381 keep state $TorSTO queue q_tor # Allow MythTV to inside pass in quick on $ext_if inet proto tcp from <trustedhostsstatic> to 192.168.0.30 port 443 flags S/SA keep state queue (q_def1,q_pri) # Allow mp3 streaming music (edna) pass in quick on $ext_if inet proto tcp from <trustedhostsstatic> to 192.168.0.40 port 993 flags S/SA keep state queue (q_mus,q_pri) # Allow traffic for postfix mail server pass in log on $ext_if inet proto tcp from any to lo0 port smtp flags S/SA synproxy state $SpamdSTO queue (q_smtp,q_pri) pass in on $int_if inet proto tcp from 192.168.0.0/24 to lo0 port smtp synproxy state flags S/SA # Allow traffic for external http server pantz.org pass in quick on $ext_if inet proto tcp from any to ($ext_if) port 80 flags S/SA keep state queue (q_http,q_pri) # Allow traffic to Dovecot pop3 server from any network on the inside. Change to external if needed. pass in on $int_if inet proto tcp from any to lo0 port pop3s flags S/SA keep state