Skip to content

Instantly share code, notes, and snippets.

@samson4649
Created August 14, 2020 07:40
Show Gist options
  • Save samson4649/413d6419bb872143d23dc85ded070c04 to your computer and use it in GitHub Desktop.
Save samson4649/413d6419bb872143d23dc85ded070c04 to your computer and use it in GitHub Desktop.
Bash hotspot creation script - has some bugs but i use internally when needed.
#!/bin/bash
if (( $(id -u) != 0 )); then
echo "Non root user detected - need to run with root privileges. Exiting..."
exit 99
fi
### start functions
function _clean(){
graceful_exit 5
rm "${ERR_FIFO}" "${LOG_DIR}" -r &>/dev/null
exec 2>&-
exec 3<&-
}
function _out(){
echo "$@"
}
function _debug(){
[[ "${DEBUG,,}" == "true" ]] && _out "[DEBUG] $@"
}
function _info(){
_out "[INFO] $@"
}
function _warn(){
_out "[WARN] $@"
}
function _error(){
_out "[ERROR] $@"
}
function print_err(){
echo -e "\n\n!!! Error Dump !!!\n"
sleep 1
cat <$ERR_FIFO
echo -e "\n!!! End Dump !!!\n"
exit 99
}
function _pause(){
sleep 0.5
}
graceful_exit() {
echo "Exit requested..."
_debug "closing ${HS_INTERFACE}"
iw dev ${HS_INTERFACE} del
_debug "bringing OG wifi interface back online"
ip l set up dev wlan0
_pause
local timeout=${1:-4}
local list=""
for c in $(ps -o pid= --ppid $$); do
# request children shutdown
kill -0 ${c} 2>/dev/null && kill -TERM ${c} && list="$list $c" || true
done
if [ -n "$list" ]; then
# schedule hard kill after timeout
(sleep ${timeout}; kill -9 ${list} 2>/dev/null || true) &
local killer=${!}
wait ${list} 2>/dev/null || true
# children exited gracfully - cancel timer
sleep 0.5 && kill -9 ${killer} 2>/dev/null && list="" || true
fi
[ -z "$list" ] && echo "Exit Gracefully (0)" && exit 0 || echo "Dirty Exit (1)" && exit 1
}
### end functions
## trap exit
trap exit INT TERM ERR
trap _clean EXIT
# make fifo for stderr hiding
ERR_FIFO=/tmp/hotspot_setup.stderr
exec 3<>$ERR_FIFO
exec 2>&1
DEBUG=true
LOG_DIR=$(mktemp -d)
declare -a PIDS
# interface bindings
SRC_DEVICE=phy0
HS_INTERFACE=hotspot0
BR_INTERFACES=()
USE_BRIDGE=""
# check that the interface supports ap mode
if ! iw phy | head -n +$(iw phy | grep -n 'Band 1:' | cut -d':' -f1) | tail -n +$(iw phy | grep -n 'Supported interface modes:' | cut -d':' -f1) | grep -E '^[[:space:]]*\* AP$' &>/dev/null ; then
echo "no interface that is compatible with AP mode found. Exiting..."
exit 99
fi
# check if the user wants a bridge wrapped on the interface
if [ -z "${USE_BRIDGE}" ]; then
read -p "Do you want to bind the interface to a bridge (alternative to routing) ( default: false ): " yn
case ${yn,,} in
y*)
USE_BRIDGE=true
;;
n*)
USE_BRIDGE=false
;;
*)
USE_BRIDGE=false
;;
esac
if [[ "${USE_BRIDGE}" == "true" ]]; then
# enter a name for the bridge interface (if no default)
if [ -z "${BRIDGE_INTERFACE}" ]; then
read -p "Enter an alternate name for the bridge interface ( default: hotspot_br0 ): " BRIDGE_INTERFACE
if [ -z "${BRIDGE_INTERFACE}" ]; then
BRIDGE_INTERFACE=hotspot_br0
fi
fi
# interfaces to bridge
while read -p "Enter additional interfaces to bind to bridge (leave blank to continue): " INT && [ ! -z "${INT}" ] ; do
if ip -o l | sed -E 's/^[0-9]+: ([a-zA-Z0-9-]+):.*$/\1/' | grep ${INT} &>/dev/null; then
# interface on host
BR_INTERFACES+="${INT}"
else
# interface not present on host
echo "Interface '${INT}' doesnt exist - try again"
fi
done
fi
fi
echo "Ready to deploy "
cat <<EOF
Creating hotspot:
physical device: ${SRC_DEVICE}
interface: ${HS_INTERFACE}
using bridge: ${USE_BRIDGE}
EOF
if [[ "${USE_BRIDGE,,}" == "true" ]]; then
cat <<EOF
Creating Bridge:
interface: ${BRIDGE_INTERFACE}
slaves interfaces: ${HS_INTERFACE} ${BR_INTERFACES[@]}
EOF
fi
### actual configuration of interfaces ###
# create interface
_debug "making secondary wireless interface after disabling primary"
ip l set down wlan0 2>&1 >&3 || print_err
_pause
iw phy ${SRC_DEVICE} interface add ${HS_INTERFACE} type __ap >&3 || print_err
_pause
_debug "setting to managed mode to get around bug with master mode not being able to set 4addr"
iwconfig ${HS_INTERFACE} mode managed
_pause
_debug "configuring interface to use 4addr settings on wireless"
iw dev ${HS_INTERFACE} set 4addr on >&3 || print_err
_pause
if [[ "${USE_BRIDGE,,}" == "true" ]]; then
_debug "adding bridge interface"
ip l add ${BRIDGE_INTERFACE} type bridge >&3 || print_err
_debug "setting hotspot interface as slave to bridge"
ip l set master ${BRIDGE_INTERFACE} ${HS_INTERFACE} >&3 || print_err
for INT in ${BR_INTERFACES}; do
_debug "setting interface '${INT}' as slave to bridge"
ip l set master ${BRIDGE_INTERFACE} ${INT} >&3 || print_err
done
_debug "bring bridge up"
ip l set up ${DRIDGE_INTERFACE} >&3 || print_err
fi
_debug "compiling configuration file for hostapd"
cat <<EOF > hostapd.conf
interface=${HS_INTERFACE}
driver=nl80211
ssid=${AP_SSID:-cs-2-go}
channel=5
hw_mode=g
wme_enabled=1
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=${AP_PASSWORD:-mypassword}
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
EOF
_debug "Bringing interface ${HS_INTERFACE} up now"
ip l set up dev ${HS_INTERFACE}
_pause
if [[ "${USE_BRIDGE,,}" != "true" ]]; then
_debug "Not using bridge therefore starting instance of dhcp server on interface ${HS_INTERFACE}"
if [ ! -f /etc/dhcp/dhcpd.conf ]; then
_err "not able to find dhcpd configuration in /etc/dhcp/dhcpd.conf - not running dhcp server"
else
_debug "Using current DHCPd configuration in '/etc/dhcp/dhcpd.conf'"
_debug "Setting ip on ${HS_INTERFACE} to match dhcpd configuration"
IP_ADDR=$( grep router /etc/dhcp/dhcpd.conf | sed -E 's/^.*[[:space:]](([0-9]{1,3}.?){4});$/\1/')
if ! echo "${IP_ADDR}" | grep -E '^([0-9]{1,3}.?){4}$' &>/dev/null; then
_err "not able to locate a valid ip for the interface in the dhcpd.conf file - skipping"
else
ip a add ${IP_ADDR}/24 dev ${HS_INTERFACE}
echo "" > /var/lib/dhcp/dhcpd.lease
_pause
_debug "Starting DHCPd server..."
dhcpd -f -cf /etc/dhcp/dhcpd.conf ${HS_INTERFACE} &>"${LOG_DIR}/dhcpd.log" &
PIDS+=($!)
_pause
fi
fi
fi
_debug "Starting hostapd - CTRL+c to exit..."
_pause
hostapd hostapd.conf &>"${LOG_DIR}/hostapd.log" &
PIDS+=($!)
_pause
tail -vf "${LOG_DIR}"/*.log
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment