Customising OpenWrt to my needs

My customisations to OpenWrt Chaos Calmer to optimise for UK FTTC. With some additional tweaks to suit my usage
avahi dnsmasq OpenWrt SQM

For the past few years i have been using OpenWrt on my home router. It’s truly an excellent Linux distribution and has progressed the state-of-the-art in home networking significantly.

Out of the box it is extremely functional but, due to needing to provide a solution fit for most situations, there are several tweaks that can be made to better tailor things to a UK connection.

This post will attempt to document the changes i have made to make OpenWrt better fit with a UK Fibre to the Cabinet (VDSL2) connection through a BT telephone line using the BT Openreach VDSL2 modem.

This will be a very long post as it contains the contents of various configuration files for my OpenWrt routers. All config files are for the current stable release of OpenWrt, ‘Chaos Calmer’.

The customisations i have made to improve UK VDSL2 compatibility are:

Additional customisations i have made to suit my own needs are:

Primary router

My primary router is a TP-Link WDR4900. It’s a simultaneous dual-band router that, interestingly enough, runs on a PPC SOC rather than the MIPS architecture more commonly found in routers.

It’s a very beefy little box, far more powerful than most routers sold even today. Some crazy fool was selling this on eBay back in 2012 and i managed to snag it for £50!

Best router i’ve ever owned, made even better by the OpenWrt firmware.

On to the config…

Networking

/etc/config/network:

config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'
	option ula_prefix 'fd1c:515e:9999::/48'

# Because my router uses a switch instead of
# dedicated physical interfaces for WAN and LAN
# i added the 'eth0' interface to bump the MTU
# up to 1508 to allow for 1500 byte PPPoE.

config interface 'eth0'
	option ifname 'eth0'
	option mtu '1508'

# Because 'eth0' above now has a 1508 MTU any
# VLANs created on it will inherit this value
# so i needed to explicitly set the LAN back
# to 1500.
#
# Also enabled igmp_snooping for the multicast.

config interface 'lan'
	option ifname 'eth0.1'
	option force_link '1'
	option proto 'static'
	option netmask '255.255.255.0'
	option ip6assign '60'
	option ipaddr '172.18.0.1'
	option mtu '1500'
	option igmp_snooping '1'

# This is the ISP's PPPoE connection.  Set the
# MTU to 1508 else it will default back to
# 1492.  It will intelligently negotiate with
# the ISP's server for a 1500 MTU.
# The connection is set to over-ride the ISP's
# DNS settings with Google's public DNS.

config interface 'wan'
	option ifname 'eth0.2'
	option proto 'pppoe'
	option username 'ISP-USERNAME'
	option password 'ISP-Password'
	option peerdns '0'
	option dns '8.8.8.8 8.8.4.4'
	option mtu '1508'
	option ipv6 '1'

# Native IPv6 with Google's IPv6 DNS over-riding
# ISP-provided settings.

config interface 'wan6'
	option ifname '@wan'
	option proto 'dhcpv6'
	option dns '2001:4860:4860::8888 2001:4860:4860::8844'
	option peerdns '0'

# YouView multicast traffic doesn't come in
# on the ISP's PPPoE connection, it's
# broadcast from the fibre cabinet.
# To receive it the interface that the PPPoE
# connection sits above must have a valid,
# private IP address (any will do).  This
# isn't used for anything else.

config interface 'iptv'
	option ifname 'eth0.2'
	option proto 'static'
	option ipaddr '10.22.22.1'
	option netmask '255.255.255.0'

# Standard OpenWrt Switch/VLAN config
# for my TP-Link WDR4900 router with
# the LAN on VLAN 1 and the WAN on
# VLAN 2.

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

config switch_vlan
	option device 'switch0'
	option vlan '1'
	option ports '0t 2 3 4 5'

config switch_vlan
	option device 'switch0'
	option vlan '2'
	option ports '0t 1'

# My additional VLANs.  Traffic for these
# VLANs will be tagged and assigned to
# the third LAN port.

config switch_vlan
	option device 'switch0'
	option vlan '10'
	option ports '0t 4t'

config switch_vlan
	option device 'switch0'
	option vlan '15'
	option ports '0t 4t'

config switch_vlan
	option device 'switch0'
	option vlan '20'
	option ports '0t 4t'

config switch_vlan
	option device 'switch0'
	option vlan '25'
	option ports '0t 4t'

# My bridged Wifi/VLAN networks.
# The MTU is explicitly set to 1500.
# In addition to IPv4 each VLAN gets
# an IPv6 /64 with an explicit hint.

config interface 'wifi_priv'
	option ifname 'eth0.10'
	option type 'bridge'
	option proto 'static'
	option ipaddr '172.18.2.1'
	option netmask '255.255.255.0'
	option ip6assign '64'
	option ip6hint 'feed'
	option mtu '1500'

config interface 'wifi5_priv'
	option ifname 'eth0.20'
	option type 'bridge'
	option proto 'static'
	option ipaddr '172.18.3.1'
	option netmask '255.255.255.0'
 	option ip6assign '64'
 	option ip6hint 'cafe'
	option mtu '1500'

config interface 'wifi_guest'
	option ifname 'eth0.15'
	option type 'bridge'
	option proto 'static'
	option ipaddr '172.18.4.1'
	option netmask '255.255.255.0'
	option ip6assign '64'
	option ip6hint 'dead'
	option mtu '1500'

config interface 'wifi5_guest'
	option ifname 'eth0.25'
	option type 'bridge'
	option proto 'static'
	option ipaddr '172.18.5.1'
	option netmask '255.255.255.0'
	option ip6assign '64'
	option ip6hint 'deaf'
	option mtu '1500'

# Create a new persistent 
# interface for the VPN.
#
# The "auto" option ensures
# it is created at boot.

config interface 'vpn0'
	option ifname 'tun0'
	option proto 'none'
	option auto '1'

Note: Keep your interface names at no more than 12 characters. When i originally set this up one of my interfaces was named wifi5_private which is 13 characters. Once OpenWrt bridges this it becomes br-wifi5_private which is 16 characters.

For some reason br-wifi5_private was truncated to br-wifi5_privat (losing its ‘e’) in /sys/devices/virtual/net/. Later, when adding the wifi5_private network to a firewall zone OpenWrt would freak out and i’d be unable to connect to anything other than the router.

Lowering the number of characters in the interface name fixed things immediately, but it took me a couple of hours to figure out the problem.

Wifi

/etc/config/wireless:

# Standard OpenWrt Wireless hardware
# config for the radios.

# ***
# Update: 2015-04-16
#
# Dropped txpower from '20' to '15' for
# both radios.  This shrinks the Wifi range
# allowing stupid client devices to drop
# their connection faster and lock on to
# another access point.
# ***
#
# Provided you have positioned the access
# points correctly you likely won't notice
# a loss in connectivity (i can run a 'ping'
# while switching and see only a single
# missed packet).

config wifi-device 'radio0'
	option type 'mac80211'
	option channel '36'
	option hwmode '11a'
	option path 'ffe09000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0'
	option htmode 'HT40'
	option country 'GB'
	option txpower '15'

config wifi-device 'radio1'
	option type 'mac80211'
	option hwmode '11g'
	option path 'ffe0a000.pcie/pci0001:02/0001:02:00.0/0001:03:00.0'
	option htmode 'HT20'
	option channel '6'
	option country 'GB'
	option txpower '15'

# The config for each SSID.  Make sure
# each SSID is attached to the correct
# VLAN as defined in /etc/config/network
# and Guest Wifi has the 'isolate' option.

# By including the word 'Fast' in the SSID
# of the 5GHz network people who can connect
# to both will gravitate towards 5GHz,
# relieving some of the congestion typical
# on 2.4GHz.  People with only 2.4GHz radios
# in their devices will be none the wiser.

config wifi-iface
	option device 'radio1'
	option mode 'ap'
	option key 'MY PRIVATE NETWORK PASSPHRASE'
	option network 'wifi_priv'
	option ssid 'Private Wifi'
	option encryption 'psk2+ccmp'

config wifi-iface
	option device 'radio0'
	option mode 'ap'
	option key 'MY PRIVATE NETWORK PASSPHRASE'
	option network 'wifi5_priv'
	option ssid 'Private Wifi (Fast)'
	option encryption 'psk2+ccmp'

config wifi-iface
	option device 'radio1'
	option mode 'ap'
	option key 'MY GUEST NETWORK PASSPHRASE'
	option network 'wifi_guest'
	option ssid 'Guest Wifi'
	option encryption 'psk2+ccmp'
	option isolate '1'

config wifi-iface
	option device 'radio0'
	option mode 'ap'
	option key 'MY GUEST NETWORK PASSPHRASE'
	option network 'wifi5_guest'
	option ssid 'Guest Wifi (Fast)'
	option encryption 'psk2+ccmp'
	option isolate '1'

DHCP

/etc/config/dhcp:

config dnsmasq
	option domainneeded '1'
	option boguspriv '1'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option expandhosts '1'
	option authoritative '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.auto'
	option local '/lan.example.org/'
	option domain 'lan.example.org'

config dhcp 'lan'
	option interface 'lan'
	option leasetime '12h'
	option dhcpv6 'server'
	option ra 'server'
	option start '201'
	option limit '50'
	option ra_management '1'

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'

config dhcp 'wifi5_priv'
	option leasetime '12h'
	option interface 'wifi5_priv'
	option dhcpv6 'server'
	option ra 'server'
	option start '201'
	option limit '50'
	option ra_management '1'

config dhcp 'wifi_priv'
	option leasetime '12h'
	option interface 'wifi_priv'
	option dhcpv6 'server'
	option ra 'server'
	option start '201'
	option limit '50'
	option ra_management '1'

# A shorter leasetime can be set for the
# guest wifi networks since guests likely
# won't be sticking around for very long,
# and you might want a quick turnaround on
# IPs if you are in a busy environment.

config dhcp 'wifi5_guest'
	option leasetime '2h'
	option interface 'wifi5_guest'
	option dhcpv6 'server'
	option ra 'server'
	option start '50'
	option limit '200'
	option ra_management '1'

config dhcp 'wifi_guest'
	option leasetime '2h'
	option interface 'wifi_guest'
	option dhcpv6 'server'
	option ra 'server'
	option start '50'
	option limit '200'
	option ra_management '1'

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'

According to the above configuration file all machines assigned addresses from this router, no matter what network interface they connect on, will receive a DNS name in the form of HOSTNAME.lan.example.org. For most people this is perfectly fine, but it may be that you want different subdomains for each network (i.e. HOSTNAME.fast.wifi.lan.example.org for machines connecting on private 5GHz wifi, HOSTNAME.wired.lan.example.org for machines using ethernet, and a subdomain of guest.wifi.lan.example.org shared between both guest wifi networks).

This is something that dnsmasq supports, but it’s not possible to configure it via /etc/config/dhcp, it must be configured directly. If you want to do this create a new file on your router:

/etc/dnsmasq.conf.domains:

domain=wired.lan.example.org,172.18.0.0/24,local
domain=slow.wifi.lan.example.org,172.18.2.0/24,local
domain=fast.wifi.lan.example.org,172.18.3.0/24,local
domain=guest.wifi.lan.example.org,172.18.4.0/24,local
domain=guest.wifi.lan.example.org,172.18.5.0/24,local

Note: Even though both guest wifi networks fall under 172.18.4.0/23 don’t be tempted to use that in the config. Unless the network is /24, /16, or /8 dnsmasq will refuse to start.

Now, to add this as an extra dnsmasq config file and add it to the list of files included in config backups, on the router run:

echo "conf-file=/etc/dnsmasq.conf.domains" >> /etc/dnsmasq.conf

echo "/etc/dnsmasq.conf.domains" >> /etc/sysupgrade.conf

IGMP Proxy

Install the igmpproxy package and edit its config file to work with YouView’s multicast. The altnet value 109.159.247.0/24 is required for YouView. The other altnet value prevents warnings in the log and should match your network(s).

/etc/config/igmpproxy:

config igmpproxy
	option quickleave 1

config phyint
	option network iptv
	option direction upstream
	list altnet 109.159.247.0/24
	list altnet 172.18.0.0/22

config phyint
	option network lan
	option direction downstream

Avahi

Install the avahi-daemon package and edit its configuration file to enable mDNS reflection between the Wired and Private Wireless networks. I use Avahi only for reflection between subnets, so also disable publishing.

/etc/avahi/avahi-daemon.conf:

[server]
	use-ipv4=yes
	use-ipv6=yes
	check-response-ttl=no
	use-iff-running=no
	allow-interfaces=eth0.1,br-wifi_priv,br-wifi5_priv
	enable-dbus=no

[publish]
	disable-publishing=yes

[reflector]
	enable-reflector=yes
	reflect-ipv=no

[rlimits]
	rlimit-core=0
	rlimit-data=4194304
	rlimit-fsize=0
	rlimit-nofile=30
	rlimit-stack=4194304
	rlimit-nproc=3

Firewall

/etc/config/firewall:

config defaults
	option syn_flood '1'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'

config zone
	option name 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	list network 'lan'

config zone
	option name 'wan'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	list network 'wan'
	list network 'wan6'
	list network 'iptv' # Added the YouView interface to the WAN zone

# Add a new zone for the private Wifi
# networks.

config zone
	option name 'wifi_private'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	list network 'wifi5_priv'
	list network 'wifi_priv'

# Add a new zone for the guest Wifi
# networks.

config zone
	option name 'wifi_guest'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'wifi5_guest'
	list network 'wifi_guest'

# Add a new zone for VPNs.

config zone
	option name 'vpn'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	list network 'vpn0'

# Configure the forwarding settings for
# zones specified above.

# The wired LAN can access the Internet,
# private wireless networks and clients
# connected to the VPN.

config forwarding
	option src 'lan'
	option dest 'wan'

config forwarding
	option src 'lan'
	option dest 'wifi_private'

config forwarding
	option src 'lan'
	option dest 'vpn'

# The private wireless networks can access
# the Internet, the wired LAN and clients
# connected to the VPN.

config forwarding
	option src 'wifi_private'
	option dest 'wan'

config forwarding
	option src 'wifi_private'
	option dest 'lan'

config forwarding
	option src 'wifi_private'
	option dest 'vpn'

# Clients connected to the VPN can access
# the Internet, the wired LAN and the
# private wireless network.

config forwarding
	option src 'vpn'
	option dest 'wan'

config forwarding
	option src 'vpn'
	option dest 'lan'

config forwarding
	option src 'vpn'
	option dest 'wifi_private'

# The Guest Wireless networks can only
# access the Internet.

config forwarding
	option src 'wifi_guest'
	option dest 'wan'

# Firewall rules.
#
# Standard OpenWrt rules.

config rule
	option name 'Allow-DHCP-Renew'
	option src 'wan'
	option proto 'udp'
	option dest_port '68'
	option target 'ACCEPT'
	option family 'ipv4'

config rule
	option name 'Allow-Ping'
	option src 'wan'
	option proto 'icmp'
	option icmp_type 'echo-request'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-IGMP'
	option src 'wan'
	option proto 'igmp'
	option family 'ipv4'
	option target 'ACCEPT'
        
config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option src_ip 'fe80::/10'
	option src_port '547'
	option dest_ip 'fe80::/10'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Input'
	option src 'wan'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Forward'
	option src 'wan'
	option dest '*'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-MLD'
	option src 'wan'
	option proto 'icmp'
	option src_ip 'fe80::/10'
	list icmp_type '130/0'
	list icmp_type '131/0'
	list icmp_type '132/0'
	list icmp_type '143/0'
	option family 'ipv6'
	option target 'ACCEPT'
        
config include
	option path '/etc/firewall.user'

# Add rules allowing YouView Multicast
# traffic, but only to Wired LAN.

config rule
	option name 'IGMP'
	option src 'wan'
	option proto 'igmp'
	option target 'ACCEPT'

config rule
	option name 'Multicast'
	option src 'wan'
	option dest 'lan'
	option dest_ip '224.0.0.0/4'
	option proto 'udp'
	option family 'ipv4'
	option target 'ACCEPT'

# Add rule allowing connections
# to the OpenVPN server from the WAN.

config rule
	option name 'Allow-OpenVPN-Inbound'
	option target 'ACCEPT'
	option src 'wan'
	option proto 'udp'
	option dest_port '1194'

# Add new rules for Guest Wifi networks
#
# Allow Guest Wifi clients to request IPv4 addresses.

config rule
	option name 'Allow-Guest-Wifi-DHCP-Request'
	option src 'wifi_guest'
	option src_port '67-68'
	option dest_port '67-68'
	option proto 'udp'
	option target 'ACCEPT'

# Allow Guest Wifi clients to request IPv6 addresses.

config rule
	option name 'Allow-Guest-Wifi-DHCPv6-Request'
	option src 'wifi_guest'
	option src_ip 'fe80::/10'
	option src_port '546'
	option dest_ip 'fe80::/10'
	option dest_port '547'
	option proto 'udp'
	option target 'ACCEPT'
	option family 'ipv6'

config rule
	option name 'Allow-Guest-Wifi-ICMPv6-Input'
	option src 'wifi_guest'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

# Allow Guest Wifi clients to make DNS queries
# to the router.

config rule
	option name 'Allow-Guest-Wifi-DNS-Queries'
	option src 'wifi_guest'
	option dest_port '53'
	option proto 'tcp udp'
	option target 'ACCEPT'

Quality of Service

Install the luci-app-sqm package. This also pulls in the other necessary SQM packages.

The SQM package has a much more easily understood config file than the older QoS one without the weird choices (prioritising AOL Instant Messenger? Does it even still exist?).

/etc/config/sqm:

#
# Set your 'download' and 'upload' values
# to around 90% of your connection speed.
#
# The 'overhead' value should be set to '8'
# to account for the additional 8 bytes that
# PPPoE introduces.
#
config queue 'eth1'
	option qdisc 'fq_codel'
	option qdisc_advanced '0'
	option interface 'pppoe-wan'
	option script 'simple_pppoe.qos'
	option enabled '1'
	option linklayer 'ethernet'
	option download '90%-OF-DOWNLOAD-SPEED'
	option upload '90%-OF-UPLOAD-SPEED'
	option overhead '8'

I’ve found fq_codel to be amazingly good at keeping a connection responsive and reducing bufferbloat. I would most definitely advise everyone to use it.

Even when my connection is getting hammered my latency only increases an additional 3ms (as opposed to around 40ms when fq_codel isn’t enabled).

Ad blocking via DNS

I use a list of common ad server hostnames from pgl.yoyo.org. This list is pre-formatted for dnsmasq and, rather than using the traditional method of responding with a fake IP, responds to ad domains with an NX Domain (non-existent domain) so that the browser never even attempts a connection to pull the ad.

On the OpenWrt router run:

wget -O /etc/dnsmasq.conf.ads.yoyo "http://pgl.yoyo.org/as/serverlist.php?hostformat=dnsmasq-server&showintro=0&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D=&mimetype=plaintext"

echo "conf-file=/etc/dnsmasq.conf.ads.yoyo" >> /etc/dnsmasq.conf

echo "/etc/dnsmasq.conf.ads.yoyo" >> /etc/sysupgrade.conf

This will:

OpenVPN server

Install the openvpn-openssl, luci-app-openvpn, and openvpn-easy-rsa packages. After installation make sure that the /etc/openvpn and /etc/easy-rsa directories are preserved when doing configuration backups by running the following on the router:

echo "/etc/openvpn/" >> /etc/sysupgrade.conf
echo "/etc/easy-rsa/" >> /etc/sysupgrade.conf

A Certificate Authority (CA) now needs to be created. First find and modify some values in /etc/easy-rsa/vars to increase key strength and ease the repetitive nature of certificate creation.

/etc/easy-rsa/vars:

# Set your key size to 2048.

export KEY_SIZE=2048

# Modify these values to be relevant
# to your situation

export KEY_COUNTRY="US"
export KEY_PROVINCE="CA"
export KEY_CITY="Beverly Hills"
export KEY_ORG="West Beverly Hills High"
export KEY_EMAIL="90210@example.org"
export KEY_OU="VPN"

To build your Certificate Authority, on the router, run:

cd /etc/easy-rsa
source vars
clean-all # Only run this the first time as it will wipe all previous certificates away!
build-ca

and follow the directions. Once the CA has been created a certificate for the OpenVPN server needs to be created and signed by the CA. Run the following on the router:

build-key-server vpn0

Follow the instructions, but when asked to set a password and optional company name just press return. When asked to sign and commit the certificate do so.

Now copy the server key and certificate as well as the CA certificate to /etc/openvpn/:

cp /etc/easy-rsa/keys/ca.crt /etc/openvpn/
cp /etc/easy-rsa/keys/vpn0.crt /etc/openvpn/
cp /etc/easy-rsa/keys/vpn0.key /etc/openvpn/

A file containing Diffie-Hellman parameters will also need to be created. This can be done on the router but is very CPU-intensive and could take upwards of an hour to complete so i would recommend generating the file on a PC.

If you want to generate the file on Linux, *BSD or OS X (and maybe a Windows 10 machine with the new Linux subsystem?) you can run the following:

openssl dhparam -out dh2048.pem 2048

Then simply copy the dh2048.pem file to the /etc/openvpn directory on your router using SCP.

If you do want to build the file on your router you can run the following on your router:

cd /etc/easy-rsa
build-dh
cp dh2048.pem /etc/openvpn/

But don’t say i didn’t warn you!

Now to configure the OpenVPN server itself. If you don’t have IPv6 (or do, but don’t have a spare /64 you can dedicate to VPN clients) remove the IPv6-specific lines from the config.

/etc/config/openvpn:

config openvpn 'vpn0'
	option enabled '1'
	option dev 'tun0'
	option port '1194'
	option proto 'udp'
	option comp_lzo 'adaptive'
	option tun_ipv6 '1'
	option status '/var/log/openvpn_status.log'
	option log '/tmp/openvpn.log'
	option verb '3'
	option mute '5'
	option keepalive '10 120'
	option persist_key '1'
	option persist_tun '1'
	option user 'nobody'
	option group 'nogroup'
	option ca '/etc/openvpn/ca.crt'
	option cert '/etc/openvpn/vpn0.crt'
	option key '/etc/openvpn/vpn0.key'
	option dh '/etc/openvpn/dh2048.pem'
	option mode 'server'
	option tls_server '1'
	option server '172.18.6.0 255.255.255.0' # The private subnet for VPN clients
	option server_ipv6 'fd1c:515e:9999:1111::/64' # Use one of your GLOBALLY ROUTABLE IPv6 /64s here
	option topology 'subnet'
	option route_gateway 'dhcp'
	option client_to_client '1'
	option passtos '1'
	list push 'comp-lzo adaptive'
	list push 'persist-key'
	list push 'persist-tun'
	list push 'user nobody'
	list push 'group nogroup'
	list push 'topology subnet'
	list push 'route-gateway dhcp'
	list push 'redirect-gateway def1'
	list push 'route 172.18.0.0 255.255.255.0' # Tell clients route to wired LAN is via VPN
	list push 'route 172.18.2.0 255.255.255.0' # Tell clients route to 2.4GHz Private Wifi is via VPN
	list push 'route 172.18.3.0 255.255.255.0' # Tell clients route to 5GHz Private Wifi is via VPN
	list push 'route-ipv6 2000::/3'
	list push 'dhcp-option DNS 172.18.0.1'
	list push 'dhcp-option DOMAIN vpn.lan.example.org'

The OpenVPN server is now configured, but you still need to create and sign client certificates if you want anyone to be able to connect. On the router run:

cd /etc/easy-rsa
build-key-pkcs12 user1

repeating the second line but modifying user1 for each new client certificate. When asked leave the company name and password blank. Sign and commit the certificates.

In /etc/easy-rsa/keys create a new file:

/etc/easy-rsa/keys/client.ovpn:

#specify TUN vs. TAP (if you're not sure, you want TUN)
dev tun

#specify protocol to use (default is UDP)
proto udp

#Certificate information
ca   ca.crt
cert client.crt
key  client.key

#client settings
client
remote-cert-tls server
remote vpn.example.org 1194

For each new user you should copy this file and modify the cert and key values to match the user then bundle it up with the user’s cert and key along with the ca.crt file and provide it to the user so they can import it into their OpenVPN client.

For instance: If you have just created and signed a certificate for user1 do the following on the router:

cd /etc/easy-rsa/keys
cp client.ovpn user1.ovpn

Then modify user1.ovpn:

#Certificate information
ca   ca.crt
cert user1.crt
key  user1.key

Bundle all the necessary files together:

tar -cf user1.tar ca.crt user1.*

Download the user1.tar file over SCP and give it to the client. They can then extract and import the necessary files into their OpenVPN client.

Finishing up

In OpenWrt’s Web GUI check under System/Startup and ensure that all the packages you installed (just avahi-daemon, igmpproxy, sqm, and openvpn in this post) are set to “Enabled”.

Now reboot the router for all the new settings to come into effect.

Secondary router/access point

My secondary router (which will become a mostly dumb access point) is a TP-Link WDR3600. It’s a simultaneous dual-band router that is much weaker than the WDR4900. This won’t be a problem though as the primary router will be doing the heavy lifting.

The WAN port of this router is connected to a Zyxel GS1910-24 smart switch, which has been configured to allow the relevant VLAN-tagged traffic through a cable that goes around the outside of the house and plugs into the third LAN port of the WDR4900.

On to the config…

Networking

/etc/config/network:

config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

# Remove the 'wan' and 'wan6'
# interfaces as we're basically
# combining the WAN and LAN into one.
#
# Modify the new combined LAN interface
# so that the secondary router gets its
# own IP from DHCP that can be connected to
# directly for managing the router.
#
# Add a 'lan6' interface so the secondary
# router also gets its own IPv6 address.

config interface 'lan'
	option ifname 'eth0.1'
	option force_link '1'
	option proto 'dhcp'

config interface 'lan6'
	option ifname '@lan'
	option proto 'dhcpv6'
	option reqprefix 'no'

# Modify the default VLAN so that
# VLAN 1 encompasses both LAN and
# WAN ports.
#
# Remove VLAN 2 (the old WAN VLAN).

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

config switch_vlan
	option device 'switch0'
	option vlan '1'
	option ports '0t 1 2 3 4 5'

# My additional VLANs.  Traffic for these
# VLANs will be tagged and assigned to
# the old WAN port.

config switch_vlan
	option device 'switch0'
	option vlan '10'
	option ports '0t 1t'

config switch_vlan
	option device 'switch0'
	option vlan '15'
	option ports '0t 1t'

config switch_vlan
	option device 'switch0'
	option vlan '20'
	option ports '0t 1t'

config switch_vlan
	option device 'switch0'
	option vlan '25'
	option ports '0t 1t'

# Bridged Wifi/VLAN interfaces.
#
# The "auto" option ensures that
# these interfaces come up on boot.

config interface 'wifi_priv'
	option proto 'none'
	option ifname 'eth0.10'
	option type 'bridge'
	option auto '1'

config interface 'wifi5_priv'
	option proto 'none'
	option ifname 'eth0.20'
	option type 'bridge'
	option auto '1'

config interface 'wifi_guest'
	option proto 'none'
	option ifname 'eth0.15'
	option type 'bridge'
	option auto '1'

config interface 'wifi5_guest'
	option proto 'none'
	option ifname 'eth0.25'
	option type 'bridge'
	option auto '1'

Wifi

/etc/config/wireless:

# Standard OpenWrt Wireless hardware
# config for the radios.

# ***
# Update: 2015-04-16
#
# Dropped txpower from '20' to '15' for
# both radios.  This shrinks the Wifi range
# allowing stupid client devices to drop
# their connection faster and lock on to
# another access point.
# ***
#
# Provided you have positioned the access
# points correctly you likely won't notice
# a loss in connectivity (i can run a 'ping'
# while switching and see only a single
# missed packet).

config wifi-device 'radio0'
	option type 'mac80211'
	option channel '11'
	option hwmode '11g'
	option path 'platform/ar934x_wmac'
	option htmode 'HT20'
	option country 'GB'
	option txpower '15'

config wifi-device 'radio1'
	option type 'mac80211'
	option hwmode '11a'
	option path 'pci0000:00/0000:00:00.0'
	option txpower '15'
	option htmode 'HT40'
	option country 'GB'
	option channel '44'

# The config for each SSID.  Make sure
# each SSID is attached to the correct
# VLAN as defined in /etc/config/network
# and Guest Wifi has the 'isolate' option.

config wifi-iface
	option device 'radio0'
	option mode 'ap'
	option key 'MY PRIVATE NETWORK PASSPHRASE'
	option network 'wifi_priv'
	option ssid 'Wifi (Private)'
	option encryption 'psk2+ccmp'

config wifi-iface
	option device 'radio1'
	option mode 'ap'
	option key 'MY PRIVATE NETWORK PASSPHRASE'
	option network 'wifi5_priv'
	option ssid 'Wifi 5GHz (Private)'
	option encryption 'psk2+ccmp'

config wifi-iface
	option device 'radio0'
	option mode 'ap'
	option key 'MY GUEST NETWORK PASSPHRASE'
	option network 'wifi_guest'
	option ssid 'Wifi (Guest)'
	option encryption 'psk2+ccmp'
	option isolate '1'

config wifi-iface
	option device 'radio1'
	option mode 'ap'
	option key 'MY GUEST NETWORK PASSPHRASE'
	option network 'wifi5_guest'
	option ssid 'Wifi 5GHz (Guest)'
	option encryption 'psk2+ccmp'
	option isolate '1'

Finishing up

That’s it for editing config files on the secondary router/AP.

DHCP, ODCHPD and the firewall will need to be disabled to make this router a mostly dumb access point. This can be done by running

/etc/init.d/dnsmasq disable
/etc/init.d/odhcpd disable
/etc/init.d/firewall disable

Rebooting the router will cause the new settings to come into effect.

Hopefully someone will find this information useful should they wish to tweak OpenWrt themselves. I just hope i didn’t forget something!

Huge thanks to the developers of OpenWrt for making an enterprise-class router distribution with great power and flexibility, and to the CeroWrt Project for all their hard work in eliminating bufferbloat and bringing other advanced technologies to consumer routers (can’t wait to see what you do with Wifi!).

Ad blocking using DNS and Privoxy (with Squid for caching)

Chaining Squid and Privoxy for caching and ad-blocking combined with DNS-based ad-blocking using dnsmasq
Ad blocking dnsmasq Privoxy Squid