Differences between revisions 46 and 47
Revision 46 as of 2010-07-08 15:22:36
Size: 40791
Editor: ?green
Comment: update Document Conventions and Basic Networking sections
Revision 47 as of 2010-11-16 17:37:08
Size: 41011
Editor: ?green
Comment:
Deletions are marked like this. Additions are marked like this.
Line 247: Line 247:

'''I am considering switching from a custom script to [[http://packages.debian.org/ferm|ferm]] which would also be fast and use a single configuration file, but also be more readable and standard than this script.'''

I have been working to set up a Soekris net5501 to act as a home router/server. My efforts are documented here to serve as an example for others attempting similar setup scenarios. Note that this guide is only intended to cover post-installation software setup and so should be applicable to nearly any hardware.

UNDER CONSTRUCTION; most of what you see here is incomplete.

Good luck with your challenge! If you notice any error please mail me, leave a ?comment, or fix it.

If you know of a better place in the wiki for this to go, please ?suggest it.

Requirements

Here is a list of requirements with links to the relevant sections.

  • 100% Debian, no external software
  • Stock Debian kernel
  • ?dnsmasq server, providing

    • DNS, including local DNS
    • DHCP server, including static IPs
  • Support dual-stack network; IPv4 and IPv6 - ?SixXS

  • Provide local private network bridge - ?Networking

    • Ethernet ports + private secured wireless (?hostap)

  • Provide public network
    • Unsecured wireless (?hostap)

  • Simple and robust ?firewall

    • Reasonable security for the router
    • Port forwarding (single, range, or all)
    • With ?UPnP support

    • Modify TOS packet header bits
  • ?Traffic control to provide a better internet experience for multiple users/connections

    • Use TOS packet header bits
  • Carefully controlled log files - ?rsyslogd

Document Conventions

  • eth0 is WAN ethernet port
  • aiccu is the interface of the SixXS ipv6 tunnel
  • eth1-eth3 are LAN ethernet (private)
  • wlan0 is private wireless (?hostap)

  • wlan0_0 is public wireless (?hostap)

  • br0 bridges eth1-eth3 and wlan0
  • private local ipv4 network: 192.0.2.0/24 (choose your own, probably 192.168.x.0/24)
  • public local ipv4 network: 192.0.3.0/24 (choose your own, probably 192.168.x+1.0/24)
  • WAN ipv6 SixXS IP: 2001:db8::1/48

SixXS

Register with SixXS and request an tunnel and subnet. Choose your tunnel type carefully. I chose the less efficient AYIYA type because it will work behind masquerading.

Use aiccu to bring up the tunnel.

OPTIONAL: To avoid using your SixXS password in plaintext in the aiccu configuration file, add a TIC Password for the tunnel, then use "$HANDLE/$TUNNELID" as your username and the password you chose in the configuration.

aiccu.conf:

username $HANDLE
password $PASSWORD
protocol tic
server tic.sixxs.net
ipv6_interface aiccu
tunnel_id $TUNNELID
automatic true
requiretls false

Now you should have an interface named aiccu and ipv6 connectivity. Test with:

ping6 -c 2 www.kame.net

Basic Networking

IPv6

Divide your /48 SixXS subnet into appropriate subnets.

First 48 bits:

1111111111111111.1111111111111111.1111111111111111.0000000000000000.0000000000000000.0000000000000000.0000000000000000.0000000000000000

Use these 16 bits for defining subnets:

0000000000000000.0000000000000000.0000000000000000.1111111111111111.0000000000000000.0000000000000000.0000000000000000.0000000000000000

So with /48 you would have 1 subnet.

With /50, you would have 4 subnets:

1111111111111111.1111111111111111.1111111111111111.1100000000000000.0000000000000000.0000000000000000.0000000000000000.0000000000000000

Those 2 bits (49 and 50) determine the network. In hex, those would be:

0000000000000000 = 0000  xxxx:xxxx:xxxx::/50
0100000000000000 = 4000  xxxx:xxxx:xxxx:4000::/50
1000000000000000 = 8000  xxxx:xxxx:xxxx:8000::/50
1100000000000000 = c000  xxxx:xxxx:xxxx:c000::/50

You can calculate those with something like

echo "obase=16;ibase=2;1000000000000000" | bc

You could further divide those 4 subnets using more bits, like perhaps 51 and 52. Here are subnets for the first xxxx:xxxx:xxxx::/50 above:

0000000000000000 = 0000  xxxx:xxxx:xxxx::/52
0001000000000000 = 1000  xxxx:xxxx:xxxx:1000::/52
0010000000000000 = 2000  xxxx:xxxx:xxxx:2000::/52
0011000000000000 = 3000  xxxx:xxxx:xxxx:3000::/52

And now another example, dividing the second primary subnet xxxx:xxxx:xxxx:c000::/50 into 8 subnets using bits 51-53:

1100000000000000 = c000  xxxx:xxxx:xxxx:c000::/53
1100100000000000 = c800  xxxx:xxxx:xxxx:c800::/53
1101000000000000 = c000  xxxx:xxxx:xxxx:d000::/53
1101100000000000 = c000  xxxx:xxxx:xxxx:d800::/53
1110000000000000 = c000  xxxx:xxxx:xxxx:e000::/53
1110100000000000 = c000  xxxx:xxxx:xxxx:e800::/53
1111000000000000 = c000  xxxx:xxxx:xxxx:f000::/53
1111100000000000 = c000  xxxx:xxxx:xxxx:f800::/53

See:

Configuration

/etc/network/interfaces:

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface (WAN)
auto eth0
#allow-hotplug eth0 # hotplugging does not seem to work reliably
iface eth0 inet dhcp

# Network bridge (LAN)
auto br0
iface br0 inet static
  hostapd /etc/hostapd/hostapd.conf  # this starts hostapd
  address 192.0.2.1
  netmask 255.255.255.0
  network 192.0.2.0
  broadcast 192.0.2.255
  bridge_ports eth1 eth2 eth3 wlan0
iface br0 inet6 static
  address (from sixxs)
  netmask 64

# Public wireless network
auto wlan0_0
iface wlan0_0 inet static
  address 192.0.3.1
  netmask 255.255.255.0
  network 192.0.3.0
  broadcast 192.0.3.255
iface wlan0_0 inet6 static
  address (from sixxs)
  netmask 64


Set up /etc/hosts to make local DNS work correctly:

Change this line:

127.0.1.1      hostname.example.org hostname

To:

192.0.2.1    hostname.example.org hostname2.example2.org hostname

Test: make sure both hostname -s and hostname -f work correctly now.

dnsmasq

dnsmasq.conf:

interface=br0
dhcp-range=private,192.0.2.51,192.0.2.250,48h

interface=wlan0_0
dhcp-range=public,192.0.3.51,192.0.3.250,48h

domain-needed
bogus-priv

# Set the NTP time server address to be the same machine as
# is running dnsmasq
dhcp-option=42,0.0.0.0

# Send microsoft-specific option to tell windows to release the DHCP lease
# when it shuts down. 
dhcp-option=vendor:MSFT,2,1i

# Set the limit on DHCP leases, the default is 150
## here, raised to the maximum number of hosts on networks
dhcp-lease-max=506

# Set the DHCP server to authoritative mode. In this mode it will barge in
# and take over the lease for any client which broadcasts on the network,
# whether it has a record of the lease or not. This avoids long timeouts
# when a machine wakes up on a new network. DO NOT enable this if there's
# the slighest chance that you might end up accidentally configuring a DHCP
# server for your campus/company accidentally. The ISC server uses
# the same option, and this URL provides more information:
# http://www.isc.org/index.pl?/sw/dhcp/authoritative.php
#dhcp-authoritative


OPTIONAL: For static host configuration, create /etc/dnsmasq.d/static-hosts.conf:

# static DHCP hosts
# Optionally, use IPs from 2 to 50 (outside of DHCP range).

# example for private network
#dhcp-host=xx:xx:xx:xx:xx:xx,192.0.2.10

# example for public network
#dhcp-host=xx:xx:xx:xx:xx:xx,192.0.3.16


OPTIONAL: To use custom nameservers, create /etc/alt.dns:

# Google Public DNS
nameserver      8.8.8.8
nameserver      8.8.4.4

And uncomment line in /etc/default/dnsmasq:

IGNORE_RESOLVCONF=yes

And add line to /etc/dnsmasq.conf:

resolv-file=/etc/alt.dns

Firewall

Firewall shell scripts are slow (see http://www.faqs.org/docs/iptables/saveandrestore.html ), and scripts for iptables-restore/ip6tables-restore must be maintained individually. In order to keep performance, use a single script, and gain readability for easy maintenance, I wrote a script that creates iptables-restore and ip6tables-restore scripts.

I am considering switching from a custom script to ferm which would also be fast and use a single configuration file, but also be more readable and standard than this script.

Create /usr/local/sbin/build-firewall.sh:

 #!/bin/sh  # What markup will make this line correct?
set -e

case "$1" in
 apply)
  ;;
 restore)
  ;;
 build)
  ;;
 save)
  ;;
 *)
  echo "Usage: $0 {apply|build|restore|save}"
  echo
  echo "apply: iptables-apply (includes connection check)"
  echo "build: just write iptables and ip6tables scripts"
  echo "restore: iptables-restore (apply immediately without check)"
  echo "save: restore, then save iptables and ip6tables scripts to /etc/network/"
  exit 1
  ;;
esac

policies() {
ipboth RAW :PREROUTING ACCEPT
ipboth RAW :OUTPUT ACCEPT
ipboth MANGLE :PREROUTING ACCEPT
ipboth MANGLE :INPUT ACCEPT
ipboth MANGLE :FORWARD ACCEPT
ipboth MANGLE :OUTPUT ACCEPT
ipboth MANGLE :POSTROUTING ACCEPT
ip4 NAT :PREROUTING ACCEPT
ip4 NAT :OUTPUT ACCEPT
ip4 NAT :POSTROUTING ACCEPT
ipboth FILTER :INPUT DROP
ipboth FILTER :FORWARD DROP
ipboth FILTER :OUTPUT DROP
}

rules() { # Use no "double quotes" in rules!
# DNAT
 # modify DNAT
 ip4 NAT :DNAT_MOD -
 ip4 NAT -A PREROUTING -j DNAT_MOD

 # do not change destination IP/port for these packets
 ip4 NAT -A DNAT_MOD -i eth0 -p icmp -j RETURN
 ip4 NAT :DNAT_SKIP -
 ip4 NAT -A DNAT_MOD -i eth0 -g DNAT_SKIP

 # manual port forwarding
 ip4 NAT :MANUAL_DNAT -
 ip4 NAT -A DNAT_MOD -i eth0 -j MANUAL_DNAT
 ## to specific host (modify static-hosts.conf if necessary)
 #ip4 NAT -A MANUAL_DNAT -p tcp -m tcp --dport 33333 -j DNAT --to-destination 192.0.2.10
 ## to specific host and different destination port (modify static-hosts.conf if necessary)
 #ip4 NAT -A MANUAL_DNAT -p tcp -m tcp --dport 81 -j DNAT --to-destination 192.0.2.10
 #ip4 NAT -A MANUAL_DNAT -p tcp -m tcp --dport 24 -j DNAT --to-destination 192.0.3.11
 ## to different destination port on router
 #ip4 NAT -A MANUAL_DNAT -p tcp -m tcp --dport 81 -j DNAT --to-destination :80

 # upnp
 ip4 NAT :DNAT_UPNP -
 ip4 NAT -A DNAT_MOD -i eth0 -j DNAT_UPNP
 ## example, from linux-igd upnpd
 ##ip4 NAT -A DNAT_UPNP -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.0.2.96:80

 # forward all remaining ports
 ip4 NAT :DNAT_ALLPORTS -
 ip4 NAT -A DNAT_MOD -i eth0 -j DNAT_ALLPORTS
 #ip4 NAT -A DNAT_ALLPORTS -j DNAT --to-destination 192.0.2.10
# END DNAT

# masquerading
ip4 NAT -A POSTROUTING -s 192.0.2.0/24 ! -d 192.0.2.0/24 -o eth0 -j MASQUERADE
ip4 NAT -A POSTROUTING -s 192.0.3.0/24 ! -d 192.0.3.0/24 -o eth0 -j MASQUERADE

# IPv6
ip4 FILTER -A INPUT -p ipv6 -j ACCEPT
ip4 FILTER -A FORWARD -p ipv6 -j ACCEPT
ip4 FILTER -A OUTPUT -p ipv6 -j ACCEPT

# loopback
ipboth FILTER -A INPUT -i lo -j ACCEPT
ipboth FILTER -A OUTPUT -o lo -j ACCEPT

# BLOCKING
 # RH0
 ip6tables -A INPUT -m rt --rt-type 0 -j DROP
 ip6tables -A FORWARD -m rt --rt-type 0 -j DROP
 ip6tables -A OUTPUT -m rt --rt-type 0 -j DROP

 # host block
 ipboth FILTER :HOST_BLOCK -
 ipboth FILTER -A INPUT -j HOST_BLOCK
 ipboth FILTER -A FORWARD -j HOST_BLOCK
 ipboth FILTER -A OUTPUT -j HOST_BLOCK
 ## examples
 # ipboth FILTER -A HOST_BLOCK --source 10.0.1.254 -j HOST_BLOCK_EXEC
 # ipboth FILTER -A HOST_BLOCK --destination 10.0.1.254 -j HOST_BLOCK_EXEC
 ipboth FILTER :HOST_BLOCK_EXEC -
 ipboth FILTER -A HOST_BLOCK_EXEC -m limit --limit 1/min --limit-burst 1 -j LOG --log-prefix Blocked-host_ --log-level notice
 ipboth FILTER -A HOST_BLOCK_EXEC -j DROP

 # invalid
 ipboth FILTER :VALIDITY_CHECK -
 ipboth FILTER :INVALID -
 ipboth FILTER -A INPUT -j VALIDITY_CHECK
 ipboth FILTER -A FORWARD -j VALIDITY_CHECK
 ipboth FILTER -A VALIDITY_CHECK -m state --state INVALID -j INVALID
 ipboth FILTER -A INVALID -m limit --limit 6/min --limit-burst 2 -j LOG --log-prefix Invalid-packet_ --log-level info
 ipboth FILTER -A INVALID -j DROP
 ## more validity checks here, like previous line

 # fragmented
 ipboth FILTER :FRAGMENT_CHECK -
 ipboth FILTER -A INPUT -j FRAGMENT_CHECK
 ipboth FILTER -A FORWARD -j FRAGMENT_CHECK
 ipboth FILTER :FRAGMENTED -
 ip4 FILTER -A FRAGMENT_CHECK -f -j FRAGMENTED
 ip6 FILTER -A FRAGMENT_CHECK -m frag --fragmore -m length --length 0:1279 -j FRAGMENTED
 ipboth FILTER -A FRAGMENTED -m limit --limit 3/min --limit-burst 1 -j LOG --log-prefix Fragmented-packet_ --log-level info
 ipboth FILTER -A FRAGMENTED -j DROP
# END BLOCKING

# local dhcp
ipboth FILTER -A INPUT -p udp -i br0 --sport 67:68 --dport 67:68 -j ACCEPT
ipboth FILTER -A INPUT -p udp -i wlan0_0 --sport 67:68 --dport 67:68 -j ACCEPT
# out
ipboth FILTER -A OUTPUT -p udp -o br0 --sport 67:68 --dport 67:68 -j ACCEPT
ipboth FILTER -A OUTPUT -p udp -o wlan0_0 --sport 67:68 --dport 67:68 -j ACCEPT

# spoofed
ipboth FILTER :SPOOFED -
ip4 FILTER -A INPUT -j SPOOFED #*check* ip6 removed here
ip4 FILTER -A FORWARD -j SPOOFED #*check* ip6 removed here
ipboth FILTER -A SPOOFED -i eth0 -j RETURN
ip6 FILTER -A SPOOFED -i aiccu -j RETURN
ip4 FILTER -A SPOOFED -i br0 -s 192.0.2.0/24 -j RETURN
#ip6 FILTER -A SPOOFED -i br0 -s 0:) -j RETURN #*check* fix with correct ipv6 addresses
ip4 FILTER -A SPOOFED -i wlan0_0 -s 192.0.3.0/24 -j RETURN
#ip6 FILTER -A SPOOFED -i wlan0_0 -s 0:) -j RETURN #*check* fix with correct ipv6 addresses
ipboth FILTER -A SPOOFED -m limit --limit 6/min -j LOG --log-prefix Spoofed-packet_ --log-level notice
ip4 FILTER -A SPOOFED -j REJECT --reject-with icmp-net-unreachable
ip6 FILTER -A SPOOFED -j REJECT --reject-with icmp6-adm-prohibited

# ICMP
ip4 FILTER -A OUTPUT -p icmp -j ACCEPT
ip6 FILTER -A OUTPUT -p ipv6-icmp -j ACCEPT
ipboth FILTER :ICMP -
ip4 FILTER -A INPUT -p icmp -j ICMP
ip6 FILTER -A INPUT -p ipv6-icmp -j ICMP
ip4 FILTER -A FORWARD -p icmp -j ICMP
ip6 FILTER -A FORWARD -p ipv6-icmp -j ICMP
ipboth FILTER -A ICMP -m limit --limit 20/sec --limit-burst 100 -j ACCEPT
ip4 FILTER -A ICMP -p icmp -m icmp --icmp-type echo-request -j DROP
ip6 FILTER -A ICMP -p ipv6-icmp -m icmp6 --icmpv6-type echo-request -j DROP
ipboth FILTER -A ICMP -m limit --limit 20/sec -j ACCEPT
ipboth FILTER -A ICMP -j DROP

# established connections
ipboth FILTER -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ipboth FILTER -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
ipboth FILTER -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SPECIFIC SERVICES
 # ssh
 ip4 NAT -A DNAT_SKIP -p tcp --dport ssh -j RETURN
 ipboth FILTER -A INPUT -p tcp --dport ssh -j ACCEPT
 ipboth FILTER -A OUTPUT -p tcp --dport ssh -j ACCEPT

 # upstream dhcp
 ip4 NAT -A DNAT_SKIP -p tcp --dport 67:68 -j RETURN
 ipboth FILTER -A INPUT -p udp -i eth0 --sport 67:68 --dport 67:68 -j ACCEPT
 ipboth FILTER -A OUTPUT -p udp -o eth0 --sport 67:68 --dport 67:68 -j ACCEPT

 # SixXS, AYIYA, aiccu
 #ip4 NAT -A DNAT_SKIP -p tcp --dport 3874 -j RETURN
 #ip4 NAT -A DNAT_SKIP -p udp --dport 5072 -j RETURN # removed 3740
 ip4 FILTER -A INPUT -p udp --sport 5072 -j ACCEPT
 ip4 FILTER -A OUTPUT -p tcp -o eth0 --dport 3874 -j ACCEPT
 ip4 FILTER -A OUTPUT -p udp -o eth0 -m multiport --dport 3740,5072 -j ACCEPT

 # dns
 ip4 NAT -A DNAT_SKIP -p tcp -m multiport --dport domain,mdns -j RETURN
 ip4 NAT -A DNAT_SKIP -p udp -m multiport --dport domain,mdns -j RETURN
 ipboth FILTER -A INPUT -p tcp -i br0 -m multiport --dport domain,mdns -j ACCEPT
 ipboth FILTER -A INPUT -p udp -i br0 -m multiport --dport domain,mdns -j ACCEPT
 ipboth FILTER -A INPUT -p tcp -i wlan0_0 -m multiport --dport domain,mdns -j ACCEPT
 ipboth FILTER -A INPUT -p udp -i wlan0_0 -m multiport --dport domain,mdns -j ACCEPT
 ipboth FILTER -A OUTPUT -p udp -o br0 --dport mdns -j ACCEPT
 ipboth FILTER -A OUTPUT -p udp -o wlan0_0 --dport mdns -j ACCEPT
 ipboth FILTER -A OUTPUT -p tcp -o eth0 --dport domain -j ACCEPT
 ipboth FILTER -A OUTPUT -p udp -o eth0 --dport domain -j ACCEPT
 ip6 FILTER -A OUTPUT -p tcp -o aiccu --dport domain -j ACCEPT
 ip6 FILTER -A OUTPUT -p udp -o aiccu --dport domain -j ACCEPT

 # ntp
 ip4 NAT -A DNAT_SKIP -p udp --dport ntp -j RETURN
 ipboth FILTER -A INPUT -p udp --dport ntp -j ACCEPT
 ipboth FILTER -A OUTPUT -p udp --sport ntp -j ACCEPT

 # www/https
 ip4 NAT -A DNAT_SKIP -p tcp --dport www -j RETURN
 ipboth FILTER -A INPUT -p tcp --dport www -j ACCEPT
 ipboth FILTER -A OUTPUT -p tcp -o eth0 -m multiport --dports www,https -j ACCEPT
 ip6 FILTER -A OUTPUT -p tcp -o aiccu -m multiport --dports www,https -j ACCEPT

 # upnp
 ip4 NAT -A DNAT_SKIP -p tcp -m multiport --dports 5000,49152 -j RETURN
 ip4 NAT -A DNAT_SKIP -p udp --dport 1900 -j RETURN
 ip4 FILTER :UPNP_FORWARD -
 ip4 FILTER -A INPUT -i br0 -p udp -m multiport --ports 1900 -j ACCEPT
 ip4 FILTER -A INPUT -i br0 -p tcp -m multiport --ports 2869,5000,49152 -j ACCEPT
 ip4 FILTER -A INPUT -i br0 -p igmp -j ACCEPT
 ip4 FILTER -A OUTPUT -o br0 -p udp -m multiport --ports 1900 -j ACCEPT
 ip4 FILTER -A OUTPUT -o br0 -p tcp -m multiport --ports 2869,5000,49152 -j ACCEPT
 ip4 FILTER -A OUTPUT -o br0 -p igmp -j ACCEPT
 ip4 FILTER -A FORWARD -i eth0 -o br0 -j UPNP_FORWARD
 ## example, from linux-igd upnpd
 ##ip4 FILTER -A UPNP_FORWARD -d 192.0.2.10/24 -p tcp -m tcp --dport 80 -j ACCEPT
# END SPECIFIC SERVICES

# GENERAL PERMITTED
 # to private
 #ipboth FILTER -A OUTPUT -o br0 -j ACCEPT
# END GENERAL PERMITTED

# from private
ipboth FILTER :FROM_PRIVATE -
ipboth FILTER -A FORWARD -i br0 -j FROM_PRIVATE
ipboth FILTER -A FROM_PRIVATE -o br0 -j ACCEPT
ipboth FILTER -A FROM_PRIVATE -o eth0 -j ACCEPT
ipboth FILTER -A FROM_PRIVATE -o aiccu -j ACCEPT
ipboth FILTER -A FROM_PRIVATE -o wlan0_0 -m limit --limit 3/min -j LOG --log-prefix Rejected-private-to-public_ --log-level info
ip4 FILTER -A FROM_PRIVATE -o wlan0_0 -j REJECT --reject-with icmp-net-prohibited
ip6 FILTER -A FROM_PRIVATE -o wlan0_0 -j REJECT --reject-with icmp6-adm-prohibited

# from public
ipboth FILTER :FROM_PUBLIC -
ipboth FILTER -A FORWARD -i wlan0_0 -j FROM_PUBLIC
ipboth FILTER -A FROM_PUBLIC -o eth0 -j ACCEPT
ipboth FILTER -A FROM_PUBLIC -o aiccu -j ACCEPT
ipboth FILTER -A FROM_PUBLIC -o br0 -m limit --limit 3/min -j LOG --log-prefix Rejected-public-to-private_ --log-level info
ip4 FILTER -A FROM_PUBLIC -o br0 -j REJECT --reject-with icmp-net-prohibited
ip6 FILTER -A FROM_PUBLIC -o br0 -j REJECT --reject-with icmp6-adm-prohibited
ipboth FILTER -A FROM_PUBLIC -o wlan0_0 -m limit --limit 3/min -j LOG --log-prefix Rejected-public-to-public_ --log-level info
ip4 FILTER -A FROM_PUBLIC -o wlan0_0 -j REJECT --reject-with icmp-host-prohibited
ip6 FILTER -A FROM_PUBLIC -o wlan0_0 -j REJECT --reject-with icmp6-adm-prohibited
ipboth FILTER -A FROM_PUBLIC -o tun0 -m limit --limit 3/min -j LOG --log-prefix Rejected-public-to-vpn_ --log-level info

# DROP/REJECT
 # unmatched packets
 ip4 FILTER -A INPUT -m limit --limit 20/min -j LOG --log-prefix Unmatched-INPUT_ --log-level debug
 ip6 FILTER -A INPUT -m limit --limit 20/min -j LOG --log-prefix Unmatched-v6-INPUT_ --log-level debug
 ip4 FILTER -A FORWARD -m limit --limit 20/min -j LOG --log-prefix Unmatched-FORWARD_ --log-level debug
 ip6 FILTER -A FORWARD -m limit --limit 20/min -j LOG --log-prefix Unmatched-v6-FORWARD_ --log-level debug
 ip4 FILTER -A OUTPUT -j LOG --log-prefix Unmatched-OUTPUT_ --log-level debug
 ip6 FILTER -A OUTPUT -j LOG --log-prefix Unmatched-v6-OUTPUT_ --log-level debug
# end DROP/REJECT

# TOS
 ipboth MANGLE :TOS_CHAIN -
 ipboth MANGLE -A POSTROUTING -j TOS_CHAIN

 # Correcting TOS for incorrectly marked packets
 ipboth MANGLE :FIX_TOS -
 ipboth MANGLE -A TOS_CHAIN -m tos ! --tos Normal-Service -j FIX_TOS
  # Large packets with Minimize-Delay TOS
  ipboth MANGLE -A FIX_TOS -m tos ! --tos Minimize-Delay -j RETURN
  ipboth MANGLE -A FIX_TOS -p tcp -m length --length 0:512  -j RETURN
  ipboth MANGLE -A FIX_TOS -p udp -m length --length 0:1024 -j RETURN
  ipboth MANGLE -A FIX_TOS -j TOS --set-tos Maximize-Throughput

 # Add TOS for unmarked packets
 ipboth MANGLE :ADD_TOS -
 ipboth MANGLE -A TOS_CHAIN -m tos --tos Normal-Service -j ADD_TOS
  # TCP control packets (from www.docum.org / Stef Coene)
  ipboth MANGLE :ACK_TOS -
  ipboth MANGLE -A ADD_TOS -p tcp -m tcp --tcp-flags SYN,RST,ACK ACK -j ACK_TOS
  ipboth MANGLE -A ACK_TOS -m length --length 0:256 -j TOS --set-tos Minimize-Delay
  ipboth MANGLE -A ACK_TOS -m length --length 256: -j TOS --set-tos Maximize-Throughput
  ipboth MANGLE -A ADD_TOS -p tcp --tcp-flags SYN,RST,ACK ACK -j RETURN
  # Specify general TOS settings here for protocol/port
  ipboth MANGLE -A ADD_TOS -p icmp -j TOS --set-tos Normal-Service
  ipboth MANGLE -A ADD_TOS -p tcp -m multiport --ports domain,bootps,bootpc,msnp,mdns,auth,aol,irc,ircs,ircd,5154,3389,5900 -j TOS --set-tos Minimize-Delay
  ipboth MANGLE -A ADD_TOS -p tcp -m multiport --ports pop3,pop3s,imap,imaps -j TOS --set-tos Maximize-Throughput
  ipboth MANGLE -A ADD_TOS -p tcp -m multiport --ports snmp -j TOS --set-tos Maximize-Reliability
  ipboth MANGLE -A ADD_TOS -p tcp -m multiport --ports smtp,ssmtp -j TOS --set-tos Minimize-Cost
  ipboth MANGLE -A ADD_TOS -p tcp -m multiport --ports www,https -j TOS --set-tos 0x18
  ipboth MANGLE -A ADD_TOS -p udp -m multiport --ports domain,bootps,bootpc,ntp,msnp,aol,irc,ircs,5154,5060:5064,iax,1720,1731 -j TOS --set-tos Minimize-Delay
  #ipboth MANGLE -A ADD_TOS -p udp -m multiport --ports 000 -j TOS --set-tos Maximize-Throughput
  #ipboth MANGLE -A ADD_TOS -p udp -m multiport --ports 000 -j TOS --set-tos Maximize-Reliability
  #ipboth MANGLE -A ADD_TOS -p udp -m multiport --ports 000 -j TOS --set-tos Minimize-Cost
# END TOS

# SHAPING
 # add shaping assist fwmarks
 ipboth MANGLE :SHAPING_MARK_IN -
 ipboth MANGLE -A PREROUTING -j SHAPING_MARK_IN
  ipboth MANGLE -A SHAPING_MARK_IN -i eth0 -j RETURN
  ip6 MANGLE -A SHAPING_MARK_IN -i aiccu -j RETURN
  ipboth MANGLE -A SHAPING_MARK_IN -i br0 -j MARK --set-mark 0x80/0xf0
  ipboth MANGLE -A SHAPING_MARK_IN -i br0 -j RETURN
  ipboth MANGLE -A SHAPING_MARK_IN -i wlan0_0 -j MARK --set-mark 0x90/0xf0
 ipboth MANGLE -A OUTPUT -o eth0 -j MARK --set-mark 0x20/0xf0
 ipboth MANGLE -A OUTPUT -o aiccu -j MARK --set-mark 0x20/0xf0
 #ip6 MANGLE -A OUTPUT -o br0 -j MARK --set-mark 0x20/0xf0 #*check* breaks radvd

 # mark priorty
 # 1 link-critical: DHCP, ARP
 # 2 time-critical: dns
 # 3 TOS 0 high priority: ftp, telnet, ssh
 # 4 
 # 5 TOS 1 medium priority: icmp, www, https
 # 6 
 # 7 TOS 2 low priority: smtp, pop, imap, ftp-data
 # 8 very low priority:
 ipboth MANGLE :SHAPE_PRIORITY -
 ipboth MANGLE -A POSTROUTING -o eth0 -j SHAPE_PRIORITY
 ip6 MANGLE -A POSTROUTING -o aiccu -j SHAPE_PRIORITY
  ipboth MANGLE -A SHAPE_PRIORITY -p udp --sport 68 --dport 67 -j MARK --set-mark 0x01/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -p udp --sport 68 --dport 67 -j RETURN
  ipboth MANGLE -A SHAPE_PRIORITY -p udp --dport domain -j MARK --set-mark 0x02/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -p udp --dport domain -j RETURN
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x00 -j MARK --set-mark 0x05/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x02 -j MARK --set-mark 0x07/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x04 -j MARK --set-mark 0x05/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x06 -j MARK --set-mark 0x05/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x08 -j MARK --set-mark 0x07/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x0a -j MARK --set-mark 0x07/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x0c -j MARK --set-mark 0x07/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x0e -j MARK --set-mark 0x07/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x10 -j MARK --set-mark 0x03/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x12 -j MARK --set-mark 0x03/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x14 -j MARK --set-mark 0x03/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x16 -j MARK --set-mark 0x03/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x18 -j MARK --set-mark 0x05/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x1a -j MARK --set-mark 0x05/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x1c -j MARK --set-mark 0x05/0x0f
  ipboth MANGLE -A SHAPE_PRIORITY -m tos --tos 0x1e -j MARK --set-mark 0x05/0x0f

 # classify
 ipboth MANGLE :SHAPE_CLASSIFY -
 ipboth MANGLE -A POSTROUTING -o eth0 -j SHAPE_CLASSIFY
 ip6 MANGLE -A POSTROUTING -o aiccu -j SHAPE_CLASSIFY
  ip4 MANGLE -A SHAPE_CLASSIFY -o eth0 -p udp --dport 5072 -j CLASSIFY --set-class 0x1:0x6
  ip4 MANGLE -A SHAPE_CLASSIFY -o eth0 -p udp --dport 5072 -j RETURN
  ipboth MANGLE :SHAPE_CLASSIFY_ROUTER -
  ipboth MANGLE :SHAPE_CLASSIFY_PRIVATE -
  ipboth MANGLE :SHAPE_CLASSIFY_PUBLIC -
  ipboth MANGLE -A SHAPE_CLASSIFY -m mark --mark 0x20/0xf0 -j SHAPE_CLASSIFY_ROUTER
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x01/0x0f -j CLASSIFY --set-class 0x1:0x21
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x02/0x0f -j CLASSIFY --set-class 0x1:0x22
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x03/0x0f -j CLASSIFY --set-class 0x1:0x23
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x04/0x0f -j CLASSIFY --set-class 0x1:0x24
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x05/0x0f -j CLASSIFY --set-class 0x1:0x25
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x06/0x0f -j CLASSIFY --set-class 0x1:0x26
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x07/0x0f -j CLASSIFY --set-class 0x1:0x27
   ipboth MANGLE -A SHAPE_CLASSIFY_ROUTER -m mark --mark 0x08/0x0f -j CLASSIFY --set-class 0x1:0x28
  ipboth MANGLE -A SHAPE_CLASSIFY -m mark --mark 0x80/0xf0 -j SHAPE_CLASSIFY_PRIVATE
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x01/0x0f -j CLASSIFY --set-class 0x1:0x81
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x02/0x0f -j CLASSIFY --set-class 0x1:0x82
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x03/0x0f -j CLASSIFY --set-class 0x1:0x83
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x04/0x0f -j CLASSIFY --set-class 0x1:0x84
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x05/0x0f -j CLASSIFY --set-class 0x1:0x85
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x06/0x0f -j CLASSIFY --set-class 0x1:0x86
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x07/0x0f -j CLASSIFY --set-class 0x1:0x87
   ipboth MANGLE -A SHAPE_CLASSIFY_PRIVATE -m mark --mark 0x08/0x0f -j CLASSIFY --set-class 0x1:0x88
  ipboth MANGLE -A SHAPE_CLASSIFY -m mark --mark 0x90/0xf0 -j SHAPE_CLASSIFY_PUBLIC
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x01/0x0f -j CLASSIFY --set-class 0x1:0x91
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x02/0x0f -j CLASSIFY --set-class 0x1:0x92
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x03/0x0f -j CLASSIFY --set-class 0x1:0x93
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x04/0x0f -j CLASSIFY --set-class 0x1:0x94
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x05/0x0f -j CLASSIFY --set-class 0x1:0x95
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x06/0x0f -j CLASSIFY --set-class 0x1:0x96
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x07/0x0f -j CLASSIFY --set-class 0x1:0x97
   ipboth MANGLE -A SHAPE_CLASSIFY_PUBLIC -m mark --mark 0x08/0x0f -j CLASSIFY --set-class 0x1:0x98
# END SHAPING

# TCPMSS clamp
ipboth MANGLE -A POSTROUTING -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
ipboth MANGLE -A POSTROUTING -o aiccu -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
}


# build
IPTABLES=$( mktemp /tmp/iptables.XXX )
IP6TABLES=$( mktemp /tmp/ip6tables.XXX )
RAW_IP4=$( mktemp )
MANGLE_IP4=$( mktemp )
NAT_IP4=$( mktemp )
FILTER_IP4=$( mktemp )
RAW_IP6=$( mktemp )
MANGLE_IP6=$( mktemp )
FILTER_IP6=$( mktemp )
ip4() {
 TABLE=$( eval "echo \$${1}_IP4" )
 shift 1
 echo $* >> $TABLE
}
ip6() {
 TABLE=$( eval "echo \$${1}_IP6" )
 shift 1
 echo $* >> $TABLE
}
ipboth() {
 ip4 $@
 ip6 $@
}
ipboth RAW "*raw"
ipboth MANGLE "*mangle"
ip4 NAT "*nat"
ipboth FILTER "*filter"
policies
rules
for TABLE in RAW_IP4 MANGLE_IP4 NAT_IP4 FILTER_IP4 RAW_IP6 MANGLE_IP6 FILTER_IP6 ; do
 eval "echo COMMIT >> \$${TABLE}"
done
echo "# iptables firewall for owenhs" >> $IPTABLES
echo "# ip6tables firewall for owenhs" >> $IP6TABLES
cat $RAW_IP4 $MANGLE_IP4 $NAT_IP4 $FILTER_IP4 >> $IPTABLES
cat $RAW_IP6 $MANGLE_IP6 $FILTER_IP6 >> $IP6TABLES
rm -f $RAW_IP4 $MANGLE_IP4 $NAT_IP4 $FILTER_IP4 $RAW_IP6 $MANGLE_IP6 $FILTER_IP6
case "$1" in
 apply)
  iptables-apply -t 30 $IPTABLES
  ip6tables-apply -t 30 $IP6TABLES
  echo "iptables and ip6tables applied successfully"
  rm -f $IPTABLES $IP6TABLES
  ;;
 restore)
  iptables-restore $IPTABLES
  ip6tables-restore $IP6TABLES
  echo "iptables and ip6tables restored successfully"
  rm -f $IPTABLES $IP6TABLES
  ;;
 build)
  echo "new: $IPTABLES"
  echo "new: $IP6TABLES"
  ;;
 save)
  iptables-restore $IPTABLES
  ip6tables-restore $IP6TABLES
  mv /etc/network/iptables /tmp/iptables.bak0
  mv /etc/network/ip6tables /tmp/ip6tables.bak0
  mv $IPTABLES /etc/network/iptables
  mv $IP6TABLES /etc/network/ip6tables
  mv /tmp/iptables.bak0 $IPTABLES
  mv /tmp/ip6tables.bak0 $IP6TABLES
  echo "old: $IPTABLES"
  echo "old: $IP6TABLES"
  ;;
esac

UPnP

Note that UPnP has some flaws. Use it only if you understand and accept them. If you choose not to use UPnP, you should remove the applicable parts of the firewall script.

/etc/default/linux-igd:

EXTIFACE=eth0
INTIFACE=br0
ALLOW_MULTICAST=yes

/etc/upnpd.conf:

iptables_location = "/sbin/iptables"
debug_mode = 3
create_forward_rules = yes
forward_rules_append = no
forward_chain_name = UPNP_FORWARD
prerouting_chain_name = DNAT_UPNP
duration = 86400 # One day from time of addition
description_document_name = gatedesc.xml
xml_document_path = /etc/linuxigd
listenport = 49152
paranoid = 1

hostapd

It seemed to work best to start hostapd from /etc/network/interfaces rather than init.

hostapd.conf:

interface=wlan0
bridge=br0
driver=nl80211
logger_syslog=-1
logger_stdout=-1
logger_syslog_level=2
logger_stdout_level=4
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd

ssid=private
country_code=US
ieee80211d=1
hw_mode=g
channel=10
beacon_int=100
max_num_sta=255
rts_threshold=2347
fragm_threshold=2346
preamble=1
macaddr_acl=0
accept_mac_file=/etc/hostapd/hostapd.accept
deny_mac_file=/etc/hostapd/hostapd.deny
ignore_broadcast_ssid=0
ap_max_inactivity=300
ieee8021x=0
eap_server=0
wpa=3
wpa_passphrase=passphrase
wpa_key_mgmt=WPA-PSK WPA-PSK-SHA256
wpa_pairwise=TKIP CCMP
rsn_pairwise=CCMP
wpa_strict_rekey=1
ieee80211w=1

bss=wlan0_0
bssid=02:xx:xx:xx:xx:xx  # use your wireless MAC address, just change the first character pair
ssid=public
wpa=0

Traffic Shaping

Create /usr/local/sbin/shaping.sh:

 #!/bin/sh  # What markup will make this line correct?
set -e

# Default up/down values in kilobytes/s
DOWN=50
UP=30

# Tested up/down values in bytes/s
if DOWN_TESTED=$( cat /var/local/down-bytes.txt 2> /dev/null ) ; then
  DOWN=$DOWN_TESTED
 else
  DOWN=$( echo "$DOWN * 1024" | bc )
fi
if UP_TESTED=$( cat /var/local/up-bytes.txt 2> /dev/null ) ; then
  UP=$UP_TESTED
 else
  UP=$( echo "$UP * 1024" | bc )
fi

# Drop to safe percentage of tested bandwidth
DOWN=$(( $DOWN * 90 / 100 ))
UP=$(( $UP * 90 / 100 ))


remove() {
 for DEV in eth0 aiccu eth1 eth2 eth3 wlan0 wlan0_0 ; do
  tc qdisc del dev $DEV root 2> /dev/null || true
 done
}

case "$1" in
 start|restart)
  remove
  ;;
 stop)
  remove
  exit 0
  ;;
 status)
  echo "[qdisc]"
  tc -s qdisc show dev $DEV
  echo "[class]"
  tc -s class show dev $DEV
  echo "[filter]"
  tc -s filter show dev $DEV
  exit 0
  ;;
 rates)
  tc class change dev eth0 parent 0x1:0x0 classid 0x1:0x1 hfsc ls m2 7bps ul m2 ${UP}bps
  for DEV in eth1 eth2 eth3 wlan0 ; do
   tc class change dev $DEV parent 0x1:0x1 classid 0x1:0x2 hfsc ls m2 50bps ul m2 $(($DOWN *8/10))bps
  done
  tc class change dev wlan0_0 parent 0x1:0x1 classid 0x1:0x3 hfsc ls m2 25bps ul m2 $(($DOWN *4/10))bps
  exit
  ;;
 *)
  echo "Usage: $0 {start|stop|status|restart|rates}"
  exit 1
  ;;
esac


# DESCRIPTION           CLASSID         RT LS UL
# eth0 root qdisc HFSC  0x1:0x0         N  N  N
# + root                0x1:0x1         N  Y  Y
#   + ipv4              0x1:0x4         N  Y  N
#     + router          0x1:0x2         N  Y  N
#       + prio 1        0x1:0x21        Y  Y  N
#       + ...
#     + private         0x1:0x8         N  Y  Y
#       + prio 1        0x1:0x81        Y  Y  N
#       + ...
#     + public          0x1:0x9         N  Y  Y
#       + prio 1        0x1:0x91        Y  Y  N
#       + ...
#   + ipv6              0x1:0x6         N  Y  N
# + default             0x1:0x3         N  Y  N

# aiccu root qdisc HFSC 0x1:0x0         N  N  N
# + root                0x1:0x1         N  Y  N
#   + router            0x1:0x2         N  Y  N
#     + prio 1          0x1:0x21        Y  Y  N
#       + ...
#   + private           0x1:0x8         N  Y  N
#     + prio 1          0x1:0x81        Y  Y  N
#       + ...
#   + public            0x1:0x9         N  Y  N
#     + prio 1          0x1:0x91        Y  Y  N
#       + ...
# + default             0x1:0x3         N  Y  N

tc qdisc add dev eth0 handle 0x1:0x0 root hfsc default 0x3
tc class add dev eth0 parent 0x1:0x0 classid 0x1:0x1 hfsc ls m2 10bps ul m2 ${UP}bps
tc class add dev eth0 parent 0x1:0x0 classid 0x1:0x3 hfsc ls m2 2bps ul m2 ${UP}bps
tc class add dev eth0 parent 0x1:0x1 classid 0x1:0x4 hfsc ls m2 10bps
tc class add dev eth0 parent 0x1:0x1 classid 0x1:0x6 hfsc ls m2 10bps
tc class add dev eth0 parent 0x1:0x4 classid 0x1:0x2 hfsc ls m2 25bps # router
tc class add dev eth0 parent 0x1:0x4 classid 0x1:0x8 hfsc ls m2 50bps # private
tc class add dev eth0 parent 0x1:0x4 classid 0x1:0x9 hfsc ls m2 25bps # public

tc qdisc add dev aiccu handle 0x1:0x0 root hfsc default 0x3
tc class add dev aiccu parent 0x1:0x0 classid 0x1:0x1 hfsc ls m2 10bps
tc class add dev aiccu parent 0x1:0x0 classid 0x1:0x3 hfsc ls m2 2bps
tc class add dev aiccu parent 0x1:0x1 classid 0x1:0x2 hfsc ls m2 25bps # router
tc class add dev aiccu parent 0x1:0x1 classid 0x1:0x8 hfsc ls m2 50bps # private
tc class add dev aiccu parent 0x1:0x1 classid 0x1:0x9 hfsc ls m2 25bps # public

priority_classes() {
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}1 hfsc ls m2 8bps rt m2 8192bps
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}2 hfsc ls m2 10bps rt m2 10240bps
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}3 hfsc ls m2 24bps rt m2 10240bps
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}4 hfsc ls m1 20bps d 24s m2 18bps rt m2 8192bps
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}5 hfsc ls m1 16bps d 16s m2 14bps
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}6 hfsc ls m1 10bps d 8s m2 8bps
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}7 hfsc ls m2 6bps
 tc class add dev $DEV parent 0x1:0x$PARENT classid 0x1:0x${PARENT}8 hfsc ls m2 4bps
}

for PARENT in 2 8 9 ; do
 for DEV in eth0 aiccu ;  do
  priority_classes
 done
done


# local interfaces
PARENT=1
for DEV in eth1 eth2 eth3 wlan0 wlan0_0 ; do
 tc qdisc add dev $DEV handle 0x1:0x0 root hfsc default 0x3
 tc class add dev $DEV parent 0x1:0x0 classid 0x1:0x1 hfsc ls m2 10bps
 tc class add dev $DEV parent 0x1:0x0 classid 0x1:0x3 hfsc ls m2 2bps
 priority_classes
done


For bandwidth testing, you could create /usr/local/sbin/bandwidth-test.sh:

 #!/bin/sh  # What markup will make this line correct?
set -e

MAXTIME=30

# get previous limits
UP_OLD=$( cat /var/local/up-bytes.txt 2> /dev/null ) || true
DOWN_OLD=$( cat /var/local/down-bytes.txt 2> /dev/null ) || true

# set limits high for testing
echo 2072576 >| /var/local/up-bytes.txt
echo 2072576 >| /var/local/down-bytes.txt

# set shaping rates
shaping.sh rates

# start measuring
OUTPUT=$( mktemp )
FILTERED=$( mktemp )
bwm-ng -T max -I eth0 -o csv -c 0 >> $OUTPUT &
MON_PID=$!

# Use the network as much as possible, both up and down, here
 TMPFILE=$( mktemp /tmp/testfile_rand_5m.XXX )
 dd if=/dev/urandom of=$TMPFILE bs=1048576 count=16 2> /dev/null &
 DD_PID=$!
## DOWN
 echo "starting DOWN"
 curl --ipv4 --silent --max-time $MAXTIME "http://linux.mirrors.es.net/fedora/releases/12/Fedora/i386/iso/Fedora-12-i386-disc1.iso" > /dev/null || true &
  DOWN1_PID=$!
 curl --ipv4 --silent --max-time $MAXTIME "http://nas1.itc.virginia.edu/fedora/releases/12/Fedora/i386/iso/Fedora-12-i386-DVD.iso" > /dev/null || true &
  DOWN2_PID=$!
 wait $DOWN1_PID
 wait $DOWN2_PID
 echo "finished DOWN"
## UP
 sleep 2s
 wait $DD_PID
 echo "starting UP"
 curl --ipv4 --silent --max-time $MAXTIME --form file=@$TMPFILE http://www.senduit.com/ > /dev/null || true &
  UP1_PID=$!
 wait $UP1_PID
 echo "finished UP"
 rm -f $TMPFILE

# stop measuring
kill -s INT $MON_PID
wait $MON_PID
tail -n 2 < $OUTPUT | grep eth0 >> $FILTERED

# Write new limits
gawk -F ";" '{ print $3 }' < $FILTERED | sed -r 's/\..*$//' >| /var/local/up-bytes.txt
gawk -F ";" '{ print $4 }' < $FILTERED | sed -r 's/\..*$//' >| /var/local/down-bytes.txt

# Apply new limits
shaping.sh rates

rm -f $OUTPUT
rm -f $FILTERED

rsyslog

Logging everything to rsyslog and then to only a few files helps keep logging simpler and disk usage more easily controlled. To see a particular facility or priority, use grep.

First, create a log rotation script /usr/local/sbin/clogrotate.sh:

 #!/bin/sh  # What markup will make this line correct?
# rotates channel logs; executed by rsyslog (see rsyslog.conf)
mv -f $1 ${1}.1
#gzip ${1}.1  # disabled because I'm running on Flash media


Then rsyslog.conf:

# [modules]
$ModLoad imuxsock # provides support for local system logging
$ModLoad imklog   # provides kernel logging support

# [templates]
$template FullFileFormat,"%timestamp:::date-rfc3339% %syslogfacility-text%.%syslogseverity-text% %syslogtag%%msg%\n"
$ActionFileDefaultTemplate FullFileFormat

# [log file permissions]
$FileOwner root
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022

# [channels]
$outchannel systemlog,/var/log/systemlog,104857600,clogrotate.sh /var/log/systemlog
$outchannel errlog,/var/log/errlog,26214400,clogrotate.sh /var/log/errlog

# [main]
$IncludeConfig /etc/rsyslog.d/*.conf
*.emerg                         *
*.err                           $errlog
*.notice                        $systemlog

Finish

Make those scripts executable:  chmod u+x /usr/local/sbin/* 

Save the firewall scripts:  build-firewall.sh save 

/etc/rc.local should look like this:

 #!/bin/sh  # What markup will make this line correct?
failed() {
 /usr/bin/logger -p local0.debug -t "`basename $0`[$$]" "$*"
 echo "$*" | mail -s "Startup failure" root
}

iptables-restore /etc/network/iptables || failed "iptables"
ip6tables-restore /etc/network/ip6tables || failed "ip6tables"
/usr/local/sbin/shaping.sh start || failed "shaping.sh"

Contact/Comments

Feedback is appreciated.

You can contact me at greenfreedom10@gmail.com.

  • I'd suggest recording the installation parts in the InstallingDebianOn namespace -- PaulWise 2010-02-21 01:01:02

    • Thanks Paul, but I do not plan to include any hardware-specific installation information. I added a note above. -- ?green 2010-02-21 03:08:07

      • Contributing to InstallingDebianOn would still be appreciated, as would the hardware info that the InstallingDebianOn templates suggest to add -- PaulWise 2010-02-21 12:37:45

        • Done, though it probably needs further work. -- ?green 2010-02-22 03:38:53