create_ap/create_ap

302 lines
8.0 KiB
Plaintext
Raw Normal View History

2013-06-20 13:09:04 +01:00
#!/bin/bash
# dependencies:
# bash (to run this script)
# util-linux (for getopt)
# hostapd
# iproute2
# haveged (optional)
# dnsmasq (needed for 'nat' or 'none' Internet sharing method)
# iptables (needed for 'nat' Internet sharing method)
# bridge-utils (needed for 'bridge' Internet sharing method)
# dhclient (needed for 'bridge' Internet sharing method)
2013-06-20 13:09:04 +01:00
usage() {
2013-11-17 13:43:32 +02:00
echo "Usage: $(basename $0) [options] <wifi-interface> [<interface-with-internet>] [<access-point-name> [<passphrase>]]"
2013-06-20 13:09:04 +01:00
echo
echo "Options:"
echo " -h, --help Show this help"
echo " -c <channel> Channel number (default: 1)"
echo " -w <WPA version> Use 1 for WPA, use 2 for WPA2, use 1+2 for both (default: 1+2)"
echo " -n Disable Internet sharing (if you use this, don't pass"
echo " the <interface-with-internet> argument)"
echo " -m <method> Method for Internet sharing."
echo " Use: 'nat' for NAT (default)"
echo " 'bridge' for bridging"
echo " 'none' for no Internet sharing (equivalent to -n)"
2013-09-14 18:06:29 +02:00
echo " --hidden Make the Access Point hidden (do not broadcast the SSID)"
2013-06-20 13:09:04 +01:00
echo
echo "Non-Bridging Options:"
echo " -g <gateway> IPv4 Gateway for the Access Point (default: 192.168.12.1)"
echo " -d DNS server will take into account /etc/hosts"
echo
echo "Examples:"
2013-06-20 13:09:04 +01:00
echo " $(basename $0) wlan0 eth0 MyAccessPoint MyPassPhrase"
echo " $(basename $0) -n wlan0 MyAccessPoint MyPassPhrase"
echo " $(basename $0) -m bridge wlan0 eth0 MyAccessPoint MyPassPhrase"
echo " echo -e 'MyAccessPoint\nMyPassPhrase' | $(basename $0) wlan0 eth0"
2013-06-20 13:09:04 +01:00
}
get_macaddr() {
ip link show "$1" | grep ether | grep -Eo '([0-9a-f]{2}:){5}[0-9a-f]{2}\s'
}
get_avail_bridge() {
for i in {1..100}; do
curr_bridge=$(brctl show | grep "br$i" | cut -s -f1)
if [[ -z $curr_bridge ]]; then
echo "br$i"
return
fi
done
2013-06-20 13:09:04 +01:00
}
ARGS=$(getopt -o hc:w:g:dnm: -l "help","hidden" -n $(basename $0) -- "$@")
2013-06-20 13:09:04 +01:00
[[ $? -ne 0 ]] && exit 1
eval set -- "$ARGS"
CHANNEL=1
GATEWAY=192.168.12.1
WPA_VERSION=1+2
ETC_HOSTS=0
2013-09-14 18:06:29 +02:00
HIDDEN=0
SHARE_METHOD=nat
2013-06-20 13:09:04 +01:00
while :; do
case "$1" in
2013-11-17 03:31:15 +02:00
-h|--help)
usage
exit 1
;;
--hidden)
shift
HIDDEN=1
;;
-c)
shift
CHANNEL="$1"
shift
2013-11-17 03:31:15 +02:00
;;
-w)
shift
WPA_VERSION="$1"
shift
2013-11-17 03:31:15 +02:00
;;
-g)
shift
GATEWAY="$1"
shift
2013-11-17 03:31:15 +02:00
;;
-d)
shift
ETC_HOSTS=1
;;
-n)
shift
SHARE_METHOD=none
;;
-m)
shift
SHARE_METHOD="$1"
shift
2013-11-17 03:31:15 +02:00
;;
--)
shift
break
;;
2013-06-20 13:09:04 +01:00
esac
done
if [[ $# -lt 1 ]]; then
usage
exit 1
fi
if [[ $(id -u) -ne 0 ]]; then
echo "You must run it as root."
exit 1
fi
if [[ "$SHARE_METHOD" != "nat" && "$SHARE_METHOD" != "bridge" && "$SHARE_METHOD" != "none" ]]; then
echo "ERROR: Wrong Internet sharing method"
echo
usage
exit 1
fi
WIFI_IFACE=$1
if [[ "$SHARE_METHOD" == "bridge" ]]; then
BRIDGE_IFACE=$(get_avail_bridge)
if [[ -z $BRIDGE_IFACE ]]; then
echo "ERROR: No availabe bridges < br100"
exit 1
fi
fi
if [[ "$SHARE_METHOD" != "none" ]]; then
MIN_REQUIRED_ARGS=2
else
MIN_REQUIRED_ARGS=1
fi
if [[ $# -gt $MIN_REQUIRED_ARGS ]]; then
if [[ "$SHARE_METHOD" != "none" ]]; then
if [[ $# -ne 3 && $# -ne 4 ]]; then
usage
exit 1
fi
INTERNET_IFACE=$2
SSID=$3
PASSPHRASE=$4
else
if [[ $# -ne 2 && $# -ne 3 ]]; then
usage
exit 1
fi
SSID=$2
PASSPHRASE=$3
fi
else
if [[ "$SHARE_METHOD" != "none" ]]; then
if [[ $# -ne 2 ]]; then
usage
exit 1
fi
INTERNET_IFACE=$2
fi
if tty -s; then
read -p "SSID: " SSID
2013-11-17 23:28:10 +02:00
while :; do
read -p "Passphrase: " -s PASSPHRASE
echo
read -p "Retype passphrase: " -s PASSPHRASE2
echo
if [[ "$PASSPHRASE" != "$PASSPHRASE2" ]]; then
echo "Passphrases do not match."
else
break
fi
done
else
read SSID
read PASSPHRASE
fi
2013-06-20 13:09:04 +01:00
fi
CONFDIR=$(mktemp -d /tmp/create_ap.${WIFI_IFACE}.conf.XXXXXXXX)
echo "Config dir: $CONFDIR"
[[ $HIDDEN -eq 1 ]] && echo "Access Point's SSID is hidden!"
2013-06-20 13:09:04 +01:00
# hostapd config
cat << EOF > $CONFDIR/hostapd.conf
ssid=${SSID}
interface=${WIFI_IFACE}
driver=nl80211
hw_mode=g
channel=${CHANNEL}
ctrl_interface=$CONFDIR/hostapd_ctrl
ctrl_interface_group=0
2013-09-14 18:06:29 +02:00
ignore_broadcast_ssid=$HIDDEN
2013-06-20 13:09:04 +01:00
EOF
if [[ -n "$PASSPHRASE" ]]; then
[[ "$WPA_VERSION" == "1+2" || "$WPA_VERSION" == "2+1" ]] && WPA_VERSION=3
cat << EOF >> $CONFDIR/hostapd.conf
wpa=${WPA_VERSION}
wpa_passphrase=$PASSPHRASE
2013-06-20 13:09:04 +01:00
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
EOF
fi
if [[ "$SHARE_METHOD" == "bridge" ]]; then
echo "bridge=${BRIDGE_IFACE}" >> $CONFDIR/hostapd.conf
else
# dnsmasq config (dhcp + dns)
cat << EOF > $CONFDIR/dnsmasq.conf
2013-06-20 13:09:04 +01:00
interface=${WIFI_IFACE}
bind-interfaces
dhcp-range=${GATEWAY%.*}.1,${GATEWAY%.*}.254,255.255.255.0,24h
dhcp-option=option:router,${GATEWAY}
EOF
[[ $ETC_HOSTS -eq 0 ]] && echo no-hosts >> $CONFDIR/dnsmasq.conf
fi
2013-06-20 13:09:04 +01:00
# setup WiFi interface
2013-06-20 13:09:04 +01:00
ip link set down dev ${WIFI_IFACE}
ip addr flush ${WIFI_IFACE}
if [[ "$SHARE_METHOD" != "bridge" ]]; then
ip link set up dev ${WIFI_IFACE}
ip addr add ${GATEWAY}/24 dev ${WIFI_IFACE}
fi
# enable Internet sharing
if [[ "$SHARE_METHOD" != "none" ]]; then
echo "Sharing Internet using method: $SHARE_METHOD"
if [[ "$SHARE_METHOD" == "nat" ]]; then
iptables -t nat -A POSTROUTING -o ${INTERNET_IFACE} -j MASQUERADE
iptables -A FORWARD -i ${WIFI_IFACE} -j ACCEPT
OLD_IP_FORWARD=$(cat /proc/sys/net/ipv4/ip_forward)
echo 1 > /proc/sys/net/ipv4/ip_forward
elif [[ "$SHARE_METHOD" == "bridge" ]]; then
brctl addbr ${BRIDGE_IFACE}
brctl addif ${BRIDGE_IFACE} ${INTERNET_IFACE}
dhclient -pf $CONFDIR/dhclient.pid ${BRIDGE_IFACE}
fi
else
echo "No Internet sharing"
fi
2013-06-20 13:09:04 +01:00
# boost low-entropy
if [[ $(cat /proc/sys/kernel/random/entropy_avail) -lt 1000 ]]; then
which haveged > /dev/null 2>&1 && {
2013-11-17 03:31:15 +02:00
haveged -w 1024 -p $CONFDIR/haveged.pid
2013-06-20 13:09:04 +01:00
}
fi
# start dns + dhcp server
if [[ "$SHARE_METHOD" != "bridge" ]]; then
dnsmasq -C $CONFDIR/dnsmasq.conf -x $CONFDIR/dnsmasq.pid
fi
2013-06-20 13:09:04 +01:00
# start access point
echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl"
hostapd $CONFDIR/hostapd.conf || {
echo
echo "Hostapd failed to run, maybe a program is interfering."
echo "If you use NetworkManager then add the following in"
echo "/etc/NetworkManager/NetworkManager.conf and retry."
echo "Don't forget to remove it after you finish."
echo
echo "[keyfile]"
echo "unmanaged-devices=mac:$(get_macaddr "$WIFI_IFACE")"
echo
}
echo
echo "Doing cleanup..."
2013-06-20 13:09:04 +01:00
# exiting
for x in $CONFDIR/*.pid; do
# even if the $CONFDIR is empty, the for loop will assign
# a value in $x. so we need to check if the value is a file
[[ -f $x ]] && kill -9 $(cat $x)
2013-06-20 13:09:04 +01:00
done
rm -rf $CONFDIR
if [[ "$SHARE_METHOD" != "none" ]]; then
if [[ "$SHARE_METHOD" == "nat" ]]; then
iptables -t nat -D POSTROUTING -o ${INTERNET_IFACE} -j MASQUERADE
iptables -D FORWARD -i ${WIFI_IFACE} -j ACCEPT
echo $OLD_IP_FORWARD > /proc/sys/net/ipv4/ip_forward
elif [[ "$SHARE_METHOD" == "bridge" ]]; then
ip link set down $BRIDGE_IFACE
brctl delbr $BRIDGE_IFACE
fi
fi
2013-06-20 13:09:04 +01:00
ip link set down dev ${WIFI_IFACE}
ip addr flush ${WIFI_IFACE}
exit 0