Differences between revisions 47 and 48
Revision 47 as of 2010-11-16 17:37:08
Size: 41011
Editor: ?green
Comment:
Revision 48 as of 2011-01-25 20:23:46
Size: 22981
Editor: ?green
Comment: Update multiple sections
Deletions are marked like this. Additions are marked like this.
Line 4: Line 4:
I have been working to set up a [[http://www.soekris.com/net5501.htm|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.'''
I have set up a [[http://www.soekris.com/net5501.htm|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.
Line 11: Line 9:

''[[#Comments|Feedback is appreciated.]]''
Line 31: Line 31:
  * With [[#UPnP|UPnP]] support
  * Modify TOS packet header bits
Line 34: Line 32:
  * Use TOS packet header bits
Line 45: Line 42:
 * 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)
 * private local ipv4 network: 192.0.2.0/24
 * public local ipv4 network: 192.0.3.0/24
Line 165: Line 162:
Change this line: Comment this line by prepending a hash (#):
Line 170: Line 167:
To: And add these lines:
Line 173: Line 170:
192.0.3.1 hostname.example.org hostname2.example2.org hostname
Line 179: Line 177:
{{{dnsmasq.conf}}}: Edit {{{dnsmasq.conf}}}:
Line 220: Line 218:
#dhcp-host=xx:xx:xx:xx:xx:xx,192.0.2.10 #dhcp-host=xx:xx:xx:xx:xx:xx,192.0.2.5
Line 229: Line 227:
# Google Public DNS
nameserver 8.8.8.8
nameserver 8.8.4.4
# OpenNIC T2 - other servers available at opennicproject.org
nameserver 216.87.84.211 # US,CO
nameserver 2001:470:8388:10:0:100:53:20 # US,CO
nameserver 66.244.95.20 # US,IN
nameserver 2001:470:1f10:c6::2 # US,IN
Line 246: Line 246:
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 [[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.'''

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
Firewall shell scripts are slow and cumbersome. The [[http://packages.debian.org/ferm|ferm]] firewall utility makes writing and using firewall rules easier and faster.

Add this line to {{{/etc/rc.local}}}:
{{{
ferm /etc/ferm/ferm.conf
}}}

Create {{{/etc/ferm/ferm.conf}}}:
{{{
# ferm rules
# http://ferm.foo-projects.org/


# CHAIN POLICIES
domain ip {
 table nat chain (PREROUTING OUTPUT POSTROUTING) policy ACCEPT;
}
domain (ip|ip6) {
 table raw chain (PREROUTING OUTPUT) policy ACCEPT;
 table mangle chain (PREROUTING INPUT FORWARD OUTPUT POSTROUTING) policy ACCEPT;
 table filter {
  chain (INPUT FORWARD) policy DROP;
  chain OUTPUT policy ACCEPT;
 }
}


# DNAT for inbound connection forwarding
domain ip {
 table nat {
  chain PREROUTING interface eth0 jump DNAT_MOD; # all new inbound connections
  chain DNAT_MOD { # DNAT modified in subchains of this chain
   protocol (tcp|udp) @subchain {
    jump DNAT_SKIP;
    jump DNAT_MANUAL;
    jump DNAT_UPNP;
    jump DNAT_ALLPORTS;
   }
  }
  chain DNAT_SKIP { # Keep service ports from being changed by manual/upnp/allports
   #protocol tcp dport 80 ACCEPT;
  }
  chain DNAT_MANUAL { # Manually forwarded ports
   protocol (tcp udp) dport 5155 DNAT to 192.168.2.50:5154; # forward to LAN host
   #protocol tcp dport 81 DNAT to :80; # forward to different local port
  }
  chain DNAT_UPNP; # UPNP forwarded ports
  chain DNAT_ALLPORTS { # Manually forwarded (ALL) ports
   DNAT to 192.168.2.5;
  }
 }
 table filter {
  chain FORWARD interface eth0 jump DNAT_FORWARD;
  chain DNAT_FORWARD {
   protocol (tcp udp) dport 5155 daddr 192.168.2.50/24 ACCEPT;
   daddr 192.168.2.5/24 ACCEPT;
   outerface (br0 wlan0_0) jump UPNP_FORWARD; # check about wlan0_0
  }
  chain UPNP_FORWARD;
 }
}


# ACCEPT
# ipv6
domain ip table filter chain (INPUT OUTPUT) protocol ipv6 ACCEPT;

# lo
domain (ip ip6) table filter {
 chain INPUT interface lo ACCEPT;
 chain OUTPUT outerface lo ACCEPT;
}

# icmp
domain (ip ip6) table filter chain (INPUT OUTPUT) protocol icmp ACCEPT;


# DROP
# RH0
domain ip6 table filter {
 chain (INPUT FORWARD OUTPUT) mod rt rt-type 0 @subchain {
  mod limit limit 20/min limit-burst 2 LOG log-prefix "DROP-RH0 " log-level info;
  DROP;
 }
}

# Host block
domain (ip ip6) table filter {
 chain (INPUT FORWARD OUTPUT) jump HOST_BLOCK;
 chain HOST_BLOCK {
  # example
  #source 77.77.77.77/24 jump HOST_BLOCK_EXEC;
 }
 chain HOST_BLOCK_EXEC {
  mod limit limit 8/min limit-burst 4 LOG log-prefix "DROP_hostblock " log-level notice;
  DROP;
 }
}

# invalid
domain (ip ip6) table filter chain (INPUT FORWARD OUTPUT) mod state state INVALID @subchain {
 mod limit limit 20/min limit-burst 2 LOG log-prefix "DROP-invalid " log-level info;
 DROP;
}


# SERVICES
@def &DNAT_SKIP($protocol, $port) = { # Make inbound connections resilient against DNAT manual/upnp/allports forwarding
 domain ip table nat chain DNAT_SKIP protocol $protocol dport $port ACCEPT;
}

# established/related connections
domain (ip ip6) table filter chain (INPUT OUTPUT) mod state state (ESTABLISHED RELATED) ACCEPT;

# local dhcp
domain (ip ip6) table filter {
 chain INPUT protocol udp interface (br0 wlan0_0) mod multiport ports (bootps bootpc) ACCEPT;
 chain OUTPUT protocol udp outerface (br0 wlan0_0) mod multiport ports (bootps bootpc) ACCEPT;
}

# ssh
&DNAT_SKIP(tcp, ssh);
domain (ip ip6) table filter {
 chain INPUT protocol tcp dport ssh mod state state NEW @subchain {
  mod recent name SSH {
   set NOP;
   update seconds 300 hitcount 8 @subchain {
    LOG log-prefix Blocked-ssh_ log-level warning;
    DROP;
   }
  }
  ACCEPT;
 }
}

# upstream dhcp
&DNAT_SKIP(tcp, bootps:bootpc);
domain (ip ip6) table filter {
 chain INPUT protocol udp interface eth0 sport bootps:bootpc ACCEPT;
 chain OUTPUT protocol udp outerface eth0 sport bootps:bootpc ACCEPT;
}

# SixXS/AYIYA/aiccu
domain ip table filter chain OUTPUT outerface eth0 {
 protocol tcp dport 3874 ACCEPT;
 protocol udp mod multiport destination-ports (3740 5072) ACCEPT;
}

# dns
&DNAT_SKIP((tcp udp), domain);
domain (ip ip6) table filter {
 chain INPUT protocol (tcp udp) dport domain @subchain {
  interface (br0 wlan0_0) ACCEPT;
 }
 chain OUTPUT protocol (tcp udp) dport domain outerface eth0 ACCEPT;
}
domain ip6 table filter chain OUTPUT protocol (tcp udp) outerface aiccu dport domain ACCEPT;

# ntp
&DNAT_SKIP(udp, ntp);
domain (ip ip6) table filter {
 chain INPUT protocol udp dport ntp ACCEPT;
 chain OUTPUT protocol udp sport ntp ACCEPT;
}

# www/https
&DNAT_SKIP(tcp, www);
domain (ip ip6) table filter chain INPUT protocol tcp dport www ACCEPT;


# FORWARDING
Line 326: Line 418:
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
domain ip table nat chain POSTROUTING saddr (192.168.2.0/24 192.168.3.0/24) outerface eth0 MASQUERADE;

# ipv6
domain ip table filter chain FORWARD protocol ipv6 ACCEPT;
Line 413: Line 424:
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
domain (ip ip6) table filter chain FORWARD mod state state (ESTABLISHED RELATED) ACCEPT;

# divide
domain (ip ip6) table filter chain FORWARD {
 interface eth0 {
  outerface br0 jump INET_TO_PRIVATE;
  outerface wlan0_0 jump INET_TO_PUBLIC;
 }
 interface br0 {
  outerface eth0 jump PRIVATE_TO_INET;
  outerface br0 jump PRIVATE_TO_PRIVATE;
  outerface wlan0_0 jump PRIVATE_TO_PUBLIC;
 }
 interface wlan0_0 {
  outerface eth0 jump PUBLIC_TO_INET;
  outerface br0 jump PUBLIC_TO_PRIVATE;
  outerface wlan0_0 jump PUBLIC_TO_PUBLIC;
 }
}
domain ip6 table filter chain FORWARD {
 interface aiccu {
  outerface br0 jump INET_TO_PRIVATE;
  outerface wlan0_0 jump INET_TO_PUBLIC;
 }
 interface br0 outerface aiccu jump PRIVATE_TO_INET;
 interface wlan0_0 outerface aiccu jump PUBLIC_TO_INET;
}

# internet to private
domain ip table filter chain INET_TO_PRIVATE daddr 192.168.2.5/24 ACCEPT;
domain (ip ip6) table filter chain INET_TO_PRIVATE mod limit limit 4/min LOG log-prefix "Rejected-internet-to-private " log-level info;
domain ip6 table filter chain INET_TO_PRIVATE REJECT reject-with icmp6-adm-prohibited;

# internet to public
domain (ip ip6) table filter chain INET_TO_PUBLIC mod limit limit 4/min LOG log-prefix "Rejected-internet-to-public " log-level info;
domain ip6 table filter chain INET_TO_PUBLIC REJECT reject-with icmp6-adm-prohibited;

# private to internet
domain (ip ip6) table filter chain PRIVATE_TO_INET ACCEPT;

# public to internet
domain (ip ip6) table filter chain PUBLIC_TO_INET ACCEPT;

# private to private
domain (ip ip6) table filter chain PRIVATE_TO_PRIVATE ACCEPT;

# private to public
domain ip table filter chain PRIVATE_TO_PUBLIC saddr 192.168.2.5/24 ACCEPT;
domain (ip ip6) table filter chain PRIVATE_TO_PUBLIC mod limit limit 3/min LOG log-prefix "Rejected-private-to-public " log-level info;
domain ip table filter chain PRIVATE_TO_PUBLIC REJECT reject-with icmp-net-prohibited;
domain ip6 table filter chain PRIVATE_TO_PUBLIC REJECT reject-with icmp6-adm-prohibited;

# public to public
domain (ip ip6) table filter chain PUBLIC_TO_PUBLIC mod limit limit 3/min LOG log-prefix "Rejected-public-to-public " log-level info;
domain ip table filter chain PUBLIC_TO_PUBLIC REJECT reject-with icmp-host-prohibited;
domain ip6 table filter chain PUBLIC_TO_PUBLIC REJECT reject-with icmp6-adm-prohibited;

# public to private
domain (ip ip6) table filter chain PUBLIC_TO_PRIVATE mod limit limit 3/min LOG log-prefix "Rejected-public-to-private " log-level info;
domain ip table filter chain PUBLIC_TO_PRIVATE REJECT reject-with icmp-net-prohibited;
domain ip6 table filter chain PUBLIC_TO_PRIVATE REJECT reject-with icmp6-adm-prohibited;


# IGNORE
# netbios
domain (ip ip6) table filter chain INPUT protocol (tcp udp) mod multiport destination-ports (netbios-ns netbios-dgm netbios-ssn) DROP;


# UNMATCHED
domain (ip ip6) table filter {
 chain INPUT mod limit limit 20/min LOG log-prefix "Unmatched-INPUT " log-level debug;
 chain FORWARD mod limit limit 20/min LOG log-prefix "Unmatched-FORWARD " log-level debug;
 #chain OUTPUT mod limit limit 20/min LOG log-prefix "Unmatched-OUTPUT " log-level debug;
}

# policy
domain (ip ip6) table filter chain INPUT protocol tcp mod state state NEW REJECT reject-with tcp-reset;
domain ip table filter chain INPUT mod addrtype dst-type (UNICAST MULTICAST) REJECT reject-with icmp-admin-prohibited;
domain ip6 table filter chain INPUT mod pkttype pkt-type (UNICAST MULTICAST) REJECT reject-with icmp6-adm-prohibited;
#domain ip table filter chain OUTPUT -j REJECT reject-with icmp-admin-prohibited;
#domain ip6 table filter chain OUTPUT -j REJECT reject-with icmp6-adm-prohibited;
Line 633: Line 508:
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 [[http://linux-igd.sourceforge.net/documentation.php#SECURITY|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
domain (ip ip6) table mangle chain FORWARD outerface eth0 protocol tcp mod tcp tcp-flags (SYN RST) SYN TCPMSS clamp-mss-to-pmtu;
domain ip6 table mangle chain FORWARD outerface aiccu protocol tcp mod tcp tcp-flags (SYN RST) SYN TCPMSS clamp-mss-to-pmtu;
Line 738: Line 516:
{{{hostapd.conf}}}: Edit {{{hostapd.conf}}}:
Line 783: Line 561:
Create {{{/usr/local/sbin/shaping.sh}}}:
{{{
 #!/bin/sh # What markup will make this line correct?
Okay, traffic shaping is hideous. I do not have 3 extra lifetimes to spend on trying to make it work like I want it, so I just use the [[http://packages.debian.org/wondershaper|wondershaper]] package and hope it works.

Add this line to {{{/etc/rc.local}}}:
{{{
shaping.sh start
}}}

Create file {{{/usr/local/sbin/shaping.sh}}} (make it executable):
{{{
 #!/bin/sh
Line 787: Line 572:

# 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
}
Line 817: Line 575:
  remove   wondershaper eth0 $(( $(cat /var/local/down-bytes.txt)*8/1024 )) $(( $(cat /var/local/up-bytes.txt)*8/1024 ))
Line 820: Line 578:
  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
  wondershaper clear eth0
Line 841: Line 581:
  echo "Usage: $0 {start|stop|status|restart|rates}"   echo "Usage: $0 {start|restart|stop}"
  echo
  echo "start/restart: set up all shaping"
  echo "stop: remove all shaping"
Line 845: Line 588:


# 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?
}}}

Then, for bandwidth testing (is there an easier way?), create {{{/usr/local/sbin/bandwidth-test.sh}}} (make it executable):
{{{
 #!/bin/sh
Line 929: Line 598:
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
OLD_UP=$( cat /var/local/up-bytes.txt 2> /dev/null ) || true
OLD_DOWN=$( cat /var/local/down-bytes.txt 2> /dev/null ) || true

# disable shaping
shaping.sh stop
Line 946: Line 611:
 TMPFILE=$( mktemp /tmp/testfile_rand_5m.XXX )  TMPFILE=$( mktemp /tmp/testfile.XXX )
Line 972: Line 637:

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

# Apply new limits
shaping.sh rates
MEASURED_UP=$( awk -F ";" '{ print $3 }' < $FILTERED | sed -r 's/\..*$//' )
MEASURED_DOWN=$(
awk -F ";" '{ print $4 }' < $FILTERED | sed -r 's/\..*$//' )
Line 982: Line 641:

# Write new limits
echo $MEASURED_UP >| /var/local/up-bytes.txt
echo $MEASURED_DOWN >| /var/local/down-bytes.txt

# Echo new limits
MEASURED_UP_KB=$( echo "scale=1; $MEASURED_UP / 1024" | bc )
MEASURED_DOWN_KB=$( echo "scale=1; $MEASURED_DOWN / 1024" | bc )
OLD_UP_KB=$( echo "scale=1; $OLD_UP / 1024" | bc )
OLD_DOWN_KB=$( echo "scale=1; $OLD_DOWN / 1024" | bc )
echo "OLD_UP: $OLD_UP_KB"
echo "OLD_DOWN: $OLD_DOWN_KB"
echo "NEW_UP: $MEASURED_UP_KB"
echo "NEW_DOWN: $MEASURED_DOWN_KB"

# Set up shaping
shaping.sh start
Line 988: Line 664:
First, create a log rotation script {{{/usr/local/sbin/clogrotate.sh}}}:
{{{
 #!/bin/sh  # What markup will make this line correct?
First, create a log rotation script {{{/usr/local/sbin/clogrotate.sh}}} (make it executable):
{{{
 #!/bin/sh
Line 996: Line 672:
----
Then {{{rsyslog.conf}}}:
Then edit {{{rsyslog.conf}}}:
Line 1026: Line 701:
= 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"
}}}

I have 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.

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.

?Feedback is appreciated.

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)
  • ?Traffic control to provide a better internet experience for multiple users/connections

  • 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
  • public local ipv4 network: 192.0.3.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:

Comment this line by prepending a hash (#):

127.0.1.1      hostname.example.org hostname

And add these lines:

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

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

dnsmasq

Edit 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.5

# 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:

# OpenNIC T2 - other servers available at opennicproject.org
nameserver      216.87.84.211                           # US,CO
nameserver      2001:470:8388:10:0:100:53:20            # US,CO
nameserver      66.244.95.20                            # US,IN
nameserver      2001:470:1f10:c6::2                     # US,IN

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 and cumbersome. The ferm firewall utility makes writing and using firewall rules easier and faster.

Add this line to /etc/rc.local:

ferm /etc/ferm/ferm.conf

Create /etc/ferm/ferm.conf:

# ferm rules
# http://ferm.foo-projects.org/


# CHAIN POLICIES
domain ip {
 table nat chain (PREROUTING OUTPUT POSTROUTING) policy ACCEPT;
}
domain (ip|ip6) {
 table raw chain (PREROUTING OUTPUT) policy ACCEPT;
 table mangle chain (PREROUTING INPUT FORWARD OUTPUT POSTROUTING) policy ACCEPT;
 table filter {
  chain (INPUT FORWARD) policy DROP;
  chain OUTPUT policy ACCEPT;
 }
}


# DNAT for inbound connection forwarding
domain ip {
 table nat {
  chain PREROUTING interface eth0 jump DNAT_MOD; # all new inbound connections
  chain DNAT_MOD { # DNAT modified in subchains of this chain
   protocol (tcp|udp) @subchain {
    jump DNAT_SKIP;
    jump DNAT_MANUAL;
    jump DNAT_UPNP;
    jump DNAT_ALLPORTS;
   }
  }
  chain DNAT_SKIP { # Keep service ports from being changed by manual/upnp/allports
   #protocol tcp dport 80 ACCEPT;
  }
  chain DNAT_MANUAL { # Manually forwarded ports
   protocol (tcp udp) dport 5155 DNAT to 192.168.2.50:5154; # forward to LAN host
   #protocol tcp dport 81 DNAT to :80; # forward to different local port
  }
  chain DNAT_UPNP; # UPNP forwarded ports
  chain DNAT_ALLPORTS { # Manually forwarded (ALL) ports
   DNAT to 192.168.2.5;
  }
 }
 table filter {
  chain FORWARD interface eth0 jump DNAT_FORWARD;
  chain DNAT_FORWARD {
   protocol (tcp udp) dport 5155 daddr 192.168.2.50/24 ACCEPT;
   daddr 192.168.2.5/24 ACCEPT;
   outerface (br0 wlan0_0) jump UPNP_FORWARD; # check about wlan0_0
  }
  chain UPNP_FORWARD;
 }
}


# ACCEPT
# ipv6
domain ip table filter chain (INPUT OUTPUT) protocol ipv6 ACCEPT;

# lo
domain (ip ip6) table filter {
 chain INPUT interface lo ACCEPT;
 chain OUTPUT outerface lo ACCEPT;
}

# icmp
domain (ip ip6) table filter chain (INPUT OUTPUT) protocol icmp ACCEPT;


# DROP
# RH0
domain ip6 table filter {
 chain (INPUT FORWARD OUTPUT) mod rt rt-type 0 @subchain {
  mod limit limit 20/min limit-burst 2 LOG log-prefix "DROP-RH0 " log-level info;
  DROP;
 }
}

# Host block
domain (ip ip6) table filter {
 chain (INPUT FORWARD OUTPUT) jump HOST_BLOCK;
 chain HOST_BLOCK {
  # example
  #source 77.77.77.77/24 jump HOST_BLOCK_EXEC;
 }
 chain HOST_BLOCK_EXEC {
  mod limit limit 8/min limit-burst 4 LOG log-prefix "DROP_hostblock " log-level notice;
  DROP;
 }
}

# invalid
domain (ip ip6) table filter chain (INPUT FORWARD OUTPUT) mod state state INVALID @subchain {
 mod limit limit 20/min limit-burst 2 LOG log-prefix "DROP-invalid " log-level info;
 DROP;
}


# SERVICES
@def &DNAT_SKIP($protocol, $port) = { # Make inbound connections resilient against DNAT manual/upnp/allports forwarding
 domain ip table nat chain DNAT_SKIP protocol $protocol dport $port ACCEPT;
}

# established/related connections
domain (ip ip6) table filter chain (INPUT OUTPUT) mod state state (ESTABLISHED RELATED) ACCEPT;

# local dhcp
domain (ip ip6) table filter {
 chain INPUT protocol udp interface (br0 wlan0_0) mod multiport ports (bootps bootpc) ACCEPT;
 chain OUTPUT protocol udp outerface (br0 wlan0_0) mod multiport ports (bootps bootpc) ACCEPT;
}

# ssh
&DNAT_SKIP(tcp, ssh);
domain (ip ip6) table filter {
 chain INPUT protocol tcp dport ssh mod state state NEW @subchain {
  mod recent name SSH {
   set NOP;
   update seconds 300 hitcount 8 @subchain {
    LOG log-prefix Blocked-ssh_ log-level warning;
    DROP;
   }
  }
  ACCEPT;
 }
}

# upstream dhcp
&DNAT_SKIP(tcp, bootps:bootpc);
domain (ip ip6) table filter {
 chain INPUT protocol udp interface eth0 sport bootps:bootpc ACCEPT;
 chain OUTPUT protocol udp outerface eth0 sport bootps:bootpc ACCEPT;
}

# SixXS/AYIYA/aiccu
domain ip table filter chain OUTPUT outerface eth0 {
 protocol tcp dport 3874 ACCEPT;
 protocol udp mod multiport destination-ports (3740 5072) ACCEPT;
}

# dns
&DNAT_SKIP((tcp udp), domain);
domain (ip ip6) table filter {
 chain INPUT protocol (tcp udp) dport domain @subchain {
  interface (br0 wlan0_0) ACCEPT;
 }
 chain OUTPUT protocol (tcp udp) dport domain outerface eth0 ACCEPT;
}
domain ip6 table filter chain OUTPUT protocol (tcp udp) outerface aiccu dport domain ACCEPT;

# ntp
&DNAT_SKIP(udp, ntp);
domain (ip ip6) table filter {
 chain INPUT protocol udp dport ntp ACCEPT;
 chain OUTPUT protocol udp sport ntp ACCEPT;
}

# www/https
&DNAT_SKIP(tcp, www);
domain (ip ip6) table filter chain INPUT protocol tcp dport www ACCEPT;


# FORWARDING
# masquerading
domain ip table nat chain POSTROUTING saddr (192.168.2.0/24 192.168.3.0/24) outerface eth0 MASQUERADE;

# ipv6
domain ip table filter chain FORWARD protocol ipv6 ACCEPT;

# established connections
domain (ip ip6) table filter chain FORWARD mod state state (ESTABLISHED RELATED) ACCEPT;

# divide
domain (ip ip6) table filter chain FORWARD {
 interface eth0 {
  outerface br0 jump INET_TO_PRIVATE;
  outerface wlan0_0 jump INET_TO_PUBLIC;
 }
 interface br0 {
  outerface eth0 jump PRIVATE_TO_INET;
  outerface br0 jump PRIVATE_TO_PRIVATE;
  outerface wlan0_0 jump PRIVATE_TO_PUBLIC;
 }
 interface wlan0_0 {
  outerface eth0 jump PUBLIC_TO_INET;
  outerface br0 jump PUBLIC_TO_PRIVATE;
  outerface wlan0_0 jump PUBLIC_TO_PUBLIC;
 }
}
domain ip6 table filter chain FORWARD {
 interface aiccu {
  outerface br0 jump INET_TO_PRIVATE;
  outerface wlan0_0 jump INET_TO_PUBLIC;
 }
 interface br0 outerface aiccu jump PRIVATE_TO_INET;
 interface wlan0_0 outerface aiccu jump PUBLIC_TO_INET;
}

# internet to private
domain ip table filter chain INET_TO_PRIVATE daddr 192.168.2.5/24 ACCEPT;
domain (ip ip6) table filter chain INET_TO_PRIVATE mod limit limit 4/min LOG log-prefix "Rejected-internet-to-private " log-level info;
domain ip6 table filter chain INET_TO_PRIVATE REJECT reject-with icmp6-adm-prohibited;

# internet to public
domain (ip ip6) table filter chain INET_TO_PUBLIC mod limit limit 4/min LOG log-prefix "Rejected-internet-to-public " log-level info;
domain ip6 table filter chain INET_TO_PUBLIC REJECT reject-with icmp6-adm-prohibited;

# private to internet
domain (ip ip6) table filter chain PRIVATE_TO_INET ACCEPT;

# public to internet
domain (ip ip6) table filter chain PUBLIC_TO_INET ACCEPT;

# private to private
domain (ip ip6) table filter chain PRIVATE_TO_PRIVATE ACCEPT;

# private to public
domain ip table filter chain PRIVATE_TO_PUBLIC saddr 192.168.2.5/24 ACCEPT;
domain (ip ip6) table filter chain PRIVATE_TO_PUBLIC mod limit limit 3/min LOG log-prefix "Rejected-private-to-public " log-level info;
domain ip table filter chain PRIVATE_TO_PUBLIC REJECT reject-with icmp-net-prohibited;
domain ip6 table filter chain PRIVATE_TO_PUBLIC REJECT reject-with icmp6-adm-prohibited;

# public to public
domain (ip ip6) table filter chain PUBLIC_TO_PUBLIC mod limit limit 3/min LOG log-prefix "Rejected-public-to-public " log-level info;
domain ip table filter chain PUBLIC_TO_PUBLIC REJECT reject-with icmp-host-prohibited;
domain ip6 table filter chain PUBLIC_TO_PUBLIC REJECT reject-with icmp6-adm-prohibited;

# public to private
domain (ip ip6) table filter chain PUBLIC_TO_PRIVATE mod limit limit 3/min LOG log-prefix "Rejected-public-to-private " log-level info;
domain ip table filter chain PUBLIC_TO_PRIVATE REJECT reject-with icmp-net-prohibited;
domain ip6 table filter chain PUBLIC_TO_PRIVATE REJECT reject-with icmp6-adm-prohibited;


# IGNORE
# netbios
domain (ip ip6) table filter chain INPUT protocol (tcp udp) mod multiport destination-ports (netbios-ns netbios-dgm netbios-ssn) DROP;


# UNMATCHED
domain (ip ip6) table filter {
 chain INPUT mod limit limit 20/min LOG log-prefix "Unmatched-INPUT " log-level debug;
 chain FORWARD mod limit limit 20/min LOG log-prefix "Unmatched-FORWARD " log-level debug;
 #chain OUTPUT mod limit limit 20/min LOG log-prefix "Unmatched-OUTPUT " log-level debug;
}

# policy
domain (ip ip6) table filter chain INPUT protocol tcp mod state state NEW REJECT reject-with tcp-reset;
domain ip table filter chain INPUT mod addrtype dst-type (UNICAST MULTICAST) REJECT reject-with icmp-admin-prohibited;
domain ip6 table filter chain INPUT mod pkttype pkt-type (UNICAST MULTICAST) REJECT reject-with icmp6-adm-prohibited;
#domain ip table filter chain OUTPUT -j REJECT reject-with icmp-admin-prohibited;
#domain ip6 table filter chain OUTPUT -j REJECT reject-with icmp6-adm-prohibited;


# TCPMSS clamp
domain (ip ip6) table mangle chain FORWARD outerface eth0 protocol tcp mod tcp tcp-flags (SYN RST) SYN TCPMSS clamp-mss-to-pmtu;
domain ip6 table mangle chain FORWARD outerface aiccu protocol tcp mod tcp tcp-flags (SYN RST) SYN TCPMSS clamp-mss-to-pmtu;

hostapd

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

Edit 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

Okay, traffic shaping is hideous. I do not have 3 extra lifetimes to spend on trying to make it work like I want it, so I just use the wondershaper package and hope it works.

Add this line to /etc/rc.local:

shaping.sh start

Create file /usr/local/sbin/shaping.sh (make it executable):

 #!/bin/sh
set -e

case "$1" in
 start|restart)
  wondershaper eth0 $(( $(cat /var/local/down-bytes.txt)*8/1024 )) $(( $(cat /var/local/up-bytes.txt)*8/1024 ))
  ;;
 stop)
  wondershaper clear eth0
  ;;
 *)
  echo "Usage: $0 {start|restart|stop}"
  echo
  echo "start/restart: set up all shaping"
  echo "stop: remove all shaping"
  exit 1
  ;;
esac

Then, for bandwidth testing (is there an easier way?), create /usr/local/sbin/bandwidth-test.sh (make it executable):

 #!/bin/sh
set -e

MAXTIME=30

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

# disable shaping
shaping.sh stop

# 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.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
MEASURED_UP=$( awk -F ";" '{ print $3 }' < $FILTERED | sed -r 's/\..*$//' )
MEASURED_DOWN=$( awk -F ";" '{ print $4 }' < $FILTERED | sed -r 's/\..*$//' )
rm -f $OUTPUT
rm -f $FILTERED

# Write new limits
echo $MEASURED_UP >| /var/local/up-bytes.txt
echo $MEASURED_DOWN >| /var/local/down-bytes.txt

# Echo new limits
MEASURED_UP_KB=$( echo "scale=1; $MEASURED_UP / 1024" | bc )
MEASURED_DOWN_KB=$( echo "scale=1; $MEASURED_DOWN / 1024" | bc )
OLD_UP_KB=$( echo "scale=1; $OLD_UP / 1024" | bc )
OLD_DOWN_KB=$( echo "scale=1; $OLD_DOWN / 1024" | bc )
echo "OLD_UP: $OLD_UP_KB"
echo "OLD_DOWN: $OLD_DOWN_KB"
echo "NEW_UP: $MEASURED_UP_KB"
echo "NEW_DOWN: $MEASURED_DOWN_KB"

# Set up shaping
shaping.sh start

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 (make it executable):

 #!/bin/sh
# 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 edit 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

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