Skip to content

Instantly share code, notes, and snippets.

@chrisob
Last active February 6, 2017 09:57
Show Gist options
  • Save chrisob/668b7acef4dfccdce08a to your computer and use it in GitHub Desktop.
Save chrisob/668b7acef4dfccdce08a to your computer and use it in GitHub Desktop.
Automated secure layer 3 tunnel bridge with local wlan access point
interface=wlan0
driver=rtl871xdrv
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=Bridged AP
wpa_passphrase=mywpapassphrasehere
hw_mode=g
channel=1
beacon_int=100
dtim_period=2
max_num_sta=255
rts_threshold=2347
fragm_threshold=2346
macaddr_acl=0
auth_algs=3
ignore_broadcast_ssid=0
wmm_enabled=1
wmm_ac_bk_cwmin=4
wmm_ac_bk_cwmax=10
wmm_ac_bk_aifs=7
wmm_ac_bk_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmin=4
wmm_ac_be_cwmax=10
wmm_ac_be_txop_limit=0
wmm_ac_be_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmin=3
wmm_ac_vi_cwmax=4
wmm_ac_vi_txop_limit=94
wmm_ac_vi_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmin=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_txop_limit=47
wmm_ac_vo_acm=0
eapol_key_index_workaround=0
eap_server=0
own_ip_addr=127.0.0.1
wpa=2
wpa_key_mgmt=WPA-PSK WPA-EAP WPA-PSK-SHA256 WPA-EAP-SHA256
#!/bin/bash
# This script enables a secure layer 3 tunnel to be bridged with a wlan AP:
#
# 1. Establish a level 3 (TAP) tunnel from your local host to a remote server via SSH (tap0)
# 2. Establish a wlan AP via a local wifi enabled device (wlan0)
# 3. Bridge these two devices on the local host, so your wlan uses the remote server as a gateway
# 4. Configure the appropriate addresses, routes, firewall rules, and DNS servers
#
# Initial required setup:
#
# On all hosts:
# -root access
# -iptables and iproute installed
#
# On the remote SSH host:
# -At least OpenSSH server 4.3
# -Your SSH public key is in /root/.ssh/authorized_keys
# -"PermitRootLogin yes" is in /etc/ssh/sshd_config
# -"PermitTunnel yes" is in /etc/ssh/sshd_config
#
# On the local host:
# -At least OpenSSH client 4.3
# -The bridge kernel module loaded
# -dnsmasq is installed
# -hostapd is installed, note: I had to compile a patched version for Realtek devices, please see:
# -http://github.com/pritambaral/hostapd-rtl871xdrv
# -http://w1.fi/hostap.git
# -hostapd configuration file with AP config
# -drivers for your wlan device (you should have a NIC named wlan0)
# -http://github.com/dz0ny/rt8192cu
#
#
# Interfaces:
# tap0 - Level 3 (ethernet) tunnel between local host and remote host (both called tap0)
# wlan0 - Local wlan NIC
# br0 - Local bridge NIC bridging tap0 and usb0
#
# Limitations:
# Only tested with CentOS-6 for both the remote and local hosts.
REMOTE_SSH_IP=1.2.3.4
REMOTE_SSH_PORT=22
SSH_KEY=/root/.ssh/id_rsa
SSH_SOCK=/var/run/ssh_tunnel.sock
SSH_PROXY_COMMAND="none"
SSH_SOCKS_PROXY_PORT=12345
BRIDGE_SUBNET=10.123.123.0
PREFIX=24
REMOTE_GATEWAY=10.123.123.1
LOCAL_BRIDGE_IP=10.123.123.2
DHCP_FROM=10.123.123.3
DHCP_TO=10.123.123.5
DNS1=8.8.8.8
DNS2=8.8.4.4
HOSTAPD='/usr/local/src/hostap/hostapd/hostapd'
HOSTAPD_PID='/var/run/hostapd.pid'
HOSTAPD_CONFIG='/etc/hostapd/hostapd.conf'
DNSMASQ_PID='/var/run/dnsmasq.pid'
REMOTE_UP="
ip addr flush dev tap0
ip addr add ${REMOTE_GATEWAY}/${PREFIX} dev tap0
ip link set tap0 up
iptables -t filter -I FORWARD 1 -i tap0 -s ${BRIDGE_SUBNET}/${PREFIX} -j ACCEPT
iptables -t filter -I INPUT 1 -i tap0 -s ${BRIDGE_SUBNET}/${PREFIX} -j ACCEPT
iptables -t nat -I POSTROUTING 1 -o eth0 -s ${BRIDGE_SUBNET}/${PREFIX} -j MASQUERADE
"
REMOTE_DOWN="
iptables -t filter -D FORWARD -i tap0 -s ${BRIDGE_SUBNET}/${PREFIX} -j ACCEPT
iptables -t filter -D INPUT -i tap0 -s ${BRIDGE_SUBNET}/${PREFIX} -j ACCEPT
iptables -t nat -D POSTROUTING -o eth0 -s ${BRIDGE_SUBNET}/${PREFIX} -j MASQUERADE
"
function usage {
echo -e "Usage:\n$0 {up|down}\n"
}
echo
if [ "$1" == "up" ]; then
echo Checking if local tap0 exists...
ip addr show tap0 &> /dev/null
if [ $? -ne 0 ]; then
echo Creating local and remote tap0...
ssh -f root@"${REMOTE_SSH_IP}" \
-o "Port ${REMOTE_SSH_PORT}" \
-o "IdentityFile ${SSH_KEY}" \
-o "ProxyCommand ${SSH_PROXY_COMMAND}" \
-o "AddressFamily inet" \
-o "DynamicForward 0.0.0.0:${SSH_SOCKS_PROXY_PORT}" \
-o "Tunnel ethernet" \
-o "TunnelDevice 0:0" \
-o "ExitOnForwardFailure yes" \
-o "ServerAliveInterval 60" \
-o "UserKnownHostsFile /dev/null" \
-o "StrictHostKeyChecking no" \
-o "ControlMaster yes" \
-o "ControlPath ${SSH_SOCK}" \
"${REMOTE_UP}"
fi
echo Configuring local br0...
brctl addbr br0
brctl addif br0 tap0
brctl addif br0 wlan0
ip addr flush dev br0
ip addr add "${LOCAL_BRIDGE_IP}/${PREFIX}" dev br0
echo Enabling local br0...
ip link set br0 up
echo Enabling local tap0...
ip link set tap0 up
echo Starting local dnsmasq...
dnsmasq --no-hosts --no-poll --pid-file=${DNSMASQ_PID} --interface=br0 --bogus-priv --filterwin2k --no-resolv --server=${DNS1} --server=${DNS2} --cache-size=1000 --dhcp-option=3,${REMOTE_GATEWAY} --dhcp-option=6,${DNS1} --dhcp-range=${DHCP_FROM},${DHCP_TO} --dhcp-lease-max=253 --dhcp-authoritative --dhcp-leasefile=/tmp/dnsmasq.leases < /dev/null
echo Starting local hostapd...
"${HOSTAPD}" -B -P "${HOSTAPD_PID}" "${HOSTAPD_CONFIG}" > /dev/null
echo Enabling packet forwarding...
sysctl -w net.ipv4.ip_forward=1 > /dev/null
echo Creating local iptables rules...
# For DHCP assignment
iptables -t filter -I INPUT 1 -i br0 -d 255.255.255.255 -j ACCEPT
# Allow packet forwarding out to remote server
iptables -t filter -I FORWARD 1 -i br0 -s ${BRIDGE_SUBNET}/${PREFIX} -j ACCEPT
# Allow usage of socks proxy
iptables -t filter -I INPUT 1 -m state --state NEW -m tcp -p tcp --dport ${SSH_SOCKS_PROXY_PORT} -j ACCEPT
elif [ "$1" == "down" ]; then
echo Checking if local tap0 exists...
ip addr show tap0 &> /dev/null
if [ $? -eq 0 ]; then
echo Disabling local and remote tap0...
ssh -S "${SSH_SOCK}" -O exit does-not-matter-what-goes-here-blaahh &> /dev/null
echo Removing remote iptables rules...
ssh root@"${REMOTE_SSH_IP}" \
-o "Port ${REMOTE_SSH_PORT}" \
-o "IdentityFile ${SSH_KEY}" \
-o "ProxyCommand ${SSH_PROXY_COMMAND}" \
-o "UserKnownHostsFile /dev/null" \
-o "StrictHostKeyChecking no" \
"${REMOTE_DOWN}"
fi
echo Stopping local dnsmasq...
kill $(cat "${DNSMASQ_PID}") > /dev/null
# dnsmasq doesn't automatically clean up its own pid file...
rm -f "${DNSMASQ_PID}"
echo Stopping local hostapd...
kill $(cat "${HOSTAPD_PID}") > /dev/null
echo Disabling local br0...
ip link set br0 down
ip link set wlan0 down
brctl delbr br0
echo Disabling packet forwarding...
sysctl -w net.ipv4.ip_forward=0 > /dev/null
echo Removing local iptables rules...
iptables -t filter -D INPUT -i br0 -d 255.255.255.255 -j ACCEPT
iptables -t filter -D FORWARD -i br0 -s "${BRIDGE_SUBNET}/${PREFIX}" -j ACCEPT
iptables -t filter -D INPUT -m state --state NEW -m tcp -p tcp --dport ${SSH_SOCKS_PROXY_PORT} -j ACCEPT
else
usage
exit 1
fi
echo "Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment