brangerbriz / wifi-data-safari

WiFi Data Safari Workshop
https://brangerbriz.github.io/wifi-data-safari
73 stars 11 forks source link

Questions: Recommended WiFi adapter(s) & iptables infinite loop #19

Open trinitronx opened 6 years ago

trinitronx commented 6 years ago

Hello,

It was great to meet you guys yesterday (04/28/2018) at "The Collective" for the WiFi Data Safari workshop! I was browsing some of the other projects you guys were working on such as the MIDI neural net & Magenta (nSynth), and the BitCoin art display. Really cool stuff, that's right along the same areas of interest I've been thinking about getting into lately. Anyway, I just wanted first to mention those projects look really interesting too, especially the music related ones!

Today, I've had some time to test out setting up this wifi-data-safari project using the docker image. I was following the Art Installation Guide here. I got pretty close eventually and found a configuration issue and solution for getting hostapd working with my particular USB WiFi dongle. I'm using a very old Hawking HWUG1, which does not support MIMO or 802.11n, so hostapd was not starting initially. In case you're interested in the solution & debug info, I'll post this in a comment below.

UPDATE: I solved the issue with the electron node.js app. It just wasn't running :smile:. I had assumed this app was included in the docker container, and that the first part of the instructions were for running it outside the container (e.g.: for development). Looks like it works great when accessing the /habitat URL on the same host! The only issue now is that my iPhone won't reliably connect to the WiFi Data Safari Access Point. Sometimes I see the same issue as I did at the art installation where it fails to connect. Other times, it just fails to show the AP in the list entirely. I suspect it's some combination of device + driver + iPhone behavior here. Maybe my WiFi card doesn't support running hostapd & airodump-ng both accessing this old USB dongle at the same time? Either way, I'm happy to have the WebGL display working now!

I had a couple questions after my experience:

$ docker logs -f b29fb3db1df2a5397befdfbe7e564927aeb90be46d0feef69a7d80531bcbaae0
[ ok ] Starting system message bus: dbus.
[ ok ] Starting DNS forwarder and DHCP server: dnsmasq.
[ ok ] Starting advanced IEEE 802.11 management: hostapd.
iptables: No chain/target/match by that name.
iptables: Bad rule (does a matching rule exist in that chain?).
iptables: Bad rule (does a matching rule exist in that chain?).
Proxy server listening at http://0.0.0.0:1337
#### I connect my iPhone here... then this single request is logged
10.0.0.103:64899: clientconnect
10.0.0.103:64899: GET http://init-p01st.push.apple.com/bag
               << 200 OK 7.75k
#### Now I connect to http://wifi.safari  on the iPhone, and cannot connect
10.0.0.103:61952: clientconnect
10.0.0.103:61952: GET http://wifi.safari/
 << Server connection to 10.0.0.1:80 failed: Error connecting to "10.0.0.1": [Errno 111] Connection refused
10.0.0.103:61952: clientdisconnect
#### NOTE:  This was fixed by starting the node server app, but sometimes the AP goes down (maybe USB dongle can't handle both hostapd + airodump-ng?)

#### If I use the iPhone to browse to http://10.0.0.1:1337, I get infinite log lines like:

10.0.0.103:61952: GET http://10.0.0.1:1337/
10.0.0.103:61952: clientconnect
10.0.0.1:58627: clientconnect
10.0.0.1:42363: clientconnect
10.0.0.1:53109: clientconnect
10.0.0.1:43201: clientconnect
10.0.0.1:59433: clientconnect
10.0.0.1:47047: clientconnect
10.0.0.1:34425: clientconnect
10.0.0.1:52019: clientconnect
10.0.0.1:36509: clientconnect
[...SNIP...]
trinitronx commented 6 years ago

In case you are interested in the solution for supporting this old Ralink based USB WiFi adapter, read on:

Support & Debug Info for: Hawking HWUG1 USB WiFi adapter

This WiFi adapter is a single antenna USB dongle that has an Ralink chipset inside. It is supported by the mainline kernel in rt2x00 drivers. The kernel logs via dmesg show the following when detecting this chipset:

[ 5068.297924] usb 1-1: new high-speed USB device number 10 using xhci_hcd
[ 5068.577476] usb 1-1: New USB device found, idVendor=148f, idProduct=2573
[ 5068.577482] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 5068.577486] usb 1-1: Product: 802.11 bg WLAN
[ 5068.577490] usb 1-1: Manufacturer: Ralink
[ 5068.698091] usb 1-1: reset high-speed USB device number 10 using xhci_hcd
[ 5069.168956] ieee80211 phy3: rt2x00_set_chip: Info - Chipset detected - rt: 2573, rf: 0002, rev: 000a
[ 5069.169581] ieee80211 phy3: Selected rate control algorithm 'minstrel_ht'
[ 5069.190358] rt73usb 1-1:1.0 wlx000e3bNNNNNN: renamed from wlan0
[ 5069.238816] IPv6: ADDRCONF(NETDEV_UP): wlx000e3bNNNNNN: link is not ready
[ 8325.299413] ieee80211 phy3: rt2x00lib_request_firmware: Info - Loading firmware file 'rt73.bin'
[ 8325.299443] rt73usb 1-1:1.0: Direct firmware load for rt73.bin failed with error -2
[ 8325.299447] ieee80211 phy3: rt2x00lib_request_firmware: Error - Failed to request Firmware
[ 8325.570673] ieee80211 phy3: rt2x00lib_request_firmware: Info - Loading firmware file 'rt73.bin'
[ 8325.570680] rt73usb 1-1:1.0: Direct firmware load for rt73.bin failed with error -2
[ 8325.570681] ieee80211 phy3: rt2x00lib_request_firmware: Error - Failed to request Firmware
[ 8506.465342] ieee80211 phy3: rt2x00lib_request_firmware: Info - Loading firmware file 'rt73.bin'
[ 8506.465349] rt73usb 1-1:1.0: Direct firmware load for rt73.bin failed with error -2
[ 8506.465350] ieee80211 phy3: rt2x00lib_request_firmware: Error - Failed to request Firmware

Initially, the issue was that rt73.bin firmware files were not found. I fixed this later by ensuring /lib/firmware is mounted into the docker container. If the host is missing these firmware files, they can be downloaded from Linux From Scratch here. This can help for distros that neglected to include them.

Problem & path to solution

After following the setup instructions in this repo, I saw that hostapd was not starting. This was in the docker container output:

$ docker logs -f 8c4ef718eae48883def86355409b2480ac1f6744a23f1f119d4830813a46bc48                                                                                                                  
SIOCSIFFLAGS: Operation not possible due to RF-kill                                                                                                                                                                                          
[ ok ] Starting system message bus: dbus.                                                                                                                                                                                                    
[ ok ] Starting DNS forwarder and DHCP server: dnsmasq.                                                                                                                                                                                      
[FAIL] Starting advanced IEEE 802.11 management: hostapd failed!                                                                                                                                                                             
iptables: No chain/target/match by that name.                                                                                                                                                                                                
iptables: Bad rule (does a matching rule exist in that chain?).                                                                                                                                                                              
iptables: Bad rule (does a matching rule exist in that chain?).                                                                                                                                                                              
iptables: No chain/target/match by that name.                                                                                                                                                                                                
Proxy server listening at http://0.0.0.0:1337

$ docker exec -ti 8c4ef718eae48883def86355409b2480ac1f6744a23f1f119d4830813a46bc48 /bin/bash
## Checked /etc/init.d/hostapd and found env vars needed to start it
root@dockerhost:~# grep -i 'DAEMON.*=\|PID.*=' /etc/init.d/hostapd
DAEMON_SBIN=/usr/sbin/hostapd
DAEMON_DEFS=/etc/default/hostapd
DAEMON_CONF=
PIDFILE=/run/hostapd.pid
DAEMON_OPTS="-B -P $PIDFILE $DAEMON_OPTS $DAEMON_CONF"

## Create an env file to emulate how start-stop-daemon will execute hostapd
root@saturn:~# grep -i 'DAEMON.*=\|PID.*=' /etc/init.d/hostapd | sed -e '/^DAEMON_CONF/d' -e 's/^/export /'  > /tmp/hostapd.env
root@saturn:~# cat /tmp/hostapd.env
export DAEMON_SBIN=/usr/sbin/hostapd
export DAEMON_DEFS=/etc/default/hostapd
export PIDFILE=/run/hostapd.pid
export DAEMON_OPTS="-B -P $PIDFILE $DAEMON_OPTS $DAEMON_CONF"

## Set up environment and start it with extra debug messages
root@dockerhost:~# source /etc/default/hostapd
root@dockerhost:~# source /tmp/hostapd.env
root@dockerhost:~# env | grep -i 'DAEMON\|PID'
DAEMON_DEFS=/etc/default/hostapd
DAEMON_OPTS=-B -P /run/hostapd.pid -d /etc/hostapd/hostapd.conf
PIDFILE=/run/hostapd.pid
DAEMON_SBIN=/usr/sbin/hostapd

## Now start it!
root@dockerhost:~# $DAEMON_SBIN -dd $DAEMON_OPTS
random: Trying to read entropy from /dev/random
Configuration file: /etc/hostapd/hostapd.conf
rfkill: initial event: idx=0 type=1 op=0 soft=1 hard=0
rfkill: WLAN soft blocked
nl80211: Supported cipher 00-0f-ac:1
nl80211: Supported cipher 00-0f-ac:5
nl80211: Supported cipher 00-0f-ac:2
nl80211: Supported cipher 00-0f-ac:4
nl80211: Supported cipher 00-0f-ac:10
nl80211: Supported cipher 00-0f-ac:8
nl80211: Supported cipher 00-0f-ac:9
nl80211: Using driver-based off-channel TX
nl80211: interface wlx000e3bNNNNNN in phy phy0
nl80211: Set mode ifindex 4 iftype 3 (AP)
nl80211: Setup AP(wlx000e3bNNNNNN) - device_ap_sme=0 use_monitor=0
nl80211: Subscribe to mgmt frames with AP handle 0x55d44d588db0
nl80211: Register frame type=0xb0 (WLAN_FC_STYPE_AUTH) nl_handle=0x55d44d588db0 match=
nl80211: Register frame type=0x0 (WLAN_FC_STYPE_ASSOC_REQ) nl_handle=0x55d44d588db0 match=
nl80211: Register frame type=0x20 (WLAN_FC_STYPE_REASSOC_REQ) nl_handle=0x55d44d588db0 match=
nl80211: Register frame type=0xa0 (WLAN_FC_STYPE_DISASSOC) nl_handle=0x55d44d588db0 match=
nl80211: Register frame type=0xc0 (WLAN_FC_STYPE_DEAUTH) nl_handle=0x55d44d588db0 match=
nl80211: Register frame type=0xd0 (WLAN_FC_STYPE_ACTION) nl_handle=0x55d44d588db0 match=
nl80211: Register frame type=0x40 (WLAN_FC_STYPE_PROBE_REQ) nl_handle=0x55d44d588db0 match=
nl80211: Could not yet enable interface 'wlx000e3bNNNNNN' due to rfkill
nl80211: Add own interface ifindex 4
nl80211: if_indices[16]: 4
phy: phy0
BSS count 1, BSSID mask 00:00:00:00:00:00 (0 bits)
nl80211: Regulatory information - country=00
nl80211: 2402-2472 @ 40 MHz 20 mBm
nl80211: 2457-2482 @ 20 MHz 20 mBm (no IR)
nl80211: 2474-2494 @ 20 MHz 20 mBm (no OFDM) (no IR)
nl80211: 5170-5250 @ 80 MHz 20 mBm (no IR)
nl80211: 5250-5330 @ 80 MHz 20 mBm (DFS) (no IR)
nl80211: 5490-5730 @ 160 MHz 20 mBm (DFS) (no IR)
nl80211: 5735-5835 @ 80 MHz 20 mBm (no IR)
nl80211: 57240-63720 @ 2160 MHz 0 mBm
nl80211: Added 802.11b mode based on 802.11g information
Allowed channel: mode=1 chan=1 freq=2412 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=2 freq=2417 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=3 freq=2422 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=4 freq=2427 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=5 freq=2432 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=6 freq=2437 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=7 freq=2442 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=8 freq=2447 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=9 freq=2452 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=10 freq=2457 MHz max_tx_power=20 dBm
Allowed channel: mode=1 chan=11 freq=2462 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=1 freq=2412 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=2 freq=2417 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=3 freq=2422 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=4 freq=2427 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=5 freq=2432 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=6 freq=2437 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=7 freq=2442 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=8 freq=2447 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=9 freq=2452 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=10 freq=2457 MHz max_tx_power=20 dBm
Allowed channel: mode=0 chan=11 freq=2462 MHz max_tx_power=20 dBm
Driver does not support configured HT capability [SHORT-GI-20]
wlx000e3bNNNNNN: interface state UNINITIALIZED->DISABLED
wlx000e3bNNNNNN: AP-DISABLED 
wlx000e3bNNNNNN: Unable to setup interface.
hostapd_interface_deinit_free(0x55d44d5883f0)
hostapd_interface_deinit_free: num_bss=1 conf->num_bss=1
hostapd_interface_deinit(0x55d44d5883f0)
hostapd_bss_deinit: deinit bss wlx000e3bNNNNNN
wlx000e3bNNNNNN: Deauthenticate all stations
nl80211: send_mlme - da= ff:ff:ff:ff:ff:ff noack=0 freq=0 no_cck=0 offchanok=0 wait_time=0 fc=0xc0 (WLAN_FC_STYPE_DEAUTH) nlmode=3
nl80211: send_mlme -> send_frame
nl80211: send_frame - Use bss->freq=0
nl80211: send_frame -> send_frame_cmd
nl80211: CMD_FRAME freq=0 wait=0 no_cck=0 no_ack=0 offchanok=0
CMD_FRAME - hexdump(len=26): c0 00 00 00 ff ff ff ff ff ff 00 0e 3b 09 87 f0 00 0e 3b 09 87 f0 00 00 03 00
nl80211: Frame command failed: ret=-100 (Network is down) (freq=0 wait=0)
hostapd_cleanup(hapd=0x55d44d589710 (wlx000e3bNNNNNN))
hostapd_free_hapd_data: Interface wlx000e3bNNNNNN wasn't started
hostapd_interface_deinit_free: driver=0x55d44ccef980 drv_priv=0x55d44d58a5c0 -> hapd_deinit
nl80211: Remove monitor interface: refcount=0
nl80211: Remove beacon (ifindex=4)
netlink: Operstate: ifindex=4 linkmode=0 (kernel-control), operstate=6 (IF_OPER_UP)
nl80211: Set mode ifindex 4 iftype 2 (STATION)
nl80211: Teardown AP(wlx000e3bNNNNNN) - device_ap_sme=0 use_monitor=0
nl80211: Unsubscribe mgmt frames handle 0x8888dd5cc5d00539 (AP teardown)
hostapd_interface_free(0x55d44d5883f0)
hostapd_interface_free: free hapd 0x55d44d589710
hostapd_cleanup_iface(0x55d44d5883f0)
hostapd_cleanup_iface_partial(0x55d44d5883f0)
hostapd_cleanup_iface: free iface=0x55d44d5883f0

So, in this debug output I found the line: Driver does not support configured HT capability [SHORT-GI-20]

That led me to look at the pre-existing /etc/hostapd/hostapd.conf file, which had the following lines:

## Enable 802.11n
ieee80211n=1

## Enable 40MHz channels with 20ns guard interval
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]

Using the iw list command on the host, I was able to look at this adapter's supported channels & configurations. I realized that my WiFi adapter was too old to support the "HT" / MIMO / 80211n configuration here (it only has a single antenna). Additionally, it mentioned support for "HT Capability overrides: * short GI for 40 MHz". So, I disabled 80211n and changed 20 to 40 ([SHORT-GI-40]) by changing the /etc/hostapd/hostapd.conf file lines to:

## Disable 802.11n
## This was not supported by Hawking HWUG1: Ralink Chipset - rt: 2573, rf: 0002, rev: 000a
ieee80211n=0

## Enable 40MHz channels with guard interval also 40MHz / 40ns ??
ht_capab=[HT40][SHORT-GI-40][DSSS_CCK-40]

After changing this, I was still unable to start hostapd cleanly. I saw a couple lines in the debug log like:

rfkill: initial event: idx=0 type=1 op=0 soft=1 hard=0
rfkill: WLAN soft blocked
[...SNIP...]
nl80211: Could not yet enable interface 'wlx000e3bNNNNNN' due to rfkill
[...SNIP...]
wlx000e3bNNNNNN: Flushing old station entries
nl80211: flush -> DEL_STATION wlx000e3bNNNNNN (all)
nl80211: Station flush failed: ret=-100 (Network is down)
wlx000e3bNNNNNN: Could not connect to kernel driver
wlx000e3bNNNNNN: Deauthenticate all stations
[...SNIP...]

After a bit of searching, I found that the following commands on the host worked to avoid this issue:

sudo nmcli radio wifi off
sudo rfkill unblock wlan
sudo ifconfig wlx000e3bNNNNNN down

I put these in a new script called fix-wlan.sh, and run it before the docker-run.sh script. I tried restarting and again saw some errors in dmesg mentioning "rt73usb 1-1:1.0: Direct firmware load for rt73.bin failed with error -2". I fixed this by adding -v /lib/firmware:/lib/firmware:ro to the docker run ... line. After mounting the /lib/firmware directory into the container, I saw the following in host journalctl logs, validating that firmware was found and loaded:

Apr 29 19:31:50 dockerhost kernel: ieee80211 phy4: rt2x00lib_request_firmware: Info - Loading firmware file 'rt73.bin'
Apr 29 19:31:50 dockerhost kernel: ieee80211 phy4: rt2x00lib_request_firmware: Info - Firmware detected - version: 1.7

Finally, I created a ./etc/hostapd/hostapd.conf directory & file and volume mounted this into docker run [...SNIP...] -v "$(pwd)/etc/hostapd:/etc/hostapd:rw". I used the two lines from above to turn off the 80211n support. Now, I saw all services start from a fresh container:

$ bash -x ./fix-wlan.sh 
+ sudo nmcli radio wifi off 
+ sudo rfkill unblock wlan
+ sudo ifconfig wlx000e3bNNNNNN down
$ bash -x ./docker-run.sh 
++ pwd
++ pwd
+ docker run -it --net host --privileged -e COLUMNS -e LINES -e TERM -e AP_IFACE=wlx000e3bNNNNNN -e INTERNET_IFACE=eth1 -e 'SSID=WiFi Data Safari' -e MAC=unchanged -v ~/src/pub/wifi-data-safari/data:/root/data -v ~/src/pub/wifi-data-safari/etc/hostapd:/etc/hostapd:rw -v /lib/firmware:/lib/firmware:ro --detach --rm brannondorsey/mitm-router:wifi-data-safari
b29fb3db1df2a5397befdfbe7e564927aeb90be46d0feef69a7d80531bcbaae0
trinitronx@saturn:wifi-data-safari(master)$ docker logs -f b29fb3db1df2a5397befdfbe7e564927aeb90be46d0feef69a7d80531bcbaae0
[ ok ] Starting system message bus: dbus.
[ ok ] Starting DNS forwarder and DHCP server: dnsmasq.
[ ok ] Starting advanced IEEE 802.11 management: hostapd.
iptables: No chain/target/match by that name.
iptables: Bad rule (does a matching rule exist in that chain?).
iptables: Bad rule (does a matching rule exist in that chain?).
Proxy server listening at http://0.0.0.0:1337
brannondorsey commented 6 years ago

Hey @trinitronx, thanks so much for your interest in this project! It was great to meet you this weekend as well. I wish I had a chance to chat a bit more with you as it sounds like you are also up to some pretty cool projects + code stuffs. First off, I want to say kudos to you for venturing into the relatively undocumented territory that a lot of this project occupies. We've got breadcrumbs out there for avid *nix'ers to find, but ultimately there isn't a whole lot of hand holding with a lot of these docs, so I'm glad you've been able to get the project up and running!

As you have likely realized by now, the docker container we are using is a special branch of my mitm-router repo which was originally designed to ease the process of setting up an ad-hoc WiFi access point using dnsmasq + hostapd. It is not required to run the docker container to access the /habitat, /map, or /index.html views of the sniffer application. For that, all you have to do is clone this repo, npm install, and then run node server -i someInterfaceThatSupportsMonitorMode provided you already have aircrack-ng installed. The brannondorsey/mitm-router:wifi-data-safari docker container is used in combination with this node server (which is expected to already be running on the host machine) to host the WiFi network that we use during the workshop to serve everyone else the app. For your purposes, you can totally ignore this ad-hoc WiFi network and run everything from localhost.

As for the iptables rule oddities, you are spot on that the 80->1337 redirects are quite strange. That oddity is coming from our reliance on mitm-router (and specifically, how I originally wrote mitm-router to forward traffic on port 80 to 1337 for mitmproxy) to serve the WiFi access point. It works for our purposes for the workshop, but you are right that the iptable rules are quite strange. Sorry for the confusion there, that is really a product of the dependence on the mitm-router project more than anything else.

Finally, in answer to your suggestion of favorite WiFi cards that support monitor mode, I can't recommend the TP-LINK TL-WN722N enough (except for it supports 2.4GHz only, not 5.0GHz). It is an amazing card, and up until a year or so ago, it was the defacto h4x0r WiFi dongle... But recently, the new generation of dongles has shipped with a chipset that DOES NOT support monitor mode. Best I can tell, when you order a TL-WN722N there is no way of determining whether you are going to receive the old (good) chipset or a model with the new (shit) chipset. I've never come across a model that doesn't support monitor mode, but I've read horror stories on the net from those who have. So with that said, I'm not sure I can recommend it unless you can confirm you are getting an older model. For a 2018 list of WiFi dongles that support monitor mode, check out this link: http://www.wirelesshack.org/best-kali-linux-compatible-usb-adapter-dongles-2016.html

trinitronx commented 6 years ago

@brannondorsey: Thanks for the explanation of those networking pieces! Makes sense as far as what I was seeing with the mitmproxy -> 80 routing loop. I think the original issue was that I just assumed brannondorsey/mitm-router:wifi-data-safari docker image was an "all-in-one" container that would run node + hostapd & networking bits. So when I tried to debug via curl, I was hitting 1337 directly but it looped back to 80 where nothing was listening, and then back through 1337 and mitmproxy and around again!

I think the other issue was just due to that old USB hardware not supporting well the combination of 2 apps both needing access at once to the card. Probably a bit too much to ask of that cheap old USB dongle for both aircrack-ng in monitor mode & hostapd to set up an AP.

Thanks for the tips about that TP-LINK card & chipset! So much in *nix is about good hardware & driver support! I'll check out that list of USB dongles too, it looks like a lot are also much newer Ralink chipsets! Would be great to get a 5GHz one that supports the ieee80211n setting.

It was great to talk with you guys, and I'm happy to chat more about projects and such. If I have some free time I'd love to check out the midi-rnn project and test it out.