diff --git a/frontend/src/components/DocsButton.tsx b/frontend/src/components/DocsButton.tsx new file mode 100644 index 0000000..0d1ef5b --- /dev/null +++ b/frontend/src/components/DocsButton.tsx @@ -0,0 +1,39 @@ +import { ActionIcon, Box, Modal, ScrollArea, Title, Tooltip } from "@mantine/core"; +import { useState } from "react"; +import { FaBookBookmark } from "react-icons/fa6"; +import { NFRegexDocs } from "./NFRegex/NFRegexDocs"; +import { NFProxyDocs } from "./NFProxy/NFProxyDocs"; +import { PortHijackDocs } from "./PortHijack/PortHijackDocs"; +import { EnumToPrimitiveUnion } from "../js/utils"; + + +export enum DocType{ + NFREGEX = "nfregex", + NFPROXY = "nfproxy", + PORTHIJACK = "porthijack", +} + + +export const DocsButton = ({ doc }: { doc: EnumToPrimitiveUnion }) => { + const [open, setOpen] = useState(false); + + return + + setOpen(true)} size="lg" radius="md" variant="filled"> + + setOpen(false)} fullScreen title={ + Firegex Docs πŸ“• + } scrollAreaComponent={ScrollArea.Autosize}> + { + doc == DocType.NFREGEX ? + : + doc == DocType.NFPROXY ? + : + doc == DocType.PORTHIJACK ? + : + Docs not found + } + + +} + diff --git a/frontend/src/components/Firewall/utils.ts b/frontend/src/components/Firewall/utils.ts index c051df8..54fc4cc 100644 --- a/frontend/src/components/Firewall/utils.ts +++ b/frontend/src/components/Firewall/utils.ts @@ -90,4 +90,4 @@ export const firewall = { ruleset: async (data:RuleAddForm) => { return await postapi("firewall/rules", data) as ServerResponseListed; } -} \ No newline at end of file +} diff --git a/frontend/src/components/NFProxy/NFProxyDocs.tsx b/frontend/src/components/NFProxy/NFProxyDocs.tsx new file mode 100644 index 0000000..bbf0179 --- /dev/null +++ b/frontend/src/components/NFProxy/NFProxyDocs.tsx @@ -0,0 +1,105 @@ +import { CodeHighlight } from "@mantine/code-highlight"; +import { Container, Title, Text, List, Code, Space } from "@mantine/core"; + +const IMPORT_CODE_EXAMPLE = `from firegex.nfproxy import pyfilter, ACCEPT, REJECT` + +const FOO_FILTER_CODE = `from firegex.nfproxy import pyfilter, ACCEPT, REJECT + +# This is NOT a filter +def useless_function() -> int: + print("This is a useless function") + return 42 + +@pyfilter +def none_filter(): # This is a filter that does nothing + useless_function() + return ACCEPT + +` + + +export const NFProxyDocs = () => { + return ( + + 🌐 Netfilter Proxy Documentation + + πŸ“– Overview + + Netfilter Proxy is a simulated proxy that leverages nfqueue to intercept network packets. + It follows a similar workflow to NFRegex but introduces Python-based filtering capabilities, + providing users with the flexibility to upload custom filters. + + + βš™οΈ How to Use Netfilter Proxy + + To use Netfilter Proxy, simply create and upload a Python filter. The filter is passed to the C++ binary, + which then processes packets using the provided logic. This allows you to tailor the filtering behavior + to your needs. + + + πŸš€ How It Works + + The proxy is built on a multi-threaded architecture and integrates Python for dynamic filtering: + + + + + Packet Interception: + The nfqueue kernel module intercepts network packets(a netfilter module) πŸ”
+ The rules for attach the nfqueue on the network traffic is done by the nftables lib with json APIs by the python manager. +
+
+ + + Packet Reading: + A dedicated thread reads packets from nfqueue. 🧡 + + + + + Multi-threaded Analysis: + The C++ binary launches multiple threads, each starting its own Python interpreter. + Thanks to Python 3.12’s support for a per-interpeter GIL, real multithreading is achieved. + Traffic is distributed among threads based on IP addresses and port hashing, ensuring that + packets belonging to the same flow are processed by the same thread. ⚑️ + + + + + Python Filter Integration: + Users can upload custom Python filters which are then executed by the interpreter, + allowing for dynamic and flexible packet handling. 🐍 + + + + + + HTTP Parsing: + A Python wrapper for llhttp (forked and adapted for working with multi-interpeters) is used to parse HTTP connections, making it easier to handle + and analyze HTTP traffic. πŸ“‘ + + +
+ + πŸ’‘ How to write pyfilters? + + First of all install the firegex lib and update it running pip install -U fgex. + After that you can use firegex module. + + With this code we imported the pyfilter decorator and the ACCEPT and REJECT constants.
+ Let's create a first (useless) filter to see the syntax: + + You see that the filter must be decorated with the pyfilter decorator and must return a statement about how to manage that packet. +
+ You can save every data about the current flow in the global variables, the code you write will be executed only once for flow. The globals are isolated between flows. + For each packet the filter functions will be called with the required paramethers and the same globals as before. +
+ Saving data in globals of other modules is not recommended, because that memory is shared by the flows managed by the same thread and lead to unexpected behaviors. +
+ Global variables that starts with __firegex_ are reserved for internal use, don't use them. + +
+ +
+ ); +}; diff --git a/frontend/src/components/NFRegex/NFRegexDocs.tsx b/frontend/src/components/NFRegex/NFRegexDocs.tsx new file mode 100644 index 0000000..aee093b --- /dev/null +++ b/frontend/src/components/NFRegex/NFRegexDocs.tsx @@ -0,0 +1,69 @@ +import { Container, Title, Text, List } from "@mantine/core"; + +export const NFRegexDocs = () => { + return ( + + πŸ“‘ Netfilter Regex Documentation + + πŸ“– Overview + + Netfilter Regex is a powerful feature that enables filtering of network packets using regular expressions. This capability is especially useful when you need to inspect packet content and match specific strings or patterns. + + + βš™οΈ How to Use Netfilter Regex + + To get started, create a service and attach a regular expression to it. Once the service is configured, apply it to a network interface to dynamically filter packets based on the defined regex. + + + πŸš€ How It Works + + The packet filtering process is implemented in C++ and involves several key steps: + + + + + Packet Interception: + The nfqueue kernel module intercepts network packets (a netfilter module) πŸ”
+ The rules for attach the nfqueue on the network traffic is done by the nftables lib with json APIs by the python manager. +
+
+ + + Packet Reading: + A dedicated thread reads packets from nfqueue. 🧡 + + + + + Packet Parsing: + Intercepted packets are parsed by libtins, a C++ library that extracts the payload from each packet. πŸ“„ + + + + + Multi-threaded Analysis: + Multiple threads analyze packets concurrently. + While the nfqueue module balances network + load based solely on IP addressesβ€”resulting in a single thread handling traffic in NAT environments + like CTF networks, firegex manage this threads user-level in a different way. + The traffic is routed in the threads based on IP addresses combined with port hashing, + ensuring a more balanced workload and that flows will be analyzed by the same thread. ⚑️ + + + + + TCP Handling: + For TCP connections, libtins employs a TCP follower to order packets received from the kernel. πŸ“ˆ + + + + + Regex Matching: + The extracted payload is processed using vectorscan β€” a fork of hyperscan that runs also on arm64. + For UDP packets, matching occurs on a per-packet basis while saving only the match context rather than the full payload. 🎯 + + +
+
+ ); +}; diff --git a/frontend/src/components/PortHijack/PortHijackDocs.tsx b/frontend/src/components/PortHijack/PortHijackDocs.tsx new file mode 100644 index 0000000..8b62750 --- /dev/null +++ b/frontend/src/components/PortHijack/PortHijackDocs.tsx @@ -0,0 +1,9 @@ +import { Box } from "@mantine/core" + + +export const PortHijackDocs = () => { + return + PORT + {/* TODO write me pls */} + +} \ No newline at end of file diff --git a/frontend/src/js/utils.tsx b/frontend/src/js/utils.tsx index 20c7527..56297fd 100644 --- a/frontend/src/js/utils.tsx +++ b/frontend/src/js/utils.tsx @@ -20,6 +20,13 @@ export const DEV_IP_BACKEND = "127.0.0.1:4444" export const WARNING_NFPROXY_TIME_LIMIT = 1000*60*10 // 10 minutes +export type EnumToPrimitiveUnion = `${T & string}` | ParseNumber<`${T & number}`>; +type ParseNumber = T extends `${infer U extends number}` ? U : never; + +export function typeCastEnum(value: EnumToPrimitiveUnion): E { + return value as E; +} + export const socketio = import.meta.env.DEV? io("ws://"+DEV_IP_BACKEND, { path:"/sock/socket.io", diff --git a/frontend/src/pages/NFProxy/index.tsx b/frontend/src/pages/NFProxy/index.tsx index 4de0959..f95d69b 100644 --- a/frontend/src/pages/NFProxy/index.tsx +++ b/frontend/src/pages/NFProxy/index.tsx @@ -13,6 +13,7 @@ import { MdUploadFile } from "react-icons/md"; import { notifications } from '@mantine/notifications'; import { useFileDialog } from '@mantine/hooks'; import { CodeHighlight } from '@mantine/code-highlight'; +import { DocsButton } from '../../components/DocsButton'; export default function NFProxy({ children }: { children: any }) { @@ -131,6 +132,8 @@ export default function NFProxy({ children }: { children: any }) { + + diff --git a/frontend/src/pages/NFRegex/index.tsx b/frontend/src/pages/NFRegex/index.tsx index f5df64d..16c5e7c 100644 --- a/frontend/src/pages/NFRegex/index.tsx +++ b/frontend/src/pages/NFRegex/index.tsx @@ -12,6 +12,7 @@ import { TbReload } from 'react-icons/tb'; import { FaFilter } from 'react-icons/fa'; import { FaServer } from "react-icons/fa6"; import { VscRegex } from "react-icons/vsc"; +import { DocsButton } from '../../components/DocsButton'; function NFRegex({ children }: { children: any }) { @@ -59,6 +60,8 @@ function NFRegex({ children }: { children: any }) { queryClient.invalidateQueries(["nfregex"])} size="lg" radius="md" variant="filled" loading={services.isFetching}> + + diff --git a/frontend/src/pages/PortHijack/index.tsx b/frontend/src/pages/PortHijack/index.tsx index e6fa5ce..a0c1072 100644 --- a/frontend/src/pages/PortHijack/index.tsx +++ b/frontend/src/pages/PortHijack/index.tsx @@ -9,6 +9,7 @@ import { useQueryClient } from '@tanstack/react-query'; import { TbReload } from 'react-icons/tb'; import { FaServer } from 'react-icons/fa'; import { GrDirections } from 'react-icons/gr'; +import { DocsButton } from '../../components/DocsButton'; function PortHijack() { @@ -42,6 +43,8 @@ function PortHijack() { queryClient.invalidateQueries(["porthijack"])} size="lg" radius="md" variant="filled" loading={services.isFetching}> + +