Philips Hue 2.1 – Enabling WIFI

First of all this is my first blog post. The idea behind this was that information regarding rooting the 2.1 bridge from Philips is scarce across multiple blogs, githubs, youtube uploads and reddit topics. The full solution was not yet documented.

I will mention all my sources of information at the end of article.

So let’s begin with the bridge disassembly.

 

 

You will find two hex screws at the bottom of the bridge. Just pop off those rubber parts with a flat screwdriver and you will see them.

 

 

Get yourself a plastic card and pop off the back cover.

 

 

Remove the board from inside the case and inspect it.

 

 

You will need to solder a 6 header pin into the board. If you don’t have a soldering station please borrow one. The soldering operation takes 1 minute and the header can be left soldered into the board. The case fits perfectly with the header present.

The header goes into the J6 spot on the board.

 

 

Get yourself a FT232RL UART. I wasted 1 full day trying to figure out why it didn’t work with my CH340G.

With CH340G, in the first stage of the u-boot I had only artifacts on screen and the bridge got stuck in that sequence if the UART was plugged into the computer USB. I suspect a power drain. Here’s how it looked like:

 


Just use a FT232RL and you won’t have any issues. The UART needs to be set up for 3.3V usage. To make sure of this, measure between GND and RX, plus between GND and TX. You should see approx 3.3V.

On the Hue Bridge the mapping of the J6 header to UART and its pin-out is the following(starting from the top – which has a small triangle(GND)) :

Hue Bridge PIN OrderHue Bridge PIN MappingUSB to TTL Mapping
1GNDGND
2NOT USED
3NOT USED
4RXTX
5TXRX
6NOT USED

 

OPTIONAL: You could also measure between GND and TX(PIN 5) on the bridge and you will confirm the pin-out from above by seeing some voltage on your multi-meter.

Connect the UART to a computer, set the speed to 115200 and power on the Hue Bridge.

The first stage of the boot process looks like this:

 

 

After a while the boot sequence will finish and the logon prompt will be shown(if it’s not, hit Enter once or twice):

 

 

If the Enter key is recognized then TX from UART works and obiviously RX as well since you’re seeing messages on screen.

Now prepare a wire, or a paper clip. Remove the power from the Hue Bridge.

You will have to power on the bridge and after 2-3 seconds(that’s the amount of time the first stage of the u-boot takes to move to the second stage of the boot process – the FLASH chip) connect the GND of the hue board to the to the tip of solder behind SEU11.

Take a look at the options I’ve given below. Pick either one.

 

 

If you’re going to be successful and I don’t see a reason not to be, you will see this:

 

 

** Device 0 not available

 

simply means that the FLASH was bypassed and now we have access to the u-boot.

Run the following commands:

 

setenv bootdelay 3
saveenv
reset

 

This will allow you 3 seconds to enter the u-boot CLI without having to connect the wire which blocks the read of the flash memory.

We will now have to change the root account’s hash. But first make a local backup of the existing one. Someone mentioned that having the root password changed gave him some errors to the Hue Cloud services. I can’t confirm this but it doesn’t matter since we’ll leverage public key authentication with SSH and restore the hash later.

Run the command to print the hash then save it to a text file(use Notepad/Notepad++):

 

printenv security

 

Run the command to change the hash, thus changing the root password to “toor”:

 

setenv security '$5$wbgtEC1iF$ugIfQUoE7SNg4mplDI/7xdfLC7jXoMAkupeMsm10hY9'
saveenv
reset

 

Login to the Hue Bridge with “root/toor”.

Use puttygen to generate yourself an RSA 2048 key. Click on “Save private key” and then copy the string from the “Public key for pasting into OpenSSH authorized_keys file:“.

Create a file inside /root, on the bridge, and paste the public key contents. Run the following command to import the key:

 

ssh-factory-key -r key

 

where key is the file which contains the public key.

dropbear (the ssh daemon) will configure itself with the public key and the firewall daemon will receive the request to open up TCP:22. Wonderful!

Assuming you have the ethernet cable plugged in try and ssh to the Hue Bridge by using public key authentication. If you’re successful, then reboot the bridge and cancel the autoboot process once more.

Restore the old root hash which you’ve backed up previously and reset the unit.

As of now you can remove the UART device and assemble the unit back together.

You have accomplished the root the device and the enablement of SSH.

The Hue Bridge runs an OpenWRT version with some custom additions from Philips:

 

root@Philips-Hue:~# cat /etc/*release
DISTRIB_ID='OpenWrt'
DISTRIB_RELEASE='Chaos Calmer'
DISTRIB_REVISION='r47070'
DISTRIB_CODENAME='chaos_calmer'
DISTRIB_TARGET='ar71xx/generic'
DISTRIB_DESCRIPTION='OpenWrt Chaos Calmer 15.05.1'
DISTRIB_TAINTS='no-all busybox override'

 

The packages for the 15.05.1 distribution can be found over here.

The Hue Bridge supports only WEP authentication and assuming you and nobody else doesn’t use that old authentication scheme we’ll need to enable WPA2 support.

Unfortunatelly in this realease (1801260942 – returned by cat /etc/swversion) they removed the opkg tool – openwrt’s package manager.

Download “wpad-mini_2015-03-25-1_ar71xx.ipk” and extract its contents on your computer.

Extract the wpad binary from the ipk archive (I’ve used 7zip) and copy it to /usr/sbin on the bridge (you can use WinSCP for example).

Make sure it has execute permissions:

 

chmod +x /usr/sbin/wpad

 

and create the following symlink:

 

ln -s /usr/sbin/wpad /usr/sbin/wpa_supplicant

 

If we run wpa_supplicant we’ll receive an error that it requires a missing library:

 

/lib/libm.so.0

 

I said earlier that the OpenWRT release has some customization and it’s not the original one. For instance libc is 1.0.14 and the standard build has the 0.9.33.2-1.

Bummer…

The good thing is that it seems wpa_supplicant is compatible with 1.0.14 as well. Let’s create the following symlinks:

 

ln -s /lib/libm-1.0.14.so /lib/libm.so.0
ln -s /lib/libuClibc-1.0.14.so  /lib/libc.so.0

 

Try and execute wpa_supplicant from the CLI once more. It should work and display the help menu.

Make a backup of the following configuration files:

 

cp /etc/config/firewall /etc/config/firewall.old
cp /etc/config/wireless /etc/config/wireless.old
cp /etc/config/hk_mdns /etc/config/hk_mdns.old

 

Fortunatelly the vim text editor is present. Let’s activate the wireless module by adding the following to the /etc/config/wireless file:

 

config wifi-device 'radio0'
option type 'mac80211'
option channel '11'
option hwmode '11ng'
option path 'platform/qca953x_wmac'
list ht_capab 'LDPC'
list ht_capab 'SHORT-GI-20'
list ht_capab 'SHORT-GI-40'
list ht_capab 'TX-STBC'
list ht_capab 'RX-STBC1'
list ht_capab 'DSSS_CCK-40'
option htmode 'HT20'
option disabled '0'

config wifi-iface
option device 'radio0'
option network 'wlan'
option encryption 'psk2'
option key 'REPLACE_ME'
option mode 'sta'
option ssid 'REPLACE_ME'

 

Put your own SSID and KEY values in the file.

Run the following commands:

 

uci commit wireless
wifi

 

To verify the connection status execute:

 

root@Philips-Hue:/etc/config# iw wlan0 link
Connected to 10:fe:ed:f3:e7:08 (on wlan0)
SSID: XXXXXX
freq: 2452
RX: 3837187 bytes (36354 packets)
TX: 843981 bytes (2859 packets)
signal: -56 dBm
tx bitrate: 135.0 MBit/s MCS 6 40MHz short GI

bss flags: short-preamble short-slot-time
dtim period: 1
beacon int: 100

 

Get an IP address with DHCP:

 

udhcpc -i wlan0

 

To make it persistent edit /etc/config/network and add at the end:

 

config interface 'wlan'

option ifname 'wlan0'
option proto 'dhcp'
option hostname 'Philips-Hue'

 

Also replace eth1 with wlan0 inside /etc/config/hk_mdns:

 

sed -i "s/eth1/wlan0/ /etc/config/hk_mdns

 

Edit /etc/config/firewall and look for the section “config zone ‘lan’“. Add a new line like below, to include wlan0 to the ‘lan‘ network:

 

config zone 'lan'

option name 'lan'
list network 'lan'
list network 'wlan'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
option masq '1'
option mtu_fix '1'

 

Again, inside /etc/config/network, make sure the eth1 will have its option proto set to ‘static’ and that its IP address configured to one from a private network different from the one you have on your WIFI network.

Reboot the bridge and remove the Ethernet cable.

You will now be able to connect to the WIFI interface via SSH but the Hue services won’t be running correctly.

 

 

The following network sockets exist right now:

 

 

If we connect the Ethernet cable the errors will dissapear and new sockets will be created(if the error persists reboot the bridge but keep the Ethernet cable connected):

 

 

I have checked every ASCII file on the system (or at least I think I did) and could not find any reference of eth1 anywhere.

I came to the conclusion that eth1 is hardcoded somewhere in the binaries.

Someone mentioned that editing /usr/sbin/ipbridge in hex and replacing the eth1 string with wlan0 will make things work. Unfortunately it did not work for me.

One solution I thought of, was to create an udev rule which would have renamed eth1 to wlan0 but udev is not available on OpenWRT. We have hotplug2 which didn’t help me in this situation.

So if the services expect eth1 to be up, but don’t care if the interface can reach the Internet or not let’s give them that 🙂

Take a RJ45 jack and create an Ethernet loopback. Pin 1 should be connected to Pin 3 and Pin 2 should be connected to Pin 6.

 

 

Plug that into the Ethernet port and you will be just fine:

 

eth1 Link encap:Ethernet HWaddr 00:17:88:4E:24:38
inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fddf:d971:4229::1/60 Scope:Global
inet6 addr: fe80::217:88ff:fe4e:2438/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:916 (916.0 B) TX bytes:916 (916.0 B)
Interrupt:5

 

See how the RX bytes = TX bytes? That’s because of the loopback.

Now the Hue Bridge can be used on WIFI only 🙂

 

Conclusions:

This has been a good two days project for me. I’m amazed by how people actually hacked this.

At first pepe2k from OpenWRT forum figured out that we could remove a resistor which caused the u-boot sequence to drop us to the prompt. He also analyzed a dump of the the firmware, discovering that the root password is taken from the u-boot env variables.

After that, Colin O’Flynn discovered that we can bypass the access of the flash by using a wire between GND and the data out (DO) PIN of the chip.

 

References:

19 comments on Philips Hue 2.1 – Enabling WIFI

  1. This doesnt work for me unfortunately. When I try to execute wpa_supplicant, I get the error:

    root@Philips-hue:/usr/sbin# wpa_supplicant
    -ash: wpa_supplicant/: not found

    But with ls /usr/sbin I can see the wpa_supplicant file :/

    1. If you’re inside /usr/sbin execute like this:
      root@Philips-hue:/usr/sbin# ./wpa_supplicant

      Otherwise use the full path when executing files with the executable permission set:
      root@Philips-hue:/usr/sbin# /usr/sbin/wpa_supplicant

  2. Its working :). But I have a very small problem with the iOS App iConnectHue. This app allows multiple Bridges at the same time (very useful). But now the App don’t recognize my bridge. First it find it but say I have a problem and after a while the bridge is offline for the app. I think the app find die bridge on my WiFi with IP 192.168.179.19 and then get the info from the bridge (LAN settings) and this IP differs 192.169.1.2 (According your instructions that eth0 IP has to be another IP outside my home IP range?).

    I have not problems with the Philips Hue App.

    1. Can you define, manually, the bridge IP address in iconnect app? I don’t think this is related to the ip address of the LAN, but yes, you need to set something outside your home ip range manually.

      1. Yes this is possible but not working. I set the IP to 192.168.178.19 and the App find the bridge. But after few seconds the app say “connection problems”. I think because the app get the info from the bridge that the IP is 192.168.1.2.

          1. With “logread -f” I see the incomming connection:

            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:24 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:29 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:29 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [http_server.c,368,State Ready …]
            Thu Sep 20 09:19:33 2018 daemon.notice ipbridge: [webserver.c,234,Accepting connections]

            But I see in my App that my manually entered IP: 192.168.178.19 will automatically changed to 192.168.1.2 after successful connection. And then the app seems to try to reconnect on the 1.2 IP … I looked closer to the official Philips Hue App and discovered that the app opens a remote connection instead of a local. On my other (not rooted) bridge the Hue app is local connected…..

  3. @Andrei BANARU
    I activated the WiFi for my 2. bridge and its working fine, too. A very very BIG THANK YOU for your effort and time!!!!!!!!!!

  4. The Wifi mod works even after few weeks very good. But the problems that the bridge is only available trough the remote access (online) is still there. The Hue App shows the connection status „remote access“ and after few seconds or minutes its connected via LAN. And then somewhile its again connected via online cloud.

    Do you have an idea why this happens? I have only limited knowledge in Linux …

  5. Hi

    Any idea what do do if I lost the original root user password hash? 😀

    Long story short, I copied the hash into a notepad but forgot to save it, put my pc to sleep and the next day I woke it up I had an unfortunate blue screen on Winblows…

    Without restoring the root hash to the original I am only able to control the HUE bridge locally on my LAN and not over the WAN as the bridge uses that hash to authenticate to the cloud API…

    Thanks,
    Pete

      1. Thanks Andrei.

        I did think about that, but then I wasn’t sure if it would cause any conflicts. 🙂

        Any1 willing to share theirs? 😀

Leave a Reply

Your email address will not be published. Required fields are marked *