Cryptsus Blog rss-feed  |  We craft cyber security solutions.

OpenWrt Wireless Access Point Bridge
with 802.1X PEAP

By: Jeroen van Kessel  |  June 26th, 2019 | 10 min read

Throughout the years it has been known that many SOHO wireless routers are prone to security vulnerabilities. Many stock router firmware are consistently plagued by exploits due to bad quality control and are no longer being updated after the routers reach their end-of-life (EOL). Alternative router firmware such as DD-WRT and OpenWrt are typically more secure. We picked OpenWrt for this project since DD-WRT is updated less frequently than OpenWrt plus OpenWrt is more mainline in terms of its Linux kernel.

This blog post will eleborate on how you can leverage your wireless router to connect to any wireless access point into your home network. We will use a TP-Link TL-WR841ND v7.1 and a Yagi RP-SMA 2.4 GHz High Gain 16 DBi antenna. Note that the D in TP-Link TL-WR841ND standsfor Detachable antenna(s). You are only able to attach external high gain directional antennas to the D-models.

Technical overview

Clients can connect over RJ45 or WPA2 to the bridged TP-link OpenWrt router. The OpenWrt router authenticates with 802.1X to an open AP such as eduroam or Ziggo HotSpots. NAT will occur on the OpenWrt router. The eduroam or Ziggo 8021.X authenticator server will eventually verify and approve or deny authentication based on username, password and certificate. Figure 1 shows this process:

Figure 1: OpenWrt 802.1X authentication overview

Flashing the firmware

Lets download the latest version of OpenWrt so we can replace the stock firmware on the router. I downloaded the firmware binary via the latest official OpenWRT repository which is sorted by chipset platform. The TP-Link WR841ND relies on the Atheros AR7241 chipset. Pick the tiny verion of OpenWrt due to its 4MB flash size memory limitations.

When logged in on the web-interface of the stock firmware, upload the openwrt-18.06.2-ar71xx-tiny-tl-wr841-v7-squashfs-factory.bin file to the router. It will reboot after flashing and OpenWrt should be installed and accessable on the same IP-adres.

We login as root without a password. Change your password because you do not want others to login unauthorized.

Certificates rely on the correct time/ date information to prevent clock related errors. Set the time to the correct local timezone: System -> System -> Timezone

OpenWrt supports WEP, WPA and WPA2 but not 802.1X authentication out-of-the-box. Therefore we will install the 802.1X supplicant, which is the client side authenticator package. We first need to remove the wpad-mini package before installing the 802.1X supplicant. Go to: System -> Software -> Installed packages: wpad-mini -> Remove.

Next go to System -> Software -> Update packages -> Filter: 802.1X -> Find pacakage -> wpa-supplicant -> Install -> Ok:

wpa-supplicant-mini	2018-05-21-62566bc2-5	163091	WPA Supplicant (minimal version)

Because of limited memory space on the router we get the following error which withholds us from installing the package:

 * verify_pkg_installable: Only have 76kb available on filesystem /overlay, pkg wpa-supplicant-mini needs 159
 * opkg_install_cmd: Cannot install package wpa-supplicant-mini.

Because the router has only 4MB flash size available, we need to remove packages which are not necessary for this 802.1X bridged setup. Unfortunately removing packages from the web-portal or by CLI does not do the job. We need to recompile the firmware binary from source with a minimal set of packages.

I am using the latest version of Ubuntu 18.04 LTS for this project. You can use VirtualBox to spawn a box if you are not running a Linux distro on your bare-metal.

$ lsb_release -d
Description:	Ubuntu 18.04.2 LTS

We download the tiny version of the OpenWrt Imagebuilder of ar71xx chipsets. Download the compressed Imagebuilder binaries:

$ wget

Verify the hash for integrity and CRC reasons:

$ echo "ed0d6d4ea6c1147c8145fd33a4225ad60c1165a67c09ab7d7dba2346caaa4076" openwrt-imagebuilder-18.06.2-ar71xx-tiny.Linux-x86_64.tar.xz |
sha256sum -c -
openwrt-imagebuilder-18.06.2-ar71xx-tiny.Linux-x86_64.tar.xz: OK

Extract the imagebuilder tar:

$ tar -xvf openwrt-imagebuilder-18.06.2-ar71xx-tiny.Linux-x86_64.tar.xz
$ cd openwrt-imagebuilder-18.06.1-ar71xx-generic.Linux-x86_64

lets see how we compile this firmware:

$ make info
Current Target: "ar71xx (Devices with small flash)"
Default Packages: base-files libc libgcc busybox dropbear mtd uci opkg netifd fstools uclient-fetch logd kmod-gpio-button-hotplug
swconfig kmod-ath9k wpad-mini uboot-envtoolsdnsmasq iptables ip6tables ppp ppp-mod-pppoe firewall odhcpd-ipv6only odhcp6c

    TP-LINK TL-WR841N/ND v1.5
    TP-LINK TL-WR841N/ND v10
    TP-LINK TL-WR841N/ND v11
    TP-LINK TL-WR841N/ND v12
    TP-LINK TL-WR841N/ND v3
    TP-LINK TL-WR841N/ND v5
    TP-LINK TL-WR841N/ND v7
    TP-LINK TL-WR841N/ND v8
    TP-LINK TL-WR841N/ND v9

Lets build the firmware with the luci web-interface, wpad package which is the 802.1X client supplicant package, but without the wpad-mini package:

$ make image PROFILE=tl-wr841-v7 PACKAGES="luci wpad -wpad-mini"

[mktplinkfw] *** error: images are too big by 9060 bytes
cp: cannot stat '/home/krabelize/Desktop/openwrt-imagebuilder-18.06.2-ar71xx-tiny.Linux-x86_64/build_dir/target-mips_24kc_musl/
linux-ar71xx_tiny/tmp/openwrt-18.06.2-ar71xx-tiny-tl-wr841-v7-squashfs-factory.bin': No such file or directory

The firmware binary will still be 9060 bytes too big for the 4MiB router. Therefore we get rid of more unnecessary pacakges:

$ make image PROFILE=tl-wr841-v7 PACKAGES="luci wpad -wpad-mini -ppp -ppp-mod-pppoe -kmod-ppp -kmod-pppoe -kmod-pppox -kmod-ipv6 -6relayd
 -ip6tables -odhcp6c -odhcpd-ipv6only"

2292370 bytes (2.3 MB, 2.2 MiB) copied, 0.0234007 s, 98.0 MB/s
[mktplinkfw] rootfs offset aligned to 0x1365064
[mktplinkfw] firmware file "/home/krabelize/Desktop/openwrt-imagebuilder-18.06.2-ar71xx-tiny.Linux-x86_64/build_dir/target-mips_24kc_musl/
linux-ar71xx_tiny/tmp/" completed
4477+1 records in
4477+1 records out
2292370 bytes (2.3 MB, 2.2 MiB) copied, 0.0284081 s, 80.7 MB/s
[mktplinkfw] rootfs offset aligned to 0x1365064
[mktplinkfw] firmware file "/home/krabelize/Desktop/openwrt-imagebuilder-18.06.2-ar71xx-tiny.Linux-x86_64/build_dir/target-mips_24kc_musl/
linux-ar71xx_tiny/tmp/" completed
padding image to 00230000
padding image to 00230000
padding image to 00240000
18+1 records in
19+0 records out
2490368 bytes (2.5 MB, 2.4 MiB) copied, 0.00946213 s, 263 MB/s

Our firmware binary got created with a size of 3840KB :)

$ ls -lsa build_dir/target-mips_24kc_musl/linux-ar71xx_tiny/tmp/openwrt-18.06.2-ar71xx-tiny-tl-wr841-v7-squashfs-factory.bin
3840 -rw-r--r-- 1 root root 3932160 jun 22 20:48 build_dir/target-mips_24kc_musl/linux-ar71xx_tiny/tmp/

Let's copy this binary to the router:

$ scp build_dir/target-mips_24kc_musl/linux-ar71xx_tiny/tmp/openwrt-18.06.2-ar71xx-tiny-tl-wr841-v7-squashfs-factory.bin

Next up is flashing the firmware:

$ ssh root@
$ cd /tmp && mtd -r write openwrt-18.06.2-ar71xx-tiny-tl-wr841-v7-squashfs-factory.bin firmware

Configuring 802.1X authentication

We will choose Ziggo Hotspots for 802.1X authentication. Ziggo HotSpots requires the installation of a ca.pem. The Eduroam network does not require certificate based authentication anymore.

mv 'WifiSpots certificaat Windows Phone Ziggo.pem' ca.pam

$ cat ca.pam

Let's configure 802.1X via the webinterface. Go to and login.

Go to: Network -> Wireless -> radio0 -> Scan -> 84% Ziggo -> Join network -> Submit

Now that we associated radio0 with the SSID of the public Hotspot of Ziggo, lets configure the 802.1X authentication: Wireless security:

Encryption: WPA2-EAP
Cipher: Force CCMP (AES)
EAP-Method: PEAP
CA-certificate: ca.pem
Authentication: EAP-MSCHAPv2
Identity: [Ziggo username]
Anonymous Identity: [empty]
Password [Ziggo password]

For the eduroam network:

Encryption: WPA-EAP
EAP-Method: PEAP
CA-certificate: [none]
Authentication: EAP-MSCHAPv2
Identity: [eduroam username]
Anonymous Identity: [empty]
Password [eduroam password]

Save and Apply

Let's see if we can route traffic over the Ziggo public hotspot gateway:


Pinging [] with 32 bytes of data:
Reply from bytes=32 time=19ms TTL=245
Reply from bytes=32 time=19ms TTL=245
Reply from bytes=32 time=21ms TTL=245
Reply from bytes=32 time=24ms TTL=245

Ping statistics for
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 19ms, Maximum = 24ms, Average = 20ms

logread shows the DHCP handshake between the WPA2 802.1X supplicant and the 802.1X authentication server:

$ logread
Mon Jun 24 19:30:34 2019 daemon.notice netifd: wwan (1467): udhcpc: sending discover
Mon Jun 24 19:30:34 2019 daemon.notice netifd: wwan (1467): udhcpc: sending select for [wan routable IP]
Mon Jun 24 19:30:34 2019 daemon.notice netifd: wwan (1467): udhcpc: lease of [wan routable IP] obtained, lease time 7200
Mon Jun 24 19:30:34 2019 daemon.notice netifd: Interface 'wwan' is now up
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: reading /tmp/
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using local addresses only for domain test
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using local addresses only for domain onion
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using local addresses only for domain localhost
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using local addresses only for domain local
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using local addresses only for domain invalid
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using local addresses only for domain bind
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using local addresses only for domain lan
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using nameserver [ip_dns1]#53
Mon Jun 24 19:30:34 2019 dnsmasq[1335]: using nameserver [ip_dns2]#53

Your OpenWrt config should look something like this for Ziggo HotSpots:

$ vi /etc/config/wireless
config wifi-device 'radio0'
        option type 'mac80211'
        option hwmode '11g'
        option path 'pci0000:00/0000:00:00.0'
        option htmode 'HT20'
        option channel '1'
        option country 'US'
        option legacy_rates '1'
        option disabled '0'

config wifi-iface 'default_radio0'
        option device 'radio0'
        option network 'lan'
        option mode 'ap'
        option ssid 'FBI Surveillance Van'
        option encryption 'psk2'
        option key 'P@ssw0rd'

config wifi-iface
        option network 'wwan'
        option ssid 'Ziggo'
        option device 'radio0'
        option mode 'sta'
        option bssid 'DE:AD:BE:EF:01:01'
        option encryption 'wpa2+ccmp'
        option eap_type 'peap'
        option ca_cert '/etc/luci-uploads/cbid.wireless.cfg033579.ca_cert'
        option auth 'EAP-MSCHAPV2'
        option identity 'y0urID_h3r3'
        option password 'p@ssw0rd'
        option disabled '0'

Don't forget to set a strong root passphrase and configure SSH public key authentication. Furthermore, The SSID of the bridged AP is unprotected. Set a strong WPA2-PSK passphrase on radio1.

Dynamic MAC address

This script changes the MAC address on OpenWrt on any specified (v)NIC interface. Change the OUI of the MAC address to a legitmate NIC vendor for RFC and IEEE compliancy. The 802.1X authentication server might have a validator in place to check spoofed MAC addresses against the above IEEE database. We are not responsible for any legal violations. Check with your ISP if changing your MAC address on a dynamic basis is allowed.

Discussion and questions