Restructuring docker project

This commit is contained in:
DomySh
2022-06-12 22:28:16 +02:00
parent 67e5014d78
commit cff484a976
58 changed files with 357 additions and 407 deletions

26
.dockerignore Executable file
View File

@@ -0,0 +1,26 @@
Dockerfile
docker-compose.yml
**/*.pyc
**/__pycache__/
/.vscode/
#Node filters
/frontend/node_modules
# testing
/frontend/coverage
# production
/frontend/build
# misc
**/.DS_Store
**/.env.local
**/.env.development.local
**/.env.test.local
**/npm-debug.log*
**/yarn-debug.log*
**/yarn-error.log*

4
.gitignore vendored
View File

@@ -7,10 +7,10 @@
**/.pnp.js
# testing
/firewall/frontend/coverage
/frontend/coverage
# production
/firewall/frontend/build
/frontend/build
# misc
**/.DS_Store

View File

@@ -1,30 +1,35 @@
#Frontend build
FROM node:16-alpine AS frontend
FROM node:lts-alpine AS frontend
RUN apk add --update npm
RUN npm install -g npm@latest
RUN mkdir /app
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
ADD ./frontend/package.json .
ADD ./frontend/package-lock.json .
RUN npm install
RUN npm ci --silent
COPY ./frontend/ .
RUN npm run build
#Building main conteiner
FROM python:3-buster
FROM python:slim-buster
RUN apt-get update && apt-get -y install supervisor build-essential libboost-dev nginx
RUN apt-get update && apt-get -y install curl supervisor gettext-base build-essential libboost-dev nginx
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash
RUN apt-get install nodejs
RUN npm install serve -g --silent
RUN mkdir /execute
WORKDIR /execute
ADD ./requirements.txt /execute/requirements.txt
ADD ./backend/requirements.txt /execute/requirements.txt
RUN pip install --no-cache-dir -r /execute/requirements.txt
COPY . /execute/
COPY ./config/nginx.conf /etc/nginx/nginx.conf
COPY ./backend/ /execute/
COPY ./config/supervisord.conf /etc/supervisor/supervisord.conf
COPY ./config/nginx.conf /tmp/nginx.conf
COPY ./config/start_nginx.sh /tmp/start_nginx.sh
#Copy react app in the main container
COPY --from=frontend /app/build/ ./frontend/

201
README.md
View File

@@ -1 +1,200 @@
# firegex
# **WORK IN PROGRESS**
# Firegex-API Documentation
### This is a short description of the API
## TODO
1. custom windows docker-compose
2. fix glich change page with loading screen
3. Instant refresh after an add or delete
4. backend checks and errors
5. frontend requests on buttons
6. frontend messages on success and some failure
7. back and frontend password
8. volume on the database
9. compile c++ -O3
#
# Documentation
## Index
- [General stats](#get-apigeneral-stats)
- [List services](#get-apiservices)
- [Service info](#get-apiserviceserv)
- [Stop service](#get-apiserviceservstop)
- [Start service](#get-apiserviceservstart)
- [Delete service](#get-apiserviceservdelete)
- [Terminate service](#get-apiserviceservterminate)
- [Regenerate public port](#get-apiserviceservregen-port)
- [Service regexes](#get-apiserviceservregexes)
- [Regex info](#get-apiregexregexid)
- [Delete regex](#get-apiregexregexiddelete)
- [Add regex](#post-apiregexesadd)
- [Add service](#post-apiservicesadd)
#
#
## **GET** **```/api/general-stats```**
### Server response:
```json
{
"services": <total number of services>,
"closed": <total number of rejected packets>,
"regex": <total number of regexes>
}
```
#
## **GET** **```/api/services```**
### Server response:
```json
[
{
"id": <service_id>,
"status": <service status>,
"public_port": <public port>,
"internal_port": <internal port>,
"n_packets": <number of rejected packets>,
"n_regex": <number of regexes>
},
{
// Another service
}
]
```
#
## **GET** **```/api/service/<serv>```**
### Server response:
```json
{
"id": <service_id>,
"status": <service status>,
"public_port": <public port>,
"internal_port": <internal port>,
"n_packets": <number of rejected packets>,
"n_regex": <number of regexes>
}
```
#
## **GET** **```/api/service/<serv>/stop```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/start```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/delete```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/terminate```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/regen-port```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/regexes```**
### Server response:
```json
[
{
"id": <regex id>,
"service_id": <service_id>,
"regex": <base64 encoded regex>,
"is_blacklist": <true|false>,
"n_packets": <number of blocked packets>,
"mode": <"C"|"S"|"B"> // Client to server, server to client or both
},
{
// Another regex
}
]
```
#
## **GET** **```/api/regex/<regex_id>```**
### Server response:
```json
{
"id": <regex id>,
"service_id": <service_id>,
"regex": <base64 encoded regex>,
"is_blacklist": <true|false>,
"n_packets": <number of blocked packets>,
"mode" <"C"|"S"|"B"> // Client to server, server to client or both
}
```
#
## **GET** **```/api/regex/<regex_id>/delete```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **POST** **```/api/regexes/add```**
### Client request:
```json
{
"service_id": <service_id>,
"regex": <base64 encoded regex>,
"is_blacklist": <true|false>,
"mode": <"C"|"S"|"B"> // Client to server, server to client or both
}
```
### Server response:
```json
{
"status": "ok"
}
```
#
## **POST** **```/api/services/add```**
### Client request:
```json
{
"name": <the id used to identify the service>,
"port": <the internal port>
}
```
### Server response:
```json
{
"status": "ok"
}
```

View File

@@ -1,5 +1,5 @@
import sqlite3, random, string, subprocess
from flask import Flask, jsonify, request
from flask import Flask, jsonify, request, abort
class SQLite():
@@ -68,7 +68,7 @@ def get_services():
res = []
for i in db.query('SELECT * FROM services;'):
n_regex = db.query('SELECT COUNT (*) FROM regexes WHERE service_id = ?;', (i[1],))[0][0]
n_pacchetti = db.query('SELECT SUM(blocked_packets) FROM regexes WHERE service_id = ?;', (i[1],))[0][0]
n_packets = db.query('SELECT SUM(blocked_packets) FROM regexes WHERE service_id = ?;', (i[1],))[0][0]
res.append({
'id': i[1],
@@ -76,7 +76,7 @@ def get_services():
'public_port': i[3],
'internal_port': i[2],
'n_regex': n_regex,
'n_pacchetti': n_pacchetti if n_pacchetti else 0,
'n_packets': n_packets if n_packets else 0,
'name': i[4]
})
@@ -90,7 +90,7 @@ def get_service(serv):
res = {}
if len(q) != 0:
n_regex = db.query('SELECT COUNT (*) FROM regexes WHERE service_id = ?;', (serv,))[0][0]
n_pacchetti = db.query('SELECT SUM(blocked_packets) FROM regexes WHERE service_id = ?;', (serv,))[0][0]
n_packets = db.query('SELECT SUM(blocked_packets) FROM regexes WHERE service_id = ?;', (serv,))[0][0]
print(q[0])
res = {
@@ -98,10 +98,12 @@ def get_service(serv):
'status': q[0][0],
'public_port': q[0][3],
'internal_port': q[0][2],
'n_packets': n_pacchetti if n_pacchetti else 0,
'n_packets': n_packets if n_packets else 0,
'n_regex': n_regex,
'name': q[0][4]
}
else:
return abort(404)
return res
@@ -265,5 +267,5 @@ if __name__ == '__main__':
})
#uwsgi
subprocess.run(["uwsgi","--http","127.0.0.1:8080","--master","--module","app:app"])
subprocess.run(["uwsgi","--socket","/tmp/uwsgi.sock","--master","--module","app:app"])

View File

@@ -1,28 +1,26 @@
worker_processes 5; ## Default: 1
pid /var/run/nginx.pid;
user nobody nogroup;
events {
worker_connections 1024;
}
http{
server {
listen ${NGINX_PORT};
server_name _;
root /execute/frontend/;
location / {
try_files $uri /index.html;
}
location /api/ {
include proxy_params;
proxy_pass http://127.0.0.1:8080;
}
}
worker_processes 5; ## Default: 1
pid /var/run/nginx.pid;
user nobody nogroup;
events {
worker_connections 1024;
}
http{
server {
listen $NGINX_PORT;
location / {
include proxy_params;
proxy_pass http://unix:/tmp/react.sock;
}
location /api/ {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
}

4
config/start_nginx.sh Normal file
View File

@@ -0,0 +1,4 @@
#/bin/bash
envsubst '$NGINX_PORT' < /tmp/nginx.conf > /etc/nginx/nginx.conf
/usr/sbin/nginx -g "daemon off;" || exit 1

View File

@@ -1,31 +1,37 @@
[supervisord]
logfile = /dev/null
loglevel = info
user = root
pidfile = /var/run/supervisord.pid
nodaemon = true
[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
user = root
startretries=5
numprocs=1
startsecs=0
process_name=%(program_name)s_%(process_num)02d
stderr_logfile=/var/log/supervisor/%(program_name)s_stderr.log
stderr_logfile_maxbytes=10MB
stdout_logfile=/var/log/supervisor/%(program_name)s_stdout.log
stdout_logfile_maxbytes=10MB
[program:backend]
directory=/execute
user = nobody
command=python3 app.py
stdout_logfile="syslog"
stderr_logfile="syslog"
startsecs=10
stopsignal=QUIT
stopasgroup=true
killasgroup=true
[supervisord]
logfile = /dev/null
loglevel = info
user = root
pidfile = /var/run/supervisord.pid
nodaemon = true
[program:backend]
directory=/execute
user = nobody
command=python3 app.py
startsecs=10
stopsignal=QUIT
stopasgroup=true
killasgroup=true
[program:frontend]
directory=/execute
user = nobody
command=serve -s frontend -l unix:/tmp/react.sock
startsecs=10
stopsignal=QUIT
stopasgroup=true
killasgroup=true
[program:nginx]
command=bash /tmp/start_nginx.sh
autostart=true
autorestart=true
user = root
startretries=5
numprocs=1
startsecs=0
stderr_logfile=/var/log/supervisor/%(program_name)s_stderr.log
stderr_logfile_maxbytes=10MB
stdout_logfile=/var/log/supervisor/%(program_name)s_stdout.log
stdout_logfile_maxbytes=10MB

View File

@@ -3,7 +3,10 @@ version: '3.9'
services:
firewall:
restart: unless-stopped
build: firewall
network_mode: "host"
build: .
#network_mode: "host"
ports:
- 80:80
environment:
- NGINX_PORT=8080
- NGINX_PORT=80

View File

@@ -1,6 +0,0 @@
Dockerfile
docker-compose.yml
**/*.pyc
**/__pycache__/
/.vscode/**

View File

@@ -1,188 +0,0 @@
# **WORK IN PROGRESS**
# Firegex-API Documentation
### This is a short description of the API
#
# Documentation
## Index
- [General stats](#get-apigeneral-stats)
- [List services](#get-apiservices)
- [Service info](#get-apiserviceserv)
- [Stop service](#get-apiserviceservstop)
- [Start service](#get-apiserviceservstart)
- [Delete service](#get-apiserviceservdelete)
- [Terminate service](#get-apiserviceservterminate)
- [Regenerate public port](#get-apiserviceservregen-port)
- [Service regexes](#get-apiserviceservregexes)
- [Regex info](#get-apiregexregexid)
- [Delete regex](#get-apiregexregexiddelete)
- [Add regex](#post-apiregexesadd)
- [Add service](#post-apiservicesadd)
#
#
## **GET** **```/api/general-stats```**
### Server response:
```json
{
"services": <total number of services>,
"closed": <total number of rejected packets>,
"regex": <total number of regexes>
}
```
#
## **GET** **```/api/services```**
### Server response:
```json
[
{
"id": <service_id>,
"status": <service status>,
"public_port": <public port>,
"internal_port": <internal port>,
"n_packets": <number of rejected packets>,
"n_regex": <number of regexes>
},
{
// Another service
}
]
```
#
## **GET** **```/api/service/<serv>```**
### Server response:
```json
{
"id": <service_id>,
"status": <service status>,
"public_port": <public port>,
"internal_port": <internal port>,
"n_packets": <number of rejected packets>,
"n_regex": <number of regexes>
}
```
#
## **GET** **```/api/service/<serv>/stop```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/start```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/delete```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/terminate```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/regen-port```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **GET** **```/api/service/<serv>/regexes```**
### Server response:
```json
[
{
"id": <regex id>,
"service_id": <service_id>,
"regex": <base64 encoded regex>,
"is_blacklist": <true|false>,
"n_packets": <number of blocked packets>,
"mode": <"C"|"S"|"B"> // Client to server, server to client or both
},
{
// Another regex
}
]
```
#
## **GET** **```/api/regex/<regex_id>```**
### Server response:
```json
{
"id": <regex id>,
"service_id": <service_id>,
"regex": <base64 encoded regex>,
"is_blacklist": <true|false>,
"n_packets": <number of blocked packets>,
"mode" <"C"|"S"|"B"> // Client to server, server to client or both
}
```
#
## **GET** **```/api/regex/<regex_id>/delete```**
### Server response:
```json
{
"status": "ok"
}
```
#
## **POST** **```/api/regexes/add```**
### Client request:
```json
{
"service_id": <service_id>,
"regex": <base64 encoded regex>,
"is_blacklist": <true|false>,
"mode": <"C"|"S"|"B"> // Client to server, server to client or both
}
```
### Server response:
```json
{
"status": "ok"
}
```
#
## **POST** **```/api/services/add```**
### Client request:
```json
{
"name": <the id used to identify the service>,
"port": <the internal port>
}
```
### Server response:
```json
{
"status": "ok"
}
```

View File

@@ -1,28 +0,0 @@
Dockerfile
docker-compose.yml
**/*.pyc
**/__pycache__/
/.vscode/**
#Node filters
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -1,23 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -1,43 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
frontend/public/favicon-16x16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

BIN
frontend/public/favicon-32x32.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
frontend/public/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
frontend/public/header-logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

22
frontend/public/index.html Executable file
View File

@@ -0,0 +1,22 @@
<!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>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@@ -1,8 +1,8 @@
import { Button, Group, NumberInput, Space, TextInput, Notification, Switch, NativeSelect } from '@mantine/core';
import { Button, Group, Space, TextInput, Notification, Switch, NativeSelect } from '@mantine/core';
import { useForm } from '@mantine/hooks';
import React, { useState } from 'react';
import { RegexAddForm, ServiceAddForm } from '../js/models';
import { addregex, addservice, b64encode, validateRegex } from '../js/utils';
import { RegexAddForm } from '../js/models';
import { addregex, b64encode, validateRegex } from '../js/utils';
import { ImCross } from "react-icons/im"
import FilterTypeSelector from './FilterTypeSelector';

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { ActionIcon, Badge, Modal } from '@mantine/core';
import { ActionIcon, Badge, Image, Modal } from '@mantine/core';
import style from "./Header.module.scss";
import { errorNotify, generalstats } from '../../js/utils';
import { GeneralStats, update_freq } from '../../js/models';
@@ -37,7 +37,9 @@ function Header() {
const closeModal = () => {setOpen(false);}
return <div id="header-page" className={style.header}>
<div className={style.logo} >LOGO</div>
<div style={{ width: 240, marginLeft: 'auto', marginRight: 'auto', padding:"40px" }}>
<Image src="/header-logo.png" alt="Firegex logo" />
</div>
<div className="flex-spacer" />
<Badge color="green" size="lg" variant="filled">Services: {generalStats.services}</Badge>
<Badge style={{marginLeft:"10px"}} size="lg" color="yellow" variant="filled">Filtered Connections: {generalStats.closed}</Badge>

View File

@@ -1,10 +1,8 @@
import { Center, Grid, SegmentedControl, Text, Title, Box, Badge, Space, ActionIcon } from '@mantine/core';
import { Grid, Text, Title, Badge, Space, ActionIcon } from '@mantine/core';
import React, { useState } from 'react';
import { RegexFilter } from '../../js/models';
import { getHumanReadableRegex } from '../../js/utils';
import style from "./RegexView.module.scss";
import { FaListAlt } from "react-icons/fa"
import { TiCancel } from "react-icons/ti"
import { BsTrashFill } from "react-icons/bs"
import YesNoModal from '../YesNoModal';
import FilterTypeSelector from '../FilterTypeSelector';

View File

@@ -47,7 +47,7 @@ export async function serviceregexlist(service_id:string){
return await getapi(`service/${service_id}/regexes`) as RegexFilter[];
}
const unescapedChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$&\'()*+,-./:;<=>?@[\\]^_`{|}~ ";
const unescapedChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
export function getHumanReadableRegex(regexB64:string){
const regex = Buffer.from(regexB64, "base64")

View File

@@ -32,7 +32,6 @@ function ServiceDetails() {
setServiceInfo(res)
}).catch(
err =>{
errorNotify(`Updater for ${srv_id} service failed [General Info]!`, err.toString())
error = true;
navigator("/")
})
@@ -40,17 +39,15 @@ function ServiceDetails() {
await serviceregexlist(srv_id).then(res => {
setRegexesList(res)
}).catch(
err =>{
errorNotify(`Updater for ${srv_id} service failed [Regex list]!`, err.toString())
error = true;
})
err => errorNotify(`Updater for ${srv_id} service failed [Regex list]!`, err.toString())
)
}
useEffect(()=>{
updateInfo()
const updater = setInterval(updateInfo, update_freq)
return () => { clearInterval(updater) }
}, []);
});
const [deleteModal, setDeleteModal] = useState(false)