#!/usr/bin/env python
#@author: Prahlad Yeri
#@description: Small daemon to create a wifi hotspot on linux
#@license: MIT
import sys
import os
import argparse
import cli
import json
import socket
class Proto:
pass
const = Proto()
#global const = Proto() #struct to hold startup parameters
#const.debug = False
#const.verbose = False
#const.command = 'start'
#const.argv = None
stores = Proto() #struct to dump misc variables
stores.running = False
def validate_ip(addr):
try:
socket.inet_aton(addr)
return True # legal
except socket.error:
return False # Not legal
def configure():
global wlan, ppp, IP, Netmask
#CHECK WHETHER WIFI IS SUPPORTED OR NOT
print 'Verifying connections'
wlan=''
ppp=''
s=cli.execute_shell('iwconfig')
if s!=None:
lines = s.splitlines()
#print 'and it is:' + s
for line in lines:
if not line.startswith(' ') and not line.startswith('mon.') and 'IEEE 802.11' in line:
wlan=line.split(' ')[0]
print 'Wifi interface found: ' + wlan
if wlan=='':
print 'Wireless interface could not be found on your device.'
return
#print 'Verifying Internet connections'
s=cli.execute_shell('ifconfig')
lines = s.splitlines()
iface=[]
for line in lines:
if not line.startswith(' ') and not line.startswith(wlan) and not line.startswith('lo') and not line.startswith('mon.') and len(line)>0:
iface.append(line.split(' ')[0])
#print 'f::' + line
if len(iface)==0:
print 'No network nic could be found on your deivce to interface with the LAN'
elif len(iface)==1:
ppp=iface[0]
print 'Network interface found: ' + ppp
else:
rniface=range(len(iface))
s=''
while True:
for i in rniface:
print i, iface[i]
try: s = int(input("Enter number for internet supplying NIC :"))
except: continue
if s not in rniface:
continue
ppp=iface[s]
break
while True:
IP= raw_input('Enter an IP address for your ap [192.168.45.1] :')
#except: continue
#print type(IP)
#sys.exit(0)
if IP==None or IP=='':
IP='192.168.45.1'
if not validate_ip(IP): continue
break
Netmask='255.255.255.0'
#CONFIGURE SSID, PASSWORD, ETC.
SSID=raw_input('Enter SSID [joe_ssid] :')
if SSID=='': SSID='joe_ssid'
password=raw_input('Enter 10 digit password [1234567890] :')
if password=='': password='1234567890'
f = open('run.dat','r')
lout=[]
for line in f.readlines():
lout.append(line.replace('',SSID).replace('',password))
f.close()
f = open('run.conf','w')
f.writelines(lout)
f.close()
print 'created hostapd configuration: run.conf'
dc = {'wlan': wlan, 'inet':ppp, 'ip':IP, 'netmask':Netmask, 'SSID':SSID, 'password':password}
json.dump(dc, open('hotspotd.json','wb'))
print dc
print 'Configuration saved'
#CHECK WIFI DRIVERS AND ISSUE WARNINGS
def check_dependencies():
#CHECK FOR DEPENDENCIES
if len(cli.check_sysfile('hostapd'))==0:
print 'hostapd executable not found. Make sure you have installed hostapd.'
return False
elif len(cli.check_sysfile('dnsmasq'))==0:
print 'dnsmasq executable not found. Make sure you have installed dnsmasq.'
return False
else:
return True
def check_interfaces():
global wlan, ppp
print 'Verifying interfaces'
s=cli.execute_shell('ifconfig')
lines = s.splitlines()
bwlan = False
bppp = False
for line in lines:
if not line.startswith(' ') and len(line)>0:
text=line.split(' ')[0]
if text.startswith(wlan):
bwlan = True
elif text.startswith('ppp0'):
bppp = True
if not bwlan:
print wlan + ' interface was not found. Make sure your wifi is on.'
return False
elif not bppp:
print ppp + ' interface was not found. Make sure you are connected to the internet.'
return False
else:
print 'done.'
return True
def pre_start():
try:
oper = platform.linux_distribution()
if oper[0].lower()=='ubuntu' and oper[2].lower()=='trusty':
#trusty patch
print 'applying hostapd workaround for ubuntu trusty.'
cli.execute_shell('nmcli nm wifi off')
cli.execute_shell('rfkill unblock wlan')
cli.execute_shell('sleep 1')
print 'done.'
except:
pass
def start_router():
if not check_dependencies():
return
elif not check_interfaces():
return
pre_start()
s = 'ifconfig ' + wlan + ' up ' + IP + ' netmask ' + Netmask
print 'created interface: mon.' + wlan + ' on IP: ' + IP
r = cli.execute_shell(s)
cli.writelog(r)
#cli.writelog('sleeping for 2 seconds.')
print 'wait..'
cli.execute_shell('sleep 2')
i = IP.rindex('.')
ipparts=IP[0:i]
#stop dnsmasq if already running.
if cli.is_process_running('dnsmasq')>0:
print 'stopping dnsmasq'
cli.execute_shell('killall dnsmasq')
#stop hostapd if already running.
if cli.is_process_running('hostapd')>0:
print 'stopping hostapd'
cli.execute_shell('killall hostapd')
#enable forwarding in sysctl.
print 'enabling forward in sysctl.'
r=cli.set_sysctl('net.ipv4.ip_forward','1')
print r.strip()
#enable forwarding in iptables.
print 'creating NAT using iptables: ' + wlan + '<->' + ppp
cli.execute_shell('iptables -P FORWARD ACCEPT')
#add iptables rules to create the NAT.
cli.execute_shell('iptables --table nat --delete-chain')
cli.execute_shell('iptables --table nat -F')
r=cli.execute_shell('iptables --table nat -X')
if len(r.strip())>0: print r.strip()
cli.execute_shell('iptables -t nat -A POSTROUTING -o ' + ppp + ' -j MASQUERADE')
cli.execute_shell('iptables -A FORWARD -i ' + ppp + ' -o ' + wlan + ' -j ACCEPT -m state --state RELATED,ESTABLISHED')
cli.execute_shell('iptables -A FORWARD -i ' + wlan + ' -o ' + ppp + ' -j ACCEPT')
#allow traffic to/from wlan
cli.execute_shell('iptables -A OUTPUT --out-interface ' + wlan + ' -j ACCEPT')
cli.execute_shell('iptables -A INPUT --in-interface ' + wlan + ' -j ACCEPT')
#start dnsmasq
s = 'dnsmasq --dhcp-authoritative --interface=' + wlan + ' --dhcp-range=' + ipparts + '.20,' + ipparts +'.100,' + Netmask + ',4h'
print 'running dnsmasq'
r = cli.execute_shell(s)
cli.writelog(r)
#~ f = open(os.getcwd() + '/hostapd.tem','r')
#~ lout=[]
#~ for line in f.readlines():
#~ lout.append(line.replace('',SSID).replace('',password))
#~
#~ f.close()
#~ f = open(os.getcwd() + '/hostapd.conf','w')
#~ f.writelines(lout)
#~ f.close()
#writelog('created: ' + os.getcwd() + '/hostapd.conf')
#start hostapd
#s = 'hostapd -B ' + os.path.abspath('run.conf')
s = 'hostapd -B ' + os.getcwd() + '/run.conf'
cli.writelog('running hostapd')
#cli.writelog('sleeping for 2 seconds.')
cli.writelog('wait..')
cli.execute_shell('sleep 2')
r = cli.execute_shell(s)
cli.writelog(r)
print 'hotspot is running.'
return
def stop_router():
#bring down the interface
cli.execute_shell('ifconfig mon.' + wlan + ' down')
#TODO: Find some workaround. killing hostapd brings down the wlan0 interface in ifconfig.
#~ #stop hostapd
#~ if cli.is_process_running('hostapd')>0:
#~ cli.writelog('stopping hostapd')
#~ cli.execute_shell('pkill hostapd')
#stop dnsmasq
if cli.is_process_running('dnsmasq')>0:
cli.writelog('stopping dnsmasq')
cli.execute_shell('killall dnsmasq')
#disable forwarding in iptables.
cli.writelog('disabling forward rules in iptables.')
cli.execute_shell('iptables -P FORWARD DROP')
#delete iptables rules that were added for wlan traffic.
if wlan != None:
cli.execute_shell('iptables -D OUTPUT --out-interface ' + wlan + ' -j ACCEPT')
cli.execute_shell('iptables -D INPUT --in-interface ' + wlan + ' -j ACCEPT')
cli.execute_shell('iptables --table nat --delete-chain')
cli.execute_shell('iptables --table nat -F')
cli.execute_shell('iptables --table nat -X')
#disable forwarding in sysctl.
cli.writelog('disabling forward in sysctl.')
r = cli.set_sysctl('net.ipv4.ip_forward','0')
print r.strip()
#cli.execute_shell('ifconfig ' + wlan + ' down' + IP + ' netmask ' + Netmask)
#cli.execute_shell('ip addr flush ' + wlan)
print 'hotspot has stopped.'
return
if __name__ == "__main__":
global wlan, ppp, IP, Netmask
#check root or not
if os.getenv('USER') != 'root':
print "You need root permissions to do this, sloth!"
sys.exit(1)
scpath = os.path.realpath(__file__)
realdir = os.path.dirname(scpath)
os.chdir(realdir)
#print 'changed directory to ' + os.path.dirname(scpath)
#if an instance is already running, then quit
parser = argparse.ArgumentParser(description='A small daemon to create a wifi hotspot on linux')
parser.add_argument('-v', '--verbose', required=False, action='store_true')
parser.add_argument('command', choices=['start', 'stop', 'configure'])
args = parser.parse_args()
#const.verbose = args.verbose
#const.command = args.command
#const.blocking = args.blocking
#const.argv = [os.getcwd() + '/server.py'] + sys.argv[1:]
cli.arguments = args #initialize
newconfig = False
if not os.path.exists('hotspotd.json'):
configure()
newconfig=True
dc =json.load(open('hotspotd.json'))
wlan = dc['wlan']
ppp = dc['inet']
IP=dc['ip']
Netmask=dc['netmask']
SSID = dc['SSID']
password = dc['password']
if args.command == 'configure':
if not newconfig: configure()
elif args.command == 'stop':
stop_router()
elif args.command == 'start':
if (cli.is_process_running('hostapd') != 0 and cli.is_process_running('dnsmasq') != 0):
print 'hotspot is already running.'
else:
start_router()