aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorache <ache@ache.one>2021-05-05 15:23:38 +0200
committerache <ache@ache.one>2021-05-05 15:23:38 +0200
commit88a3ef76d8a6bdbab39ac0745ca22f4ef65e286b (patch)
treea9a080db3aef92f113d2ac089f02a27f3acd4763
parentChoose interface internet (diff)
Better DHCP
-rwxr-xr-xautoDHCP.py285
1 files changed, 285 insertions, 0 deletions
diff --git a/autoDHCP.py b/autoDHCP.py
new file mode 100755
index 0000000..ce699c4
--- /dev/null
+++ b/autoDHCP.py
@@ -0,0 +1,285 @@
+#!/bin/env python
+
+import sys
+import ipaddress
+import argparse
+import os
+from os.path import exists
+import subprocess
+import tempfile
+
+
+def guess_wifi():
+ return [interface for interface in os.listdir('/sys/class/net/') if
+ exists(f'/sys/class/net/{interface}/wireless')]
+
+
+def guess_nowifi():
+ return [interface for interface in os.listdir('/sys/class/net/') if
+ not exists(f'/sys/class/net/{interface}/wireless')]
+
+
+def guess_interface():
+ return [interface for interface in os.listdir('/sys/class/net/')]
+
+
+def guess_internet():
+ com = subprocess.Popen(['ip', 'route', 'show'], stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ stdout, stderr = com.communicate()
+ if stderr:
+ return []
+ print(str(stdout).split('\n'))
+
+ internet_i = [line for line in
+ [stripedLine(line) for line in str(stdout).split('\n') if
+ 'default' in line]
+ if line != '']
+
+ return list(set(internet_i))
+
+
+def stripedLine(line):
+ words = line.split(' ')
+ if 'dev' in words and words.index('dev'):
+ return words[words.index('dev') + 1]
+ else:
+ return ''
+
+
+def menu(listEntry, strInput, refresh=None):
+ if listEntry == []:
+ print(f"Error menu: Empty list\n({strInput})", file=sys.stderr)
+ exit(1)
+ c = -1
+ if len(listEntry) == 1:
+ c = 0
+ while not (0 < c <= len(listEntry)):
+ for i, ii in enumerate(listEntry):
+ print(f" {i + 1}) {ii}")
+ r = input(f'{strInput} '
+ f'(q to quit{ ", r to refresh" if refresh else ""}) :')
+ if refresh and r == 'r':
+ listEntry = refresh()
+ elif r.lower() in ['q', 'quit']:
+ exit(0)
+ else:
+ try:
+ c = int(r)
+ except:
+ pass
+ return c - 1
+
+
+ip = '10.5.6.11'
+netRange = '24'
+ssid = '🦄_🌈'
+password = 'chocoball'
+
+hostapd_conf = '''
+interface={interface}
+ssid={ssid}
+wpa_passphrase={passphrase}
+wpa=1
+
+channel=11
+hw_mode=g
+
+# ieee80211d=1
+# country_code=FR
+ieee80211n=1
+# ieee80211ac=1
+
+logger_syslog=-1
+logger_syslog_level=2
+logger_stdout=-1
+logger_stdout_level=2
+
+ctrl_interface=/var/run/hostapd
+ctrl_interface_group=0
+
+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
+
+wpa_key_mgmt=WPA-PSK
+rsn_pairwise=CCMP
+wpa=2
+
+vht_oper_chwidth=3
+eap_message=hello
+eapol_key_index_workaround=0
+eap_server=0
+'''
+
+dnsmasq_conf = '''
+interface={interface}
+listen-address={ip}
+dhcp-range={dhcp_range}
+'''
+
+# dhcp_range=$(echo ${ip_start}{$ip_start_tmp\,,254}),12h
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Automaticaly set up a DHCP server')
+ parser.add_argument('--ip', dest='ip', default=ip, help='IP on the DHCP network')
+ parser.add_argument('-r', '--range', dest='range', default=netRange,
+ help='number of bit of the IP that are part of the '
+ 'network address')
+ parser.add_argument('-s', '--ssid', dest='ssid', default=ssid, help='Wifi\'s "name"')
+ parser.add_argument('--password', dest='passwd', default=password,
+ help='the password of the Wifi network if any')
+ parser.add_argument('--no-password', dest='nopass', action='store_true',
+ help='disable password')
+ parser.add_argument('-t', '--tethering', dest='teth', action='store_true',
+ help='configure tethering on the DHCP network')
+ parser.add_argument('-w', '--wifi', dest='wifi', action='store_true',
+ help='DHCP on a wifi interface')
+ parser.add_argument('--no-wifi', dest='nowifi', action='store_true',
+ help='DHCP not on a wifi interface')
+ parser.add_argument('-in', '--inet-iface', dest='internet_interface',
+ help='the internet interface to use when tethering')
+ parser.add_argument('-i', '--iface', dest='interface',
+ help='DHCP network\'s interface')
+
+ arg = parser.parse_args()
+
+ if arg.wifi and arg.nowifi:
+ print('Wifi or not Wifi, that is the question', file=sys.stderr)
+ exit(1)
+ ip = ipaddress.ip_address(arg.ip)
+
+ inetInt = arg.internet_interface
+ netInt = arg.interface
+
+ if arg.teth:
+ if not arg.internet_interface:
+ inet_int = guess_internet()
+ i = menu(inet_int, "Select the internet network interface", refresh=guess_internet)
+ inetInt = inet_int[i]
+
+ interfaces_list = []
+ refresh = None
+
+ if arg.wifi:
+ refresh = guess_wifi
+ elif arg.nowifi:
+ refresh = guess_nowifi
+ else:
+ refresh = guess_interface
+
+ interfaces_list = refresh()
+
+ if not netInt:
+ c = menu(interfaces_list, "Select the DHCP network's interface", refresh)
+ netInt = interfaces_list[c]
+ else:
+ if netInt not in interfaces_list:
+ if arg.wifi:
+ print(f"{netInt} not a valid wifi interface", file=sys.stderr)
+ exit(2)
+ elif arg.nowifi:
+ if netInt in guess_interface():
+ print(f'Warning: {netInt} is a wifi interface')
+ else:
+ print(f"{netInt} not a valid interface", file=sys.stderr)
+ exit(2)
+ else:
+ print(f"{netInt} not a valid interface", file=sys.stderr)
+ exit(2)
+
+ os.system(f'ip link set {netInt} up')
+ os.system(f'ip addr add {ip}/{netRange} dev {netInt}')
+
+ fd, dnsConfPath = tempfile.mkstemp(dir="/tmp/")
+ f_, pidPath = tempfile.mkstemp(dir="/tmp/")
+ os.close(f_)
+
+ with os.fdopen(fd, 'w') as tmp:
+ network = ipaddress.ip_network(f'{ip}/{netRange}', strict=False)
+ nextIp = ipaddress.ip_address(int(ip) + 1)
+ lastIp = ipaddress.ip_address(int(network.broadcast_address) - 1)
+
+ if nextIp >= lastIp:
+ print('Error: Empty DHCP range', file=sys.stderr)
+ exit(3)
+
+ dhcp_range = f'{nextIp}, {lastIp}, 12h'
+ tmp.write(dnsmasq_conf.format(interface=netInt, ip=ip,
+ dhcp_range=dhcp_range))
+
+ print("🔧 - Setting up dns server", f"Range : {dhcp_range}",
+ f"Server IP: {ip}", sep='\n')
+ ret = os.system(f'dnsmasq --conf-file={dnsConfPath} --pid-file={pidPath}')
+ os.remove(dnsConfPath)
+ pid = None
+ with open(pidPath, "r") as f:
+ pid = f.read().strip()
+ os.remove(pidPath)
+
+ if ret:
+ print('Error: dnsmasq failed to launch', file=sys.stderr)
+ exit(1)
+ else:
+ print(f'✅ dnsmasq launch with pid ({pid})')
+
+ if arg.teth:
+ os.system('sysctl net.ipv4.ip_forward=1')
+ os.system(f'iptables -t nat -A POSTROUTING -o {inetInt} -j MASQUERADE')
+ os.system('iptables -A FORWARD -m conntrack --ctstate'
+ ' RELATED,ESTABLISHED -j ACCEPT')
+ os.system(f'iptables -A FORWARD -i {netInt} -o {inetInt} -j ACCEPT')
+ print("Tethering set")
+
+ if arg.wifi:
+ fd2, hostAPConfPath = tempfile.mkstemp(dir="/tmp/")
+
+ with os.fdopen(fd2, 'w') as tmp:
+ tmp.write(hostapd_conf.format(ssid=arg.ssid,
+ interface=netInt,
+ passphrase=arg.passwd))
+
+ print("⚙️ - Setting up hostapd", f"SSID: {ssid}",
+ f"Password: {arg.passwd}", f"Interface: {netInt}",
+ sep='\n')
+ ret = os.system(f'hostapd {hostAPConfPath}')
+ if ret:
+ print('Error: hostapd failed to launch', file=sys.stderr)
+ if pid is not None:
+ os.system(f'kill {pid}')
+ exit(1)
+
+ if pid is not None:
+ print(" 🤖 - Terminating DHCP server")
+ ret = os.system(f'kill {pid}')
+ print("✅ Hasta la vista, baby")
+
+ print("Thant you for using autoDHCP ! 💋 ")
+