mirror of
https://github.com/RaspAP/raspap-webgui.git
synced 2024-11-22 07:30:23 +00:00
initial install test
This commit is contained in:
parent
ce63e48445
commit
2ce8351b1a
17 changed files with 767 additions and 0 deletions
20
api/auth.py
Normal file
20
api/auth.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
import os
|
||||
from fastapi.security.api_key import APIKeyHeader
|
||||
from fastapi import Security, HTTPException
|
||||
from starlette.status import HTTP_403_FORBIDDEN
|
||||
|
||||
apikey=os.getenv('RASPAP_API_KEY')
|
||||
#if env not set, set the api key to "insecure"
|
||||
if apikey == None:
|
||||
apikey = "insecure"
|
||||
|
||||
print(apikey)
|
||||
api_key_header = APIKeyHeader(name="access_token", auto_error=False)
|
||||
|
||||
async def get_api_key(api_key_header: str = Security(api_key_header)):
|
||||
if api_key_header ==apikey:
|
||||
return api_key_header
|
||||
else:
|
||||
raise HTTPException(
|
||||
status_code=HTTP_403_FORBIDDEN, detail="403: Unauthorized"
|
||||
)
|
229
api/main.py
Normal file
229
api/main.py
Normal file
|
@ -0,0 +1,229 @@
|
|||
from fastapi import FastAPI, Depends
|
||||
from fastapi.security.api_key import APIKey
|
||||
import auth
|
||||
|
||||
import json
|
||||
|
||||
import modules.system as system
|
||||
import modules.ap as ap
|
||||
import modules.client as client
|
||||
import modules.dns as dns
|
||||
import modules.dhcp as dhcp
|
||||
import modules.ddns as ddns
|
||||
import modules.firewall as firewall
|
||||
import modules.networking as networking
|
||||
import modules.openvpn as openvpn
|
||||
import modules.wireguard as wireguard
|
||||
import modules.restart as restart
|
||||
|
||||
|
||||
tags_metadata = [
|
||||
{
|
||||
"name": "system",
|
||||
"description": "All information regarding the underlying system."
|
||||
},
|
||||
{
|
||||
"name": "accesspoint/hostpost",
|
||||
"description": "Get and change all information regarding the hotspot"
|
||||
}
|
||||
]
|
||||
app = FastAPI(
|
||||
title="API for Raspap",
|
||||
openapi_tags=tags_metadata,
|
||||
version="0.0.1",
|
||||
license_info={
|
||||
"name": "Apache 2.0",
|
||||
"url": "https://www.apache.org/licenses/LICENSE-2.0.html",
|
||||
}
|
||||
)
|
||||
|
||||
@app.get("/system", tags=["system"])
|
||||
async def get_system():
|
||||
return{
|
||||
'hostname': system.hostname(),
|
||||
'uptime': system.uptime(),
|
||||
'systime': system.systime(),
|
||||
'usedMemory': system.usedMemory(),
|
||||
'processorCount': system.processorCount(),
|
||||
'LoadAvg1Min': system.LoadAvg1Min(),
|
||||
'systemLoadPercentage': system.systemLoadPercentage(),
|
||||
'systemTemperature': system.systemTemperature(),
|
||||
'hostapdStatus': system.hostapdStatus(),
|
||||
'operatingSystem': system.operatingSystem(),
|
||||
'kernelVersion': system.kernelVersion(),
|
||||
'rpiRevision': system.rpiRevision()
|
||||
}
|
||||
|
||||
@app.get("/ap", tags=["accesspoint/hostpost"])
|
||||
async def get_ap():
|
||||
return{
|
||||
'driver': ap.driver(),
|
||||
'ctrl_interface': ap.ctrl_interface(),
|
||||
'ctrl_interface_group': ap.ctrl_interface_group(),
|
||||
'auth_algs': ap.auth_algs(),
|
||||
'wpa_key_mgmt': ap.wpa_key_mgmt(),
|
||||
'beacon_int': ap.beacon_int(),
|
||||
'ssid': ap.ssid(),
|
||||
'channel': ap.channel(),
|
||||
'hw_mode': ap.hw_mode(),
|
||||
'ieee80211n': ap.ieee80211n(),
|
||||
'wpa_passphrase': ap.wpa_passphrase(),
|
||||
'interface': ap.interface(),
|
||||
'wpa': ap.wpa(),
|
||||
'wpa_pairwise': ap.wpa_pairwise(),
|
||||
'country_code': ap.country_code(),
|
||||
'ignore_broadcast_ssid': ap.ignore_broadcast_ssid()
|
||||
}
|
||||
|
||||
@app.post("/ap", tags=["accesspoint/hostpost"])
|
||||
async def post_ap(driver=None,
|
||||
ctrl_interface=None,
|
||||
ctrl_interface_group=None,
|
||||
auth_algs=None,
|
||||
wpa_key_mgmt=None,
|
||||
beacon_int=None,
|
||||
ssid=None,
|
||||
channel=None,
|
||||
hw_mode=None,
|
||||
ieee80211n=None,
|
||||
wpa_passphrase=None,
|
||||
interface=None,
|
||||
wpa=None,
|
||||
wpa_pairwise=None,
|
||||
country_code=None,
|
||||
ignore_broadcast_ssid=None,
|
||||
api_key: APIKey = Depends(auth.get_api_key)):
|
||||
if driver != None:
|
||||
ap.set_driver(driver)
|
||||
if ctrl_interface != None:
|
||||
ap.set_ctrl_interface(ctrl_interface)
|
||||
if ctrl_interface_group !=None:
|
||||
ap.set_ctrl_interface_group(ctrl_interface_group)
|
||||
if auth_algs != None:
|
||||
ap.set_auth_algs(auth_algs)
|
||||
if wpa_key_mgmt != None:
|
||||
ap.set_wpa_key_mgmt(wpa_key_mgmt)
|
||||
if beacon_int != None:
|
||||
ap.set_beacon_int(beacon_int)
|
||||
if ssid != None:
|
||||
ap.set_ssid(ssid)
|
||||
if channel != None:
|
||||
ap.set_channel(channel)
|
||||
if hw_mode != None:
|
||||
ap.set_hw_mode(hw_mode)
|
||||
if ieee80211n != None:
|
||||
ap.set_ieee80211n(ieee80211n)
|
||||
if wpa_passphrase != None:
|
||||
ap.set_wpa_passphrase(wpa_passphrase)
|
||||
if interface != None:
|
||||
ap.set_interface(interface)
|
||||
if wpa != None:
|
||||
ap.set_wpa(wpa)
|
||||
if wpa_pairwise != None:
|
||||
ap.set_wpa_pairwise(wpa_pairwise)
|
||||
if country_code != None:
|
||||
ap.set_country_code(country_code)
|
||||
if ignore_broadcast_ssid != None:
|
||||
ap.set_ignore_broadcast_ssid(ignore_broadcast_ssid)
|
||||
|
||||
|
||||
@app.get("/clients/{wireless_interface}", tags=["Clients"])
|
||||
async def get_clients(wireless_interface):
|
||||
return{
|
||||
'active_clients_amount': client.get_active_clients_amount(wireless_interface),
|
||||
'active_clients': json.loads(client.get_active_clients(wireless_interface))
|
||||
}
|
||||
|
||||
@app.get("/dhcp", tags=["DHCP"])
|
||||
async def get_dhcp():
|
||||
return{
|
||||
'range_start': dhcp.range_start(),
|
||||
'range_end': dhcp.range_end(),
|
||||
'range_subnet_mask': dhcp.range_subnet_mask(),
|
||||
'range_lease_time': dhcp.range_lease_time(),
|
||||
'range_gateway': dhcp.range_gateway(),
|
||||
'range_nameservers': dhcp.range_nameservers()
|
||||
}
|
||||
|
||||
@app.get("/dns/domains", tags=["DNS"])
|
||||
async def get_domains():
|
||||
return{
|
||||
'domains': json.loads(dns.adblockdomains())
|
||||
}
|
||||
@app.get("/dns/hostnames", tags=["DNS"])
|
||||
async def get_hostnames():
|
||||
return{
|
||||
'hostnames': json.loads(dns.adblockhostnames())
|
||||
}
|
||||
|
||||
@app.get("/dns/upstream", tags=["DNS"])
|
||||
async def get_upstream():
|
||||
return{
|
||||
'upstream_nameserver': dns.upstream_nameserver()
|
||||
}
|
||||
|
||||
@app.get("/dns/logs", tags=["DNS"])
|
||||
async def get_dnsmasq_logs():
|
||||
return(dns.dnsmasq_logs())
|
||||
|
||||
|
||||
@app.get("/ddns", tags=["DDNS"])
|
||||
async def get_ddns():
|
||||
return{
|
||||
'use': ddns.use(),
|
||||
'method': ddns.method(),
|
||||
'protocol': ddns.protocol(),
|
||||
'server': ddns.server(),
|
||||
'login': ddns.login(),
|
||||
'password': ddns.password(),
|
||||
'domain': ddns.domain()
|
||||
}
|
||||
|
||||
@app.get("/firewall", tags=["Firewall"])
|
||||
async def get_firewall():
|
||||
return json.loads(firewall.firewall_rules())
|
||||
|
||||
@app.get("/networking", tags=["Networking"])
|
||||
async def get_networking():
|
||||
return{
|
||||
'interfaces': json.loads(networking.interfaces()),
|
||||
'throughput': json.loads(networking.throughput())
|
||||
}
|
||||
|
||||
@app.get("/openvpn", tags=["OpenVPN"])
|
||||
async def get_openvpn():
|
||||
return{
|
||||
'client_configs': openvpn.client_configs(),
|
||||
'client_config_names': openvpn.client_config_names(),
|
||||
'client_config_active': openvpn.client_config_active(),
|
||||
'client_login_names': openvpn.client_login_names(),
|
||||
'client_login_active': openvpn.client_login_active()
|
||||
}
|
||||
|
||||
@app.get("/openvpn/{config}", tags=["OpenVPN"])
|
||||
async def client_config_list(config):
|
||||
return{
|
||||
'client_config': openvpn.client_config_list(config)
|
||||
}
|
||||
|
||||
@app.get("/wireguard", tags=["WireGuard"])
|
||||
async def get_wireguard():
|
||||
return{
|
||||
'client_configs': wireguard.configs(),
|
||||
'client_config_names': wireguard.client_config_names(),
|
||||
'client_config_active': wireguard.client_config_active()
|
||||
}
|
||||
|
||||
@app.get("/wireguard/{config}", tags=["WireGuard"])
|
||||
async def client_config_list(config):
|
||||
return{
|
||||
'client_config': wireguard.client_config_list(config)
|
||||
}
|
||||
|
||||
@app.post("/restart/webgui")
|
||||
async def restart_webgui():
|
||||
restart.webgui()
|
||||
|
||||
@app.post("/restart/adblock")
|
||||
async def restart_adblock():
|
||||
restart.adblock()
|
112
api/modules/ap.py
Normal file
112
api/modules/ap.py
Normal file
|
@ -0,0 +1,112 @@
|
|||
import subprocess
|
||||
import json
|
||||
|
||||
def driver():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep driver= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_driver(driver):
|
||||
return subprocess.run(f"sudo sed -i 's/^driver=.*/driver={driver}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def ctrl_interface():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep ctrl_interface= | cut -d'=' -f2 | head -1", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_ctrl_interface(ctrl_interface):
|
||||
return subprocess.run(f"sudo sed -i 's/^ctrl_interface=.*/ctrl_interface={ctrl_interface}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def ctrl_interface_group():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep ctrl_interface_group= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_ctrl_interface_group(ctrl_interface_group):
|
||||
return subprocess.run(f"sudo sed -i 's/^ctrl_interface_group=.*/ctrl_interface_group={ctrl_interface_group}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def auth_algs():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep auth_algs= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_auth_algs(auth_algs):
|
||||
return subprocess.run(f"sudo sed -i 's/^auth_algs=.*/auth_algs={auth_algs}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def wpa_key_mgmt():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep wpa_key_mgmt= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_wpa_key_mgmt(wpa_key_mgmt):
|
||||
return subprocess.run(f"sudo sed -i 's/^wpa_key_mgmt=.*/wpa_key_mgmt={wpa_key_mgmt}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def beacon_int():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep beacon_int= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_beacon_int(beacon_int):
|
||||
return subprocess.run(f"sudo sed -i 's/^beacon_int=.*/beacon_int={beacon_int}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def ssid():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep ssid= | cut -d'=' -f2 | head -1", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_ssid(ssid):
|
||||
return subprocess.run(f"sudo sed -i 's/^ssid=.*/ssid={ssid}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def channel():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep channel= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_channel(channel):
|
||||
return subprocess.run(f"sudo sed -i 's/^channel=.*/channel={channel}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def hw_mode():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep hw_mode= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_hw_mode(hw_mode):
|
||||
return subprocess.run(f"sudo sed -i 's/^hw_mode=.*/hw_mode={hw_mode}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def ieee80211n():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep ieee80211n= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_ieee80211n(ieee80211n):
|
||||
return subprocess.run(f"sudo sed -i 's/^ieee80211n=.*/ieee80211n={ieee80211n}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def wpa_passphrase():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep wpa_passphrase= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_wpa_passphrase(wpa_passphrase):
|
||||
return subprocess.run(f"sudo sed -i 's/^wpa_passphrase=.*/wpa_passphrase={wpa_passphrase}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def interface():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep interface= | cut -d'=' -f2 | head -1", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_interface(interface):
|
||||
return subprocess.run(f"sudo sed -i 's/^interface=.*/interface={interface}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def wpa():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep wpa= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_wpa(wpa):
|
||||
return subprocess.run(f"sudo sed -i 's/^wpa=.*/wpa={wpa}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def wpa_pairwise():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep wpa_pairwise= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_wpa_pairwise(wpa_pairwise):
|
||||
return subprocess.run(f"sudo sed -i 's/^wpa_pairwise=.*/wpa_pairwise={wpa_pairwise}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def country_code():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep country_code= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_country_code(country_code):
|
||||
return subprocess.run(f"sudo sed -i 's/^country_code=.*/country_code={country_code}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def ignore_broadcast_ssid():
|
||||
return subprocess.run("cat /etc/hostapd/hostapd.conf | grep ignore_broadcast_ssid= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def set_ignore_broadcast_ssid(ignore_broadcast_ssid):
|
||||
return subprocess.run(f"sudo sed -i 's/^ignore_broadcast_ssid=.*/ignore_broadcast_ssid={ignore_broadcast_ssid}/' /etc/hostapd/hostapd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def logging():
|
||||
log_output = subprocess.run(f"cat /tmp/hostapd.log", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
logs = {}
|
||||
|
||||
for line in log_output.split('\n'):
|
||||
parts = line.split(': ')
|
||||
if len(parts) >= 2:
|
||||
interface, message = parts[0], parts[1]
|
||||
if interface not in logs:
|
||||
logs[interface] = []
|
||||
logs[interface].append(message)
|
||||
|
||||
return json.dumps(logs, indent=2)
|
28
api/modules/client.py
Normal file
28
api/modules/client.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
import subprocess
|
||||
import json
|
||||
|
||||
def get_active_clients_amount(interface):
|
||||
output = subprocess.run(f'''cat '/var/lib/misc/dnsmasq.leases' | grep -iwE "$(arp -i '{interface}' | grep -oE "(([0-9]|[a-f]|[A-F]){{{2}}}:){{{5}}}([0-9]|[a-f]|[A-F]){{{2}}}")"''', shell=True, capture_output=True, text=True)
|
||||
return(len(output.stdout.splitlines()))
|
||||
|
||||
def get_active_clients(interface):
|
||||
#does not run like intended, but it works....
|
||||
output = subprocess.run(f'''cat '/var/lib/misc/dnsmasq.leases' | grep -iwE "$(arp -i '{interface}' | grep -oE "(([0-9]|[a-f]|[A-F]){{{2}}}:){{{5}}}([0-9]|[a-f]|[A-F]){{{2}}}")"''', shell=True, capture_output=True, text=True)
|
||||
clients_list = []
|
||||
|
||||
for line in output.stdout.splitlines():
|
||||
fields = line.split()
|
||||
|
||||
client_data = {
|
||||
"timestamp": int(fields[0]),
|
||||
"mac_address": fields[1],
|
||||
"ip_address": fields[2],
|
||||
"hostname": fields[3],
|
||||
"client_id": fields[4],
|
||||
}
|
||||
|
||||
clients_list.append(client_data)
|
||||
|
||||
json_output = json.dumps(clients_list, indent=2)
|
||||
|
||||
return json_output
|
24
api/modules/ddns.py
Normal file
24
api/modules/ddns.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
import subprocess
|
||||
|
||||
def use():
|
||||
return subprocess.run("cat /etc/ddclient.conf | grep use= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def method():
|
||||
#get the contents of the line below "use="
|
||||
return subprocess.run("awk '/^use=/ {getline; print}' /etc/ddclient.conf | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def protocol():
|
||||
return subprocess.run("cat /etc/ddclient.conf | grep protocol= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def server():
|
||||
return subprocess.run("cat /etc/ddclient.conf | grep server= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def login():
|
||||
return subprocess.run("cat /etc/ddclient.conf | grep login= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def password():
|
||||
return subprocess.run("cat /etc/ddclient.conf | grep password= | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def domain():
|
||||
#get the contents of the line below "password="
|
||||
return subprocess.run("awk '/^password=/ {getline; print}' /etc/ddclient.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
30
api/modules/dhcp.py
Normal file
30
api/modules/dhcp.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
import subprocess
|
||||
import json
|
||||
|
||||
def range_start():
|
||||
return subprocess.run("cat /etc/dnsmasq.d/090_wlan0.conf |grep dhcp-range= |cut -d'=' -f2| cut -d',' -f1", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def range_end():
|
||||
return subprocess.run("cat /etc/dnsmasq.d/090_wlan0.conf |grep dhcp-range= |cut -d'=' -f2| cut -d',' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def range_subnet_mask():
|
||||
return subprocess.run("cat /etc/dnsmasq.d/090_wlan0.conf |grep dhcp-range= |cut -d'=' -f2| cut -d',' -f3", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def range_lease_time():
|
||||
return subprocess.run("cat /etc/dnsmasq.d/090_wlan0.conf |grep dhcp-range= |cut -d'=' -f2| cut -d',' -f4", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def range_gateway():
|
||||
return subprocess.run("cat /etc/dhcpcd.conf | grep routers | cut -d'=' -f2", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def range_nameservers():
|
||||
output = subprocess.run("cat /etc/dhcpcd.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
nameservers = []
|
||||
|
||||
lines = output.split('\n')
|
||||
for line in lines:
|
||||
if "static domain_name_server" in line:
|
||||
servers = line.split('=')[1].strip().split()
|
||||
nameservers.extend(servers)
|
||||
|
||||
return nameservers
|
38
api/modules/dns.py
Normal file
38
api/modules/dns.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
import subprocess
|
||||
import json
|
||||
|
||||
def adblockdomains():
|
||||
output = subprocess.run("cat /etc/raspap/adblock/domains.txt", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
domains =output.split('\n')
|
||||
domainlist=[]
|
||||
for domain in domains:
|
||||
if domain.startswith('#') or domain=="":
|
||||
continue
|
||||
domainlist.append(domain.split('=/')[1])
|
||||
return domainlist
|
||||
|
||||
def adblockhostnames():
|
||||
output = subprocess.run("cat /etc/raspap/adblock/hostnames.txt", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
hostnames = output.split('\n')
|
||||
hostnamelist=[]
|
||||
for hostname in hostnames:
|
||||
if hostname.startswith('#') or hostname=="":
|
||||
continue
|
||||
hostnamelist.append(hostname.replace('0.0.0.0 ',''))
|
||||
return hostnamelist
|
||||
|
||||
def upstream_nameserver():
|
||||
return subprocess.run("awk '/nameserver/ {print $2}' /run/dnsmasq/resolv.conf", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def dnsmasq_logs():
|
||||
output = subprocess.run("cat /var/log/dnsmasq.log", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
log_entries = []
|
||||
for line in output.split("\n"):
|
||||
fields = line.split(" ")
|
||||
log_dict = {
|
||||
'timestamp': ' '.join(fields[:3]),
|
||||
'process': fields[3][:-1], # Remove the trailing colon
|
||||
'message': ' '.join(fields[4:]),
|
||||
}
|
||||
log_entries.append(log_dict)
|
||||
return log_entries
|
4
api/modules/firewall.py
Normal file
4
api/modules/firewall.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
import subprocess
|
||||
|
||||
def firewall_rules():
|
||||
return subprocess.run("cat /etc/raspap/networking/firewall/iptables_rules.json", shell=True, capture_output=True, text=True).stdout.strip()
|
68
api/modules/networking.py
Normal file
68
api/modules/networking.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
import psutil
|
||||
import json
|
||||
|
||||
def throughput():
|
||||
interface_info = {}
|
||||
|
||||
# Get network interfaces
|
||||
interfaces = psutil.net_if_stats()
|
||||
|
||||
for interface, stats in interfaces.items():
|
||||
if interface.startswith("lo") or interface.startswith("docker"):
|
||||
# Skip loopback and docker interface
|
||||
continue
|
||||
|
||||
try:
|
||||
# Get network traffic statistics
|
||||
traffic_stats = psutil.net_io_counters(pernic=True)[interface]
|
||||
rx_packets = traffic_stats[1]
|
||||
rx_bytes = traffic_stats[0]
|
||||
tx_packets = traffic_stats[3]
|
||||
tx_bytes = traffic_stats[4]
|
||||
|
||||
interface_info[interface] = {
|
||||
"RX_packets": rx_packets,
|
||||
"RX_bytes": rx_bytes,
|
||||
"TX_packets": tx_packets,
|
||||
"TX_bytes": tx_bytes
|
||||
}
|
||||
except KeyError:
|
||||
# Handle the case where network interface statistics are not available
|
||||
pass
|
||||
|
||||
return json.dumps(interface_info, indent=2)
|
||||
|
||||
def interfaces():
|
||||
interface_info = {}
|
||||
|
||||
# Get network interfaces
|
||||
interfaces = psutil.net_if_addrs()
|
||||
|
||||
for interface, addrs in interfaces.items():
|
||||
if interface.startswith("lo") or interface.startswith("docker"):
|
||||
# Skip loopback and docker interface
|
||||
continue
|
||||
|
||||
ip_address = None
|
||||
netmask = None
|
||||
mac_address = None
|
||||
|
||||
for addr in addrs:
|
||||
if addr.family == 2: # AF_INET corresponds to the integer value 2
|
||||
# IPv4 address
|
||||
ip_address = addr.address
|
||||
netmask = addr.netmask
|
||||
|
||||
# Get MAC address
|
||||
for addr in psutil.net_if_addrs().get(interface, []):
|
||||
if addr.family == psutil.AF_LINK:
|
||||
mac_address = addr.address
|
||||
|
||||
interface_info[interface] = {
|
||||
"IP_address": ip_address,
|
||||
"Netmask": netmask,
|
||||
"MAC_address": mac_address
|
||||
}
|
||||
return json.dumps(interface_info, indent=2)
|
||||
|
||||
#TODO: migrate to vnstat, to lose psutil dependency
|
41
api/modules/openvpn.py
Normal file
41
api/modules/openvpn.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
import subprocess
|
||||
|
||||
def client_configs():
|
||||
return subprocess.run("find /etc/openvpn/client/ -type f | wc -l", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def client_config_names():
|
||||
config_names_list = []
|
||||
output = subprocess.run('''ls /etc/openvpn/client/ | grep -v "^client.conf$"''', shell=True, capture_output=True, text=True).stdout.strip()
|
||||
lines = output.split("\n")
|
||||
for client in lines:
|
||||
if "_client" in client:
|
||||
config_names_dict ={'config':client}
|
||||
config_names_list.append(config_names_dict)
|
||||
return config_names_list
|
||||
|
||||
def client_login_names():
|
||||
config_names_list = []
|
||||
output = subprocess.run('''ls /etc/openvpn/client/ | grep -v "^client.conf$"''', shell=True, capture_output=True, text=True).stdout.strip()
|
||||
lines = output.split("\n")
|
||||
for client in lines:
|
||||
if "_login" in client:
|
||||
config_names_dict ={'login':client}
|
||||
config_names_list.append(config_names_dict)
|
||||
return config_names_list
|
||||
|
||||
def client_config_active():
|
||||
output = subprocess.run('''ls -al /etc/openvpn/client/ | grep "client.conf -"''', shell=True, capture_output=True, text=True).stdout.strip()
|
||||
active_config = output.split("/etc/openvpn/client/")
|
||||
return(active_config[1])
|
||||
|
||||
def client_login_active():
|
||||
output = subprocess.run('''ls -al /etc/openvpn/client/ | grep "login.conf -"''', shell=True, capture_output=True, text=True).stdout.strip()
|
||||
active_config = output.split("/etc/openvpn/client/")
|
||||
return(active_config[1])
|
||||
|
||||
def client_config_list(client_config):
|
||||
output = subprocess.run(f"cat /etc/openvpn/client/{client_config}", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
return output.split('\n')
|
||||
|
||||
#TODO: where is the logfile??
|
||||
#TODO: is service connected?
|
7
api/modules/restart.py
Normal file
7
api/modules/restart.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
import subprocess
|
||||
|
||||
def webgui():
|
||||
return subprocess.run("sudo /etc/raspap/lighttpd/configport.sh --restart", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def adblock():
|
||||
return subprocess.run("sudo /bin/systemctl restart dnsmasq.service", shell=True, capture_output=True, text=True).stdout.strip()
|
86
api/modules/system.py
Normal file
86
api/modules/system.py
Normal file
|
@ -0,0 +1,86 @@
|
|||
import subprocess
|
||||
|
||||
revisions = {
|
||||
'0002': 'Model B Revision 1.0',
|
||||
'0003': 'Model B Revision 1.0 + ECN0001',
|
||||
'0004': 'Model B Revision 2.0 (256 MB)',
|
||||
'0005': 'Model B Revision 2.0 (256 MB)',
|
||||
'0006': 'Model B Revision 2.0 (256 MB)',
|
||||
'0007': 'Model A',
|
||||
'0008': 'Model A',
|
||||
'0009': 'Model A',
|
||||
'000d': 'Model B Revision 2.0 (512 MB)',
|
||||
'000e': 'Model B Revision 2.0 (512 MB)',
|
||||
'000f': 'Model B Revision 2.0 (512 MB)',
|
||||
'0010': 'Model B+',
|
||||
'0013': 'Model B+',
|
||||
'0011': 'Compute Module',
|
||||
'0012': 'Model A+',
|
||||
'a01041': 'a01041',
|
||||
'a21041': 'a21041',
|
||||
'900092': 'PiZero 1.2',
|
||||
'900093': 'PiZero 1.3',
|
||||
'9000c1': 'PiZero W',
|
||||
'a02082': 'Pi 3 Model B',
|
||||
'a22082': 'Pi 3 Model B',
|
||||
'a32082': 'Pi 3 Model B',
|
||||
'a52082': 'Pi 3 Model B',
|
||||
'a020d3': 'Pi 3 Model B+',
|
||||
'a220a0': 'Compute Module 3',
|
||||
'a020a0': 'Compute Module 3',
|
||||
'a02100': 'Compute Module 3+',
|
||||
'a03111': 'Model 4B Revision 1.1 (1 GB)',
|
||||
'b03111': 'Model 4B Revision 1.1 (2 GB)',
|
||||
'c03111': 'Model 4B Revision 1.1 (4 GB)',
|
||||
'c03111': 'Model 4B Revision 1.1 (4 GB)',
|
||||
'a03140': 'Compute Module 4 (1 GB)',
|
||||
'b03140': 'Compute Module 4 (2 GB)',
|
||||
'c03140': 'Compute Module 4 (4 GB)',
|
||||
'd03140': 'Compute Module 4 (8 GB)',
|
||||
'c04170': 'Pi 5 (4 GB)',
|
||||
'd04170': 'Pi 5 (8 GB)'
|
||||
}
|
||||
|
||||
def hostname():
|
||||
return subprocess.run("hostname", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def uptime():
|
||||
return subprocess.run("uptime -p", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def systime():
|
||||
return subprocess.run("date", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def usedMemory():
|
||||
return round(float(subprocess.run("free -m | awk 'NR==2{total=$2 ; used=$3 } END { print used/total*100}'", shell=True, capture_output=True, text=True).stdout.strip()),2)
|
||||
|
||||
def processorCount():
|
||||
return int(subprocess.run("nproc --all", shell=True, capture_output=True, text=True).stdout.strip())
|
||||
|
||||
def LoadAvg1Min():
|
||||
return round(float(subprocess.run("awk '{print $1}' /proc/loadavg", shell=True, capture_output=True, text=True).stdout.strip()),2)
|
||||
|
||||
def systemLoadPercentage():
|
||||
return round((float(LoadAvg1Min())*100)/float(processorCount()),2)
|
||||
|
||||
def systemTemperature():
|
||||
try:
|
||||
output = subprocess.run("cat /sys/class/thermal/thermal_zone0/temp", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
return round(float(output)/1000,2)
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
def hostapdStatus():
|
||||
return int(subprocess.run("pidof hostapd | wc -l", shell=True, capture_output=True, text=True).stdout.strip())
|
||||
|
||||
def operatingSystem():
|
||||
return subprocess.run('''grep PRETTY_NAME /etc/os-release | cut -d= -f2- | sed 's/"//g' ''', shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def kernelVersion():
|
||||
return subprocess.run("uname -r", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def rpiRevision():
|
||||
output = subprocess.run("grep Revision /proc/cpuinfo | awk '{print $3}'", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
try:
|
||||
return revisions[output]
|
||||
except KeyError:
|
||||
return 'Unknown Device'
|
26
api/modules/wireguard.py
Normal file
26
api/modules/wireguard.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import subprocess
|
||||
|
||||
def configs():
|
||||
#ignore symlinks, because wg0.conf is in production the main config, but in insiders it is a symlink
|
||||
return subprocess.run("find /etc/wireguard/ -type f | wc -l", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
|
||||
def client_config_names():
|
||||
config_names_list = []
|
||||
output = subprocess.run('''ls /etc/wireguard/ | grep -v "^wg0.conf$"''', shell=True, capture_output=True, text=True).stdout.strip()
|
||||
lines = output.split("\n")
|
||||
for client in lines:
|
||||
config_names_dict ={'config':client}
|
||||
config_names_list.append(config_names_dict)
|
||||
return config_names_list
|
||||
|
||||
def client_config_active():
|
||||
output = subprocess.run('''ls -al /etc/wireguard/ | grep "wg0.conf -"''', shell=True, capture_output=True, text=True).stdout.strip()
|
||||
active_config = output.split("/etc/wireguard/")
|
||||
return(active_config[1])
|
||||
|
||||
def client_config_list(client_config):
|
||||
output = subprocess.run(f"cat /etc/wireguard/{client_config}", shell=True, capture_output=True, text=True).stdout.strip()
|
||||
return output.split('\n')
|
||||
|
||||
#TODO: where is the logfile??
|
||||
#TODO: is service connected?
|
3
api/requirements.txt
Normal file
3
api/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
fastapi==0.109.0
|
||||
uvicorn==0.25.0
|
||||
psutil==5.9.8
|
|
@ -57,6 +57,7 @@ function _install_raspap() {
|
|||
_configure_networking
|
||||
_prompt_install_adblock
|
||||
_prompt_install_openvpn
|
||||
_prompt_isntall_restapi
|
||||
_install_extra_features
|
||||
_prompt_install_wireguard
|
||||
_prompt_install_vpn_providers
|
||||
|
@ -502,6 +503,23 @@ function _prompt_install_openvpn() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Prompt to install restapi
|
||||
function _prompt_install_restapi() {
|
||||
_install_log "Configure restapi"
|
||||
echo -n "Install and enable RestAPI? [Y/n]: "
|
||||
if [ "$assume_yes" == 0 ]; then
|
||||
read answer < /dev/tty
|
||||
if [ "$answer" != "${answer#[Nn]}" ]; then
|
||||
_install_status 0 "(Skipped)"
|
||||
else
|
||||
_install_restapi
|
||||
elif [ "$restapi_option" == 1 ]; then
|
||||
_install_restapi
|
||||
else
|
||||
echo "(Skipped)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Prompt to install WireGuard
|
||||
function _prompt_install_wireguard() {
|
||||
_install_log "Configure WireGuard support"
|
||||
|
@ -562,6 +580,20 @@ function _create_openvpn_scripts() {
|
|||
_install_status 0
|
||||
}
|
||||
|
||||
# Install and enable RestAPI configuration option
|
||||
function _install_restapi() {
|
||||
_install_log "Installing and enabling RestAPI"
|
||||
sudo cp -r "$webroot_dir/api" "$raspap_dir/api" || _install_status 1 "Unable to move api folder"
|
||||
python -m pip install -r "$raspap_dir/api/requirements.txt" || _install_status 1 " Unable to install pip modules"
|
||||
|
||||
echo "Moving restapi systemd unit control file to /lib/systemd/system/"
|
||||
sudo mv $webroot_dir/installers/restapi.service /lib/systemd/system/ || _install_status 1 "Unable to move restapi.service file"
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable restapi.service || _install_status 1 "Failed to enable restapi.service"
|
||||
|
||||
_install_status 0
|
||||
}
|
||||
|
||||
# Fetches latest files from github to webroot
|
||||
function _download_latest_files() {
|
||||
_install_log "Cloning latest files from GitHub"
|
||||
|
|
|
@ -94,6 +94,7 @@ function _parse_params() {
|
|||
upgrade=0
|
||||
update=0
|
||||
ovpn_option=1
|
||||
restapi_option=0
|
||||
adblock_option=1
|
||||
wg_option=1
|
||||
insiders=0
|
||||
|
@ -111,6 +112,10 @@ function _parse_params() {
|
|||
ovpn_option="$2"
|
||||
shift
|
||||
;;
|
||||
--api|--rest|--restapi)
|
||||
restapi_option="$2"
|
||||
shift
|
||||
;;
|
||||
-a|--adblock)
|
||||
adblock_option="$2"
|
||||
shift
|
||||
|
|
14
installers/restapi.service
Normal file
14
installers/restapi.service
Normal file
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=raspap-restapi
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=root
|
||||
WorkingDirectory=/etc/raspap/api
|
||||
LimitNOFILE=4096
|
||||
ExecStart=/usr/bin/python uvicorn main:app --host 0.0.0.0 --port 8081
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
Loading…
Reference in a new issue