Autosuggestion for network interfaces ips

This commit is contained in:
DomySh
2022-07-20 00:21:22 +02:00
parent da2cebfabd
commit 1266aebe0e
12 changed files with 66 additions and 18 deletions

View File

@@ -11,7 +11,7 @@ from passlib.context import CryptContext
from fastapi_socketio import SocketManager from fastapi_socketio import SocketManager
from modules import SQLite, FirewallManager from modules import SQLite, FirewallManager
from modules.firewall import STATUS from modules.firewall import STATUS
from utils import ip_parse, refactor_name, gen_service_id from utils import get_interfaces, ip_parse, refactor_name, gen_service_id
ON_DOCKER = len(sys.argv) > 1 and sys.argv[1] == "DOCKER" ON_DOCKER = len(sys.argv) > 1 and sys.argv[1] == "DOCKER"
DEBUG = len(sys.argv) > 1 and sys.argv[1] == "DEBUG" DEBUG = len(sys.argv) > 1 and sys.argv[1] == "DEBUG"
@@ -365,6 +365,15 @@ async def add_new_service(form: ServiceAddForm, auth: bool = Depends(is_loggined
await refresh_frontend() await refresh_frontend()
return {'status': 'ok', 'service_id': srv_id} return {'status': 'ok', 'service_id': srv_id}
class IpInterface(BaseModel):
addr: str
name: str
@app.get('/api/interfaces', response_model=List[IpInterface])
async def get_ip_interfaces(auth: bool = Depends(is_loggined)):
"""Get a list of ip and ip6 interfaces"""
return get_interfaces()
async def frontend_debug_proxy(path): async def frontend_debug_proxy(path):
httpc = httpx.AsyncClient() httpc = httpx.AsyncClient()
req = httpc.build_request("GET",f"http://127.0.0.1:{os.getenv('F_PORT','3000')}/"+path) req = httpc.build_request("GET",f"http://127.0.0.1:{os.getenv('F_PORT','3000')}/"+path)

View File

@@ -2,6 +2,7 @@ fastapi[all]
httpx httpx
uvicorn[standard] uvicorn[standard]
passlib[bcrypt] passlib[bcrypt]
psutil
python-jose[cryptography] python-jose[cryptography]
fastapi-socketio fastapi-socketio
git+https://salsa.debian.org/pkg-netfilter-team/pkg-nftables#egg=nftables&subdirectory=py git+https://salsa.debian.org/pkg-netfilter-team/pkg-nftables#egg=nftables&subdirectory=py

View File

@@ -1,5 +1,5 @@
from ipaddress import ip_interface from ipaddress import ip_interface
import os, socket, secrets import os, socket, secrets, psutil
LOCALHOST_IP = socket.gethostbyname(os.getenv("LOCALHOST_IP","127.0.0.1")) LOCALHOST_IP = socket.gethostbyname(os.getenv("LOCALHOST_IP","127.0.0.1"))
@@ -19,4 +19,12 @@ def ip_parse(ip:str):
return str(ip_interface(ip).network) return str(ip_interface(ip).network)
def ip_family(ip:str): def ip_family(ip:str):
return "ip6" if ip_interface(ip).version == 6 else "ip" return "ip6" if ip_interface(ip).version == 6 else "ip"
def get_interfaces():
def _get_interfaces():
for int_name, interfs in psutil.net_if_addrs().items():
for interf in interfs:
if interf.family in [socket.AF_INET, socket.AF_INET6]:
yield {"name": int_name, "addr":interf.address}
return list(_get_interfaces())

View File

@@ -1,13 +1,13 @@
{ {
"files": { "files": {
"main.css": "/static/css/main.08225a85.css", "main.css": "/static/css/main.08225a85.css",
"main.js": "/static/js/main.6bded0d7.js", "main.js": "/static/js/main.10378d73.js",
"index.html": "/index.html", "index.html": "/index.html",
"main.08225a85.css.map": "/static/css/main.08225a85.css.map", "main.08225a85.css.map": "/static/css/main.08225a85.css.map",
"main.6bded0d7.js.map": "/static/js/main.6bded0d7.js.map" "main.10378d73.js.map": "/static/js/main.10378d73.js.map"
}, },
"entrypoints": [ "entrypoints": [
"static/css/main.08225a85.css", "static/css/main.08225a85.css",
"static/js/main.6bded0d7.js" "static/js/main.10378d73.js"
] ]
} }

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="manifest" href="/site.webmanifest"><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#FFFFFFFF"/><meta name="description" content="Firegex by Pwnzer0tt1"/><title>Firegex</title><script defer="defer" src="/static/js/main.6bded0d7.js"></script><link href="/static/css/main.08225a85.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html> <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="manifest" href="/site.webmanifest"><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#FFFFFFFF"/><meta name="description" content="Firegex by Pwnzer0tt1"/><title>Firegex</title><script defer="defer" src="/static/js/main.10378d73.js"></script><link href="/static/css/main.08225a85.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
import { Button, Group, NumberInput, Space, TextInput, Notification, Modal, Switch, SegmentedControl } from '@mantine/core'; import { Button, Group, NumberInput, Space, TextInput, Notification, Modal, Switch, SegmentedControl, SelectItemProps, Autocomplete, AutocompleteItem } from '@mantine/core';
import { useForm } from '@mantine/hooks'; import { useForm } from '@mantine/hooks';
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import { addservice, okNotify, startservice, regex_ipv4, regex_ipv6 } from '../js/utils'; import { addservice, okNotify, startservice, regex_ipv4, regex_ipv6, getipinterfaces } from '../js/utils';
import { ImCross } from "react-icons/im" import { ImCross } from "react-icons/im"
type ServiceAddForm = { type ServiceAddForm = {
@@ -12,13 +12,23 @@ type ServiceAddForm = {
autostart: boolean, autostart: boolean,
} }
interface ItemProps extends AutocompleteItem {
label: string;
}
const AutoCompleteItem = React.forwardRef<HTMLDivElement, ItemProps>(
({ label, value, ...props }: ItemProps, ref) => <div ref={ref} {...props}>
( <b>{label}</b> ) -{">"} <b>{value}</b>
</div>
);
function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) { function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) {
const form = useForm({ const form = useForm({
initialValues: { initialValues: {
name:"", name:"",
port:8080, port:8080,
ip_int:"127.0.0.1", ip_int:"",
proto:"tcp", proto:"tcp",
autostart: true autostart: true
}, },
@@ -30,6 +40,14 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
} }
}) })
const [ipInterfaces, setIpInterfaces] = useState<AutocompleteItem[]>([]);
useEffect(()=>{
getipinterfaces().then(data => {
setIpInterfaces(data.map(item => ({label:item.name, value:item.addr})));
})
},[])
const close = () =>{ const close = () =>{
onClose() onClose()
form.reset() form.reset()
@@ -55,7 +73,8 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
setSubmitLoading(false) setSubmitLoading(false)
setError("Request Failed! [ "+err+" ]") setError("Request Failed! [ "+err+" ]")
}) })
} }
return <Modal size="xl" title="Add a new service" opened={opened} onClose={close} closeOnClickOutside={false} centered> return <Modal size="xl" title="Add a new service" opened={opened} onClose={close} closeOnClickOutside={false} centered>
<form onSubmit={form.onSubmit(submitRequest)}> <form onSubmit={form.onSubmit(submitRequest)}>
@@ -66,9 +85,11 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void })
/> />
<Space h="md" /> <Space h="md" />
<TextInput <Autocomplete
label="Public IP Interface (ipv4/ipv6 + CIDR allowed)" label="Public IP Interface (ipv4/ipv6 + CIDR allowed)"
placeholder="10.1.1.0/24" placeholder="10.1.1.0/24"
itemComponent={AutoCompleteItem}
data={ipInterfaces}
{...form.getInputProps('ip_int')} {...form.getInputProps('ip_int')}
/> />

View File

@@ -74,4 +74,9 @@ export type RegexAddForm = {
is_blacklist:boolean, is_blacklist:boolean,
mode:string, // C->S S->C BOTH, mode:string, // C->S S->C BOTH,
active: boolean active: boolean
}
export type IpInterface = {
name:string,
addr:string
} }

View File

@@ -1,7 +1,7 @@
import { showNotification } from "@mantine/notifications"; import { showNotification } from "@mantine/notifications";
import { ImCross } from "react-icons/im"; import { ImCross } from "react-icons/im";
import { TiTick } from "react-icons/ti" import { TiTick } from "react-icons/ti"
import { GeneralStats, Service, ServiceAddForm, ServerResponse, RegexFilter, RegexAddForm, ServerStatusResponse, PasswordSend, ChangePassword, LoginResponse, ServerResponseToken, ServiceAddResponse } from "./models"; import { GeneralStats, Service, ServiceAddForm, ServerResponse, RegexFilter, RegexAddForm, ServerStatusResponse, PasswordSend, ChangePassword, LoginResponse, ServerResponseToken, ServiceAddResponse, IpInterface } from "./models";
var Buffer = require('buffer').Buffer var Buffer = require('buffer').Buffer
@@ -54,6 +54,10 @@ export function fireUpdateRequest(){
window.dispatchEvent(new Event(eventUpdateName)) window.dispatchEvent(new Event(eventUpdateName))
} }
export async function getipinterfaces(){
return await getapi("interfaces") as IpInterface[];
}
export async function getstatus(){ export async function getstatus(){
return await getapi(`status`) as ServerStatusResponse; return await getapi(`status`) as ServerStatusResponse;
} }