Last active
February 6, 2017 09:57
-
-
Save chrisob/668b7acef4dfccdce08a to your computer and use it in GitHub Desktop.
Automated secure layer 3 tunnel bridge with local wlan access point
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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