#!/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>',SSID).replace('<PASS>',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>',SSID).replace('<PASS>',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()