mirror of
https://github.com/billz/raspap-webgui.git
synced 2025-03-01 10:31:47 +00:00
initial install test
This commit is contained in:
parent
ce63e48445
commit
2ce8351b1a
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
|
_configure_networking
|
||||||
_prompt_install_adblock
|
_prompt_install_adblock
|
||||||
_prompt_install_openvpn
|
_prompt_install_openvpn
|
||||||
|
_prompt_isntall_restapi
|
||||||
_install_extra_features
|
_install_extra_features
|
||||||
_prompt_install_wireguard
|
_prompt_install_wireguard
|
||||||
_prompt_install_vpn_providers
|
_prompt_install_vpn_providers
|
||||||
@ -502,6 +503,23 @@ function _prompt_install_openvpn() {
|
|||||||
fi
|
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
|
# Prompt to install WireGuard
|
||||||
function _prompt_install_wireguard() {
|
function _prompt_install_wireguard() {
|
||||||
_install_log "Configure WireGuard support"
|
_install_log "Configure WireGuard support"
|
||||||
@ -562,6 +580,20 @@ function _create_openvpn_scripts() {
|
|||||||
_install_status 0
|
_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
|
# Fetches latest files from github to webroot
|
||||||
function _download_latest_files() {
|
function _download_latest_files() {
|
||||||
_install_log "Cloning latest files from GitHub"
|
_install_log "Cloning latest files from GitHub"
|
||||||
|
@ -94,6 +94,7 @@ function _parse_params() {
|
|||||||
upgrade=0
|
upgrade=0
|
||||||
update=0
|
update=0
|
||||||
ovpn_option=1
|
ovpn_option=1
|
||||||
|
restapi_option=0
|
||||||
adblock_option=1
|
adblock_option=1
|
||||||
wg_option=1
|
wg_option=1
|
||||||
insiders=0
|
insiders=0
|
||||||
@ -111,6 +112,10 @@ function _parse_params() {
|
|||||||
ovpn_option="$2"
|
ovpn_option="$2"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--api|--rest|--restapi)
|
||||||
|
restapi_option="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-a|--adblock)
|
-a|--adblock)
|
||||||
adblock_option="$2"
|
adblock_option="$2"
|
||||||
shift
|
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…
x
Reference in New Issue
Block a user