Having said that, this is a project that I have been working on for a while now and that numerous times I have seen people asking around the internet without much success. I refer to the idea of creating a wireless (wireless to wireless interface) transparent bridge using a Raspberry Pi; or well, I do not see a problem in using a similar approach to do the same at least on any other Debian based system. I have to say as well, that this method will not create a layer 2 bridge (transparent bridge) per se, but still, will make the Raspberry Pi to behave in a very similar fashion with the exception that the RPi will get an IP address too (something that a layer2 bridge shouldn't do) and other technical characteristics that would not let to classify this as a "transparent" wireless bridge. On the other side, the RPi will relay DHCP messages from the router and let devices from one side to the other of the RPi to be visible and communicate as it is supposed to happen when using a bridge; something very useful when for example in my case, needed to connect to a printer that was too far away from my home router and extending my WiFi range to the rooms at the back of the house and still allow those PC's to be on the same network of other devices in the house. Something that would not be possible if using the typical guides to setup the RPi as a wireless router access point. In order to do so, in this method I use proxy ARP bridging. I will leave the long technical explanations for you to find or else, this post will become very long.
Finally, my setup for this project is:
I am using a RPi 2 B+ and 2 cheap Realtek 802.11AC USB dongles. And with this, I would like to make emphasis that I tried in the pass to work with a RPi 3, using its built-in WiFi and an external WiFi usb dongle and I had many complications because sometimes the RPi will label the built-in WiFi with a name different to Wlan0 which gave me a couple of headaches at the moment. So, I would recommend to use 2 USB dongles and disable the built-in WiFi or use some method similar to the explained in https://www.raspberrypi.org/forums/view ... 6&t=198946, but will leave that out of this guide and leave it to you to figure out how to do that.
Anyway, without any more preambles:
HOW TO SETUP A RASPBERRY PI AS A WIRELESS BRIDGE
In this guide, we will setup wlan0 to be the port that connects to your home wireless router and wlan1 will be our relaying wireless access point. Besides, to do so, it is necessary to create a bash script that will run every time that the RPi boots and will essentially manage the bridging proper functioning.
First, we need to install all the necessary software:
Code: Select all
sudo apt install parprouted dhcp-helper hostapd bcrelayBcrelay is a tool used to relay (pass) broadcast messages and should be installed just if you need to broadcast messages in your network. I needed to do this for an specific application in the pass, but is really rarely used by standard users and everyday applications.
We need to stop the wlan1 port (our relaying wireless access point) from being allocated IP addresses by the DHCP client on the Raspberry Pi. So open up
Code: Select all
sudo nano /etc/dhcpcd.confCode: Select all
allowinterfaces eth0 wlan0
denyinterfaces wlan1Note2: The allowinterfaces line is overkill, since it is supposed to be done by default.
Now, we need to setup our relaying access point. To do so, create a configuration file for hostapd with
Code: Select all
sudo nano /etc/hostapd/hostapd.confCode: Select all
# WiFi interfaces to use for AP (Access Point)
interface=wlan1
# Use the nl80211 driver
driver=nl80211
# AP name
ssid=My-test-AP
# Use the 5GHz band. Use "a" for 5GHz and "g" for 2.4GHz
hw_mode=a
# Use channel 48. It can be set to "0" to let hostapd to find the best channel but only works with Atheros
# based chips
channel=48
# Limit the frequencies used to those allowed in the country
ieee80211d=1
# Country Code
country_code=AU
# Enable 802.11n support
ieee80211n=1
# Enable 802.11ac support
ieee80211ac=1
# Enable WMM (QoS support)
wmm_enabled=1
# Enable 40MHz channels with 20ns guard interval. Do we need this at all?
#ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]
# Accept all MAC addresses
macaddr_acl=0
# Use WPA authentication (1=wpa, 2=wep, 3=both)
auth_algs=1
# Use WPA2
wpa=2
# Use a pre-shared key
wpa_key_mgmt=WPA-PSK
# Use AES, instead of TKIP
rsn_pairwise=CCMP
# AP password
wpa_passphrase=myTestPassCode: Select all
sudo nano /etc/sysctl.conf.net.ipv4.ip_forward=1
To be able to use all this setup as a bridge, start and if necessary to re-establish the bridge, I wrote a bash script. By the way, I created this script with my basics knowledge of bash and semi-decent "C" programming logic, so I do not intent this script to be an ultimate solution and am aware that is very probable there is room for improvement in the script.
To do so, create a file at some known location. I created mine with
Code: Select all
sudo nano /home/pi/bin/LAN2_Bridge.shCode: Select all
#!/bin/bash
#---------------------------------------------------------------------------
# Variables declaration
#---------------------------------------------------------------------------
# Uncomment if broadcast-relaying is necessary
#bcRelay_ON=1
wlanCXed=0
idx=0
err_ON=0
scriptPath=""
#---------------------------------------------------------------------------
# Local Functions
#---------------------------------------------------------------------------
arp_routing(){
local __iface1=$1
local __iface2=$2
parprouted $__iface1 $__iface2 >> "$scriptPath" 2>&1
if [ "$(echo $?)" -ne 0 ]
then
sleep 1
return 1
fi
return 0
}
dhcp_relay(){
local __iface1=$1
local __iface2=$2
#local dhcp_server=$(grep -w "dhcp-server" \
#/var/lib/dhcp/dhclient.$__iface1.leases | tail -n1 | awk '{print $3}' \
#| cut -d';' -f1)
local dhcp_server=$(grep -R "offered" \
/var/log/* | tail -n1 | awk '{print $(NF)}')
dhcp-helper -s "$dhcp_server" -i "$__iface2" >> "$scriptPath" 2>&1
if [ "$(echo $?)" -ne 0 ]
then
sleep 1
return 1
fi
return 0
}
host_ap(){
hostapd -B /etc/hostapd/hostapd.conf >> "$scriptPath" 2>&1
if [ "$(echo $?)" -ne 0 ]
then
sleep 1
return 1
fi
return 0
}
bc_relay(){
local __iface1=$1
local __iface2=$2
bcrelay -d -n -i "$__iface1" -o "$__iface2" >> "$scriptPath" 2>&1
if [ "$(echo $?)" -ne 0 ]
then
sleep 1
return 1
fi
return 0
}
kill_process(){
local __proc2kill=$1
local CMDresult=$(ps aux | grep -v grep | grep "$__proc2kill")
if [ -n "$CMDresult" ]
then
killall "$__proc2kill" >> "$scriptPath" 2>&1
#while read line
#do
# kill $(echo $line | cut -d' ' -f2) >> "$scriptPath" 2>&1
#done <<< $CMDresult
fi
}
RST_process(){
until ( ifconfig wlan1 down >> "$scriptPath" 2>&1 )
do
sleep 1
done
sleep 1
until (ip addr flush dev wlan1 >> "$scriptPath" 2>&1)
do
sleep 1
done
kill_process "parprouted"
kill_process "dhcp-helper"
kill_process "hostapd"
# Executes this section if bcRelay_ON is enabled (not commented)
if [ -v bcRelay_ON ]
then
kill_process "bcrelay"
fi
sleep 1
}
CX_start(){
err_ON=0
RST_process
wlan0Info=""
while [ "$wlan0Info" == "" ]
do
# Check if wlan0 has an IP. Drops results and logs error messages
if [ "$(ifconfig wlan0 2>>"$scriptPath" | grep -w "inet" | awk '{print $2}')" != "" ]
then
# Using wlan0Info just as a test condition to help exit this loop.
# wlan0Info is reused later
wlan0Info="exit"
else
sleep 1
fi
done
wlan0Info=$(ip a show wlan0)
wlan0IP=$(echo "$wlan0Info" | grep -w "inet" | awk '{print $2}' | cut -d'/' -f1)
wlanIPMask=$(echo "$wlan0Info" | grep -w "inet" | awk '{print $2}' | cut -d'/' -f2)
wlanbrd=$(echo "$wlan0Info" | grep -w "inet" | awk '{print $4}')
wlan1IP1=$(echo "$wlanbrd" | cut -d'.' -f1)
wlan1IP2=$(echo "$wlanbrd" | cut -d'.' -f2)
wlan1IP3=$(echo "$wlanbrd" | cut -d'.' -f3)
wlan1IP4=$(($(echo "$wlanbrd" | cut -d'.' -f4) - 1))
wlan1IP=$(echo "$wlan1IP1"'.'"$wlan1IP2"'.'"$wlan1IP3"'.'"$wlan1IP4")
until ( ifconfig wlan1 up >> "$scriptPath" 2>&1 )
do
sleep 1
done
sleep 1
until (ip addr flush dev wlan1 >> "$scriptPath" 2>&1)
do
sleep 1
done
until ( ip addr add $(echo "$wlan1IP"'/'"$wlanIPMask") brd + dev wlan1 \
>> "$scriptPath" 2>&1 )
do
sleep 1
done
until ( $(arp_routing "wlan0" "wlan1") )
do
idx=$(("$idx"+1))
if [ "$idx" -eq 5 ]
then
echo "parprouted failed" >> "$scriptPath" 1>&1
err_ON=1
break
fi
done
# echo "here1"
if [ $err_ON -eq 0 ]
then
idx=0
until ( $(dhcp_relay "wlan0" "wlan1") )
do
idx=$(("$idx"+1))
if [ "$idx" -eq 5 ]
then
echo "dhcp-relay failed" >> "$scriptPath" 1>&1
err_ON=1
break
fi
done
fi
if [ $err_ON -eq 0 ]
then
idx=0
until ( $(host_ap) )
do
idx=$(("$idx"+1))
if [ "$idx" -eq 5 ]
then
echo "Host AP failed" >> "$scriptPath" 1>&1
err_ON=1
break
fi
done
fi
# Executes this section if bcRelay_ON is enabled (not commented)
if [ -v bcRelay_ON ]
then
for i in $(seq 1 2)
do
if [ $err_ON -eq 0 ]
then
idx=0
iface1="wlan0"
iface2="wlan1"
if [ $i -eq 2 ]
then
iface1="wlan1"
iface2="wlan0"
fi
until ( $(bc_relay "$iface1" "$iface2") )
do
idx=$(("$idx"+1))
if [ "$idx" -eq 5 ]
then
echo "BC_Relay failed" >> "$scriptPath" 1>&1
err_ON=1
break
fi
done
fi
done
fi
if [ $err_ON -eq 0 ]
then
wlanCXed=1
else
sleep 10
fi
}
check_processes(){
if [ "$(ps aux | grep -v grep | grep parprouted)" == "" ]
then
return 1
elif [ "$(ps aux | grep -v grep | grep dhcp-helper)" == "" ]
then
return 1
elif [ "$(ps aux | grep -v grep | grep hostapd)" == "" ]
then
return 1
elif [ -v bcRelay_ON ]
then
if [ "$(ps aux | grep -v grep | grep bcrelay)" == "" ]
then
return 1
fi
fi
return 0
}
CX_check(){
if [ "$(ifconfig wlan0 | grep inet)" != "" ] && \
[ $(check_processes; echo $?) -eq 0 ]
then
sleep 1m
else
RST_process
wlanCXed=0
fi
}
#---------------------------------------------------------------------------
# Main
#---------------------------------------------------------------------------
scriptPath="$(cd "$(dirname $0)"; pwd -P)""/log_err"
echo "Start" > "$scriptPath" 1>&1
# Main Loop. Starts and keep checking on connection to not to break, and
# all of the packages used to not to be ended. If any of this two conditions
# happen, kills all processes, wait the connection to the router
# to be re-stablished and start all processes again
while true
do
if [ $wlanCXed -eq 0 ]
then
CX_start
else
CX_check
fi
done
exit 0
#---------------------------------------------------------------------------
# END
#---------------------------------------------------------------------------After created, saved and closed, we need to change the script permissions to allow the file to be executable. This can be easily be done with the chmod command. In my example, I did with:
Code: Select all
sudo chmod 755 /home/pi/bin/LAN2_Bridge.shNow, to finish all this setup up, connect wlan0 to your wireless router so that your router details are saved or do it manually by editing the file "/etc/wpa_supplicant/wpa_supplicant.conf" (will leave it at your preference) and reboot the RPi.
After rebooting, the bridge should be available soon after and ready to be used. Be sure that wlan0 is connecting automatically to your home router since the whole bridging process depends on this interface to be up, running and connected to a router.