Skip to content

USB Dongle Wifi Configuration

Julius Heine edited this page Sep 18, 2018 · 25 revisions

USB Dongle Wifi Configuration

Intro

Since we are using the internal wifi of the rasperry pi for the adhoc network we are not able to connect to an additional wifi network as internet gateway with the same card.

Prove:

Just type iw list to see all interface options.
At the end it shows a section with allowed interface combinations. For the raspberry pi 3 b+ you can see that it is possible to use it as wifi client and hotspot at the same time but not ibss (which stands for ad hoc mode):

valid interface combinations:
		 * #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
		   total <= 3, #channels <= 2
		 * #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1,
		   total <= 4, #channels <= 1

Because of that we have to use an external wifi usb card.
You can check if it has connected successfully to your raspberry pi
by using the command iw dev:

phy#1
	Interface wlan1
		ifindex 4
		wdev 0x100000001
		addr bc:05:43:0e:f6:51
		type managed
		channel 11 (2462 MHz), width: 20 MHz, center1: 2462 MHz
		txpower 20.00 dBm
phy#0
	Interface wlan0
		ifindex 2
		wdev 0x1
		addr b8:27:eb:77:3d:37
		ssid rpiadhoc
		type IBSS
		channel 5 (2432 MHz), width: 20 MHz, center1: 2432 MHz
		txpower 31.00 dBm

So in my case wlan0 is still the adhoc interface and wlan1 is the new usb wifi interface which we will use to connect to a wifi network to use it as internet gateway.

Wifi Configuraiton

Just create a wifi configuration:
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf:

country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid="myhomewifi"
psk=<passwordhashofwpacommandlookpidocs>
}

network={
ssid="eduroam"
proto=RSN
key_mgmt=WPA-EAP
eap=PEAP
identity="s<number>@tu-dresden.de"
password=hash:<hashofspecialcommand>
phase1="peaplabel=0"
phase2="auth=MSCHAPV2"
}

Hint: Do not use tabs or blank characters in the network brackets because sometimes you get errors if you use different numbers or a combination of tabs or blank characters.

My configuration shows two networks. The first is my home network and the second a special configuration for our university wifi.
Follow these links for more information:

Check your configuration with debug mode:

sudo wpa_supplicant -i wlan1 -D wext -c /etc/wpa_supplicant/wpa_supplicant.conf -d

If there are no problems then create Daemon (Background) Mode:

sudo wpa_supplicant -i wlan1 -D wext -c /etc/wpa_supplicant/wpa_supplicant.conf -B

Startup script with routing

A little change at the end of your script for the iptables routing (replace the lancabel eth0 with wlan1):

In your default user folder /home/pi create a file for the script: sudo nano batsetup-rpi.sh:

iw wlan0 set type ibss
ip link set wlan0 up

iw wlan0 ibss join <adhocnetworkname> 2432 key d:2:<password>
# replace <adhocnetworkname> with a ssid for example: rpiadhoc
# replace <password> with a password of length 5 or 13 (WEP) for example: abcdefghijklm

modprobe batman-adv
batctl if add wlan0

ip link set up dev wlan0
ip link set up dev bat0

batctl gw_mode server

# set bat0 mac address as wlan0 mac address plus one
ip link set bat0 address b8:27:eb:77:3d:38

# set IPv6 link-local adress
# help link: https://ben.akrin.com/?p=1347
ip -6 addr add fe80::ba27:ebff:fe77:3d38/64 dev bat0

# Set Gateway IP
ip addr add 1.0.0.1/24 broadcast 1.0.0.255 dev bat0 # no duplicate IPs allowed when having multiple gateways

# This sets up routing between the mesh network (bat0) and the internet wifi network (wlan1)
iptables -t nat -A POSTROUTING -o wlan1 -j MASQUERADE
iptables -A FORWARD -i wlan1 -o bat0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i bat0 -o wlan1 -j ACCEPT

sleep 10
alfred -i bat0 -m -p 1 &
sleep 10
batadv-vis -i bat0 -s &

Go back to the gateway tutorial (Link)

Wifi client and hotspot at the same time with internet sharing

Being a wifi client and creating a hotspot is no problem for most wifi modules.

Just check you cards capabilities with the iw list again.
At the end it says the following in my case:

valid interface combinations:
		 * #{ managed, P2P-client } <= 2, #{ AP, mesh point, P2P-GO } <= 2,
		   total <= 2, #channels <= 1

The valid interface combinations section is at the end of the output.
Just be sure to read the one of the phy1 section!
The command lists the info of all connected wifi cards.

This is a link to a wifi client + ap/hotspot tutorial

I changed my configuration a little bit:

sudo apt-get install -y hostapd

/etc/default/hostapd:

DAEMON_CONF="/etc/hostapd/hostapd.conf"

sudo nano /etc/dhcpcd.conf (end of file):

# fallback to static profile on eth0
#interface eth0
#fallback static_eth0

denyinterfaces wlan0
#denyinterfaces eth0

denyinterfaces ap0

sudo nano /etc/dnsmasq.conf:

# DHCP-Server aktiv für WLAN-Interface
interface=bat0,ap0

# DHCP-Server nicht aktiv für bestehendes Netzwerk
no-dhcp-interface=eth0

# IPv4-Adressbereich und Lease-Time
dhcp-range=bat0,1.0.0.50,1.0.0.150,24h
dhcp-range=ap0,2.0.0.50,2.0.0.150,12h


# DNS
dhcp-option=option:dns-server,8.8.8.8

# Gateway
dhcp-option=bat0,3,1.0.0.31
dhcp-option=ap0,3,2.0.0.1

sudo nano batsetup-rpi.sh:

.
. something else before (only changed end)
.

# Set Gateway IP
ip addr add 1.0.0.31/24 broadcast 1.0.0.255 dev bat0

# set ap ip
ip addr add 2.0.0.1/24 broadcast 2.0.0.255 dev ap0

# This sets up routing between the mesh network (bat0) and the internet wifi network (wlan1)
iptables -t nat -A POSTROUTING -o wlan1 -j MASQUERADE
iptables -A FORWARD -i wlan1 -o bat0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i bat0 -o wlan1 -j ACCEPT

# additional This sets up routing between the hotspot network (ap0) and the internet wifi network (wlan1)
iptables -A FORWARD -i wlan1 -o ap0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i ap0 -o wlan1 -j ACCEPT

sleep 10
alfred -i bat0 -m -p 1 &
sleep 10
batadv-vis -i bat0 -s &

sudo nano /etc/hostapd/hostapd.conf:

interface=ap0
ssid=<ssid>
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=<wifipassword>
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Important note: The channel has to be the same as the channel of the client wifi!

sudo nano /etc/udev/rules.d/90-wireless.rules:

SUBSYSTEM=="ieee80211", ACTION=="add|change", ATTR{macaddress}=="<macaddressofwlan1>", KERNEL=="phy1", \
	RUN+="/sbin/iw phy phy1 interface add ap0 type __ap", \
	RUN+="/bin/ip link set ap0 address <macaddressofwlan1butlastdigitoneuptobenotthesame>"

Automatically change the AP channel to the client channel

Create a systemd service which checks the channels and restarts hostapd if necessary:

nano /home/pi/hostapd_change_channel.sh

#!/bin/bash
CONFIG_FILE=/etc/hostapd/hostapd.conf
TARGET_KEY=channel

CURRENTCHANNEL=$(iwlist wlan1 channel | grep "Current" | grep -o '[0-9]*'| tail -n 1)
CONFIGCHANNEL=$(cat $CONFIG_FILE | grep "channel" | grep -o '[0-9]*'| tail -n 1)
# echo "${CHANNELLINE}"

APINTERFACESTATUS="$(cat /sys/class/net/ap0/operstate)"
if [ "$APINTERFACESTATUS" != "up" ]
then
    echo "interface ap0 was not up - now setting up..."
    sudo ip link set ap0 up
else
    echo "interface ap0 was already set up"
fi


if [ -n "$CURRENTCHANNEL" ]
then
    if [ "$CURRENTCHANNEL" != "$CONFIGCHANNEL" ]
    then
        echo "Changing AP channel and restarting hostapd"
        REPLACEMENT_VALUE=$CURRENTCHANNEL

        sudo sed -i "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE

        sudo systemctl restart hostapd.service
    else
        echo "AP and client channels are already the same"
    fi
else
    echo "there is no current wifi client channel"
fi

Make the script executable:
chmod u+x /home/pi/hostapd_change_channel.sh

Create a systemd service which starts the script at startup:

sudo nano /etc/systemd/system/apchannelchange.service

[Unit]
Description=Change AP channel to client channel
After=network.target

[Service]
WorkingDirectory=/home/pi/
ExecStart=/home/pi/hostapd_change_channel.sh
User=pi
Type=simple
Restart=always
TimeoutSec=100
RestartSec=60

[Install]
WantedBy=multi-user.target

Afterwards run the following commands:

sudo systemctl daemon-reload
sudo systemctl enable apchannelchange.service
sudo systemctl start apchannelchange.service

Now the script periodically checks the wifi channels every minute and even restarts the hotspot if the client wifi channel changes when the pi already was connected before.
The wifi client (wlan1) does not reconnect to changed channels automatically at the moment. So this has to improve. But since wifi channels only change very rarely i will work on this later. For now just reboot the raspberry pi if it does not reconnect as client to a wifi because of a changed channel.

Sources

Important note:
Some of following sources/tutorials work on older Raspbian versions and not on the new one due to some changes with the network commands and interfaces.