docs completed

This commit is contained in:
Domingo Dirutigliano
2025-03-05 14:05:31 +01:00
parent eda44f12ff
commit 3494d10032
11 changed files with 452 additions and 94 deletions

View File

@@ -1,4 +1,4 @@
import { ActionIcon, Box, Modal, ScrollArea, Title, Tooltip } from "@mantine/core";
import { ActionIcon, ActionIconProps, Box, Modal, ScrollArea, Title, Tooltip } from "@mantine/core";
import { useState } from "react";
import { FaBookBookmark } from "react-icons/fa6";
import { NFRegexDocs } from "./NFRegex/NFRegexDocs";
@@ -6,7 +6,6 @@ import { NFProxyDocs } from "./NFProxy/NFProxyDocs";
import { PortHijackDocs } from "./PortHijack/PortHijackDocs";
import { EnumToPrimitiveUnion } from "../js/utils";
export enum DocType{
NFREGEX = "nfregex",
NFPROXY = "nfproxy",
@@ -14,12 +13,12 @@ export enum DocType{
}
export const DocsButton = ({ doc }: { doc: EnumToPrimitiveUnion<DocType> }) => {
export const DocsButton = ({ doc, ...props }: { doc: EnumToPrimitiveUnion<DocType> } & ActionIconProps) => {
const [open, setOpen] = useState(false);
return <Box>
<Tooltip label="Add a new service" color="pink">
<ActionIcon color="pink" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled"><FaBookBookmark size="20px" /></ActionIcon>
<Tooltip label="Read the documentation" color="pink">
<ActionIcon color="pink" onClick={()=>setOpen(true)} size="lg" radius="md" variant="filled" {...props}><FaBookBookmark size="20px" /></ActionIcon>
</Tooltip>
<Modal opened={open} onClose={() => setOpen(false)} fullScreen title={
<Title order={2}>Firegex Docs 📕</Title>

View File

@@ -1,5 +1,7 @@
import { CodeHighlight } from "@mantine/code-highlight";
import { Container, Title, Text, List, Code, Space } from "@mantine/core";
import { Container, Title, Text, List, Code, Space, Badge, Box } from "@mantine/core";
import { CgEditBlackPoint } from "react-icons/cg";
import { EXAMPLE_PYFILTER } from "./utils";
const IMPORT_CODE_EXAMPLE = `from firegex.nfproxy import pyfilter, ACCEPT, REJECT`
@@ -18,6 +20,46 @@ def none_filter(): # This is a filter that does nothing
`
const TYPING_ARGS_EXAMPLE = `from firegex.nfproxy import pyfilter, ACCEPT, REJECT
from firegex.nfproxy.models import HttpRequest
@pyfilter
def filter_with_args(http_request: HttpRequest) -> int:
if http_request.body:
if b"ILLEGAL" in http_request.body:
return REJECT
`
const IMPORT_FULL_ACTION_STREAM = `from firegex.nfproxy import FullStreamAction`
export const HELP_NFPROXY_SIM = `➤ fgex nfproxy -h
Usage: fgex nfproxy [OPTIONS] FILTER_FILE ADDRESS PORT
Run an nfproxy simulation
╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * filter_file TEXT The path to the filter file [default: None] [required] │
│ * address TEXT The address of the target to proxy [default: None] [required] │
│ * port INTEGER The port of the target to proxy [default: None] [required] │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --proto [tcp|http] The protocol to proxy [default: tcp] │
│ --from-address TEXT The address of the local server [default: None] │
│ --from-port INTEGER The port of the local server [default: 7474] │
│ -6 Use IPv6 for the connection │
│ --help -h Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯`
const HttpBadge = () => {
return <Badge size="md" ml="xs" radius="md" variant="gradient" gradient={{ from: 'red', to: 'grape', deg: 107 }} style={{ fontSize: "13px", fontWeight: "bolder"}}>HTTP</Badge>
}
const TCPBadge = () => {
return <Badge size="md" ml="xs" radius="md" variant="gradient" gradient={{ from: 'indigo', to: 'teal', deg: 164 }} style={{ fontSize: "13px", fontWeight: "bolder"}}>TCP</Badge>
}
export const NFProxyDocs = () => {
return (
<Container size="xl">
@@ -30,13 +72,291 @@ export const NFProxyDocs = () => {
providing users with the flexibility to upload custom filters.
</Text>
<Title order={2} mt="lg" mb="sm"> How to Use Netfilter Proxy</Title>
<Title order={2} mt="lg" mb="sm"> How to use Netfilter Proxy</Title>
<Text size="lg">
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.
</Text>
<Title order={2} mt="lg" mb="sm">💡 How to write pyfilters?</Title>
<Text size="lg">
First of all install the firegex lib and update it running <Code>pip install -U fgex</Code>.
After that you can use <Code>firegex</Code> module.
<CodeHighlight code={IMPORT_CODE_EXAMPLE} language="python" my="sm"/>
With this code we imported the <Code>pyfilter</Code> decorator and the <Code>ACCEPT</Code> and <Code>REJECT</Code> statements.<br />
Let's create a first (useless) filter to see the syntax:
<CodeHighlight code={FOO_FILTER_CODE} language="python" my="sm"/>
You see that the filter must be decorated with the <Code>pyfilter</Code> decorator and must return a statement about how to manage that packet.
<br/><Space h="sm" />
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 variables are isolated between flows.
For each packet the filter functions will be called with the required paramethers and using the same globals as before.
<br/><Space h="sm" />
<strong>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.</strong>
<br/><Space h="sm" />
<strong>Global variables that starts with '__firegex' are reserved for internal use, don't use them.</strong>
<br/><Space h="sm" />
You can manage when the function is called and also getting some data specifying some paramethers, using type decorators.
Default values of the paramethers will be ignored, also kvargs values will be ignored.
<br/><Space h="sm" />
<strong>Functions with no type decorator are considered invalid pyfilters!</strong>
<br/><Space h="sm" />
<CodeHighlight code={TYPING_ARGS_EXAMPLE} language="python" my="sm"/>
In this code we are filtering all the http requests that contains the word "ILLEGAL" in the body. All the other packets will be accepted (default behavior).
The function will be called only if at least internally teh HTTP request header has been parsed, and also when the body will be parsed.
<br/><Space h="sm" />
If we have multiple paramether, the function will be called only if with the packet arrived is possible to build all the paramethers.
</Text>
<Title order={2} mt="lg" mb="sm">🔧 How can I test the filter?</Title>
<Text size="lg">
You can test your filter by using <Code>fgex</Code> command installed by firegex lib: This will run a local proxy to a remote destination with the filter you specified.
<br/><Space h="sm" />
This can be done by running for instance: <Code>fgex nfproxy test_http.py 127.0.0.1 8080 --proto http</Code>
<CodeHighlight code={HELP_NFPROXY_SIM} language="" my="sm"/>
You don't need to restart the proxy every time you change the filter, the filter will be reloaded automatically.
</Text>
<Title order={2} mt="lg" mb="sm">📦 Packet Statements</Title>
<Text size="lg" my="xs">
Here there are all the statments you can return from a filter:
<List>
<List.Item><strong>ACCEPT: </strong> The packet will be accepted and forwarded to the destination. (default if None is returned)</List.Item>
<List.Item><strong>REJECT: </strong> The connection will be closed and all the packets will be dropped.</List.Item>
<List.Item><strong>DROP: </strong> This packet and all the following will be dropped. (This not simulate a connection closure)</List.Item>
<List.Item><strong>UNSTABLE_MANGLE: </strong> The packet will be modified and forwarded. You can edit the packet only with RawPacket data handler. (This is an unstable statement, use it carefully)</List.Item>
</List>
</Text>
<Title order={2} mt="lg" mb="sm">⚙️ Data Structures</Title>
<Text size="lg" my="xs">
Here there are all the data structure you can use for your filters:
</Text>
<Box display="flex" style={{alignItems: "center"}}>
<Title order={3} my="xs"><CgEditBlackPoint style={{marginBottom: -3}}/> RawPacket</Title><Space w="sm" /><TCPBadge /><HttpBadge />
</Box>
<Text size="lg">This data is the raw packet processed by nfqueue. It contains:</Text>
<Space h="sm" />
<Text size="lg" ml="xs">
<List>
<List.Item>
<strong>data: </strong> The raw packet data assembled by libtins (read only).
</List.Item>
<List.Item>
<strong>is_input: </strong> It's true if the packet is incoming, false if it's outgoing. (read only)
</List.Item>
<List.Item>
<strong>is_ipv6: </strong> It's true if the packet is IPv6, false if it's IPv4. (read only)
</List.Item>
<List.Item>
<strong>is_tcp: </strong> It's true if the packet is TCP, false if it's UDP. (read only)
</List.Item>
<List.Item>
<strong>l4_size: </strong> The size of l4 payload (read only)
</List.Item>
<List.Item>
<strong>raw_packet_header_len: </strong> The size of the raw packet header (read only)
</List.Item>
<List.Item>
<strong>raw_packet: </strong> The raw packet data with ip and TCP header. You can edit all the packet content and it will be modified if you send
the UNSTABLE_MANGLE statement. <strong>Be careful, beacause the associated layer 4 data can be different from 'data' filed that instead arrives from libtins.</strong>
When you edit this field, l4_size and l4_data will be updated automatically.
</List.Item>
<List.Item>
<strong>l4_data: </strong> The l4 payload data, directly taken by the raw packet. You can edit all the packet content and it will be modified if you send
the UNSTABLE_MANGLE statement. <strong>Be careful, beacause the associated layer 4 data can be different from 'data' filed that instead arrives from libtins.</strong> When you edit this field, l4_size and raw_packet will be updated automatically.
</List.Item>
</List>
</Text>
<Box display="flex" style={{alignItems: "center"}}>
<Title order={3} my="xs"><CgEditBlackPoint style={{marginBottom: -3}}/> TCPInputStream (alias: TCPClientStream)</Title><Space w="sm" /><TCPBadge /><HttpBadge />
</Box>
<Text size="lg">This data is the TCP input stream: this handler is called only on is_input=True packets. The filters that handles this data will be called only in this case.</Text>
<Space h="sm" />
<Text size="lg" ml="xs">
<List>
<List.Item>
<strong>data: </strong> The entire stream in input direction. (read only)
</List.Item>
<List.Item>
<strong>total_stream_size: </strong> The size of the entire stream in input direction. (read only)
</List.Item>
<List.Item>
<strong>is_ipv6: </strong> It's true if the stream is IPv6, false if it's IPv4. (read only)
</List.Item>
</List>
</Text>
<Box display="flex" style={{alignItems: "center"}}>
<Title order={3} my="xs"><CgEditBlackPoint style={{marginBottom: -3}}/> TCPOutputStream (alias TCPServerStream)</Title><Space w="sm" /><TCPBadge /><HttpBadge />
</Box>
<Text size="lg">This data is the TCP output stream: this handler is called only on is_input=False packets. The filters that handles this data will be called only in this case.</Text>
<Space h="sm" />
<Text size="lg" ml="xs">
<List>
<List.Item>
<strong>data: </strong> The entire stream in output direction. (read only)
</List.Item>
<List.Item>
<strong>total_stream_size: </strong> The size of the entire stream in output direction. (read only)
</List.Item>
<List.Item>
<strong>is_ipv6: </strong> It's true if the stream is IPv6, false if it's IPv4. (read only)
</List.Item>
</List>
</Text>
<Box display="flex" style={{alignItems: "center"}}>
<Title order={3} my="xs"><CgEditBlackPoint style={{marginBottom: -3}}/> HttpRequest</Title><Space w="sm" /><HttpBadge />
</Box>
<Text size="lg">This data is the Http request processed by nfqueue. This handler can be called twice per request: once when the http headers are complete, and once when the body is complete.</Text>
<Text size="lg">If the http data arrives in 1 single TCP packet, this handler will be called once</Text>
<Space h="sm" />
<Text size="lg" ml="xs">
<List>
<List.Item>
<strong>url: </strong> The url of the request (read only)
</List.Item>
<List.Item>
<strong>headers: </strong> The headers of the request (read only). The keys and values are exactly the same as the original request (case sensitive).
</List.Item>
<List.Item>
<strong>get_header(key:str, default = None): </strong> A function that returns the value of a header: it matches the key without case sensitivity. If the header is not found, it returns the default value.
</List.Item>
<List.Item>
<strong>user_agent: </strong> The user agent of the request (read only)
</List.Item>
<List.Item>
<strong>content_encoding: </strong> The content encoding of the request (read only)
</List.Item>
<List.Item>
<strong>content_length: </strong> The content length of the request (read only)
</List.Item>
<List.Item>
<strong>body: </strong> The body of the request (read only). It's None if the body has not arrived yet.
</List.Item>
<List.Item>
<strong>http_version: </strong> The http version of the request (read only)
</List.Item>
<List.Item>
<strong>keep_alive: </strong> It's true if the connection was marked for keep alive, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>should_upgrade: </strong> It's true if the connection should be upgraded, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>method: </strong> The method of the request (read only)
</List.Item>
<List.Item>
<strong>has_begun: </strong> It's true if the request has begun, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>headers_complete: </strong> It's true if the headers are complete, false if they are not. (read only)
</List.Item>
<List.Item>
<strong>message_complete: </strong> It's true if the message is complete, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>total_size: </strong> The size of the entire http request (read only)
</List.Item>
<List.Item>
<strong>stream: </strong> It's the buffer that contains the stream of the websocket traffic in input. This is used only if should_upgrade is True. (read only)
</List.Item>
</List>
</Text>
<Box display="flex" style={{alignItems: "center"}}>
<Title order={3} my="xs"><CgEditBlackPoint style={{marginBottom: -3}}/> HttpRequestHeader</Title><Space w="sm" /><HttpBadge />
</Box>
<Text size="lg">Same as HttpRequest, but this handler is called only when the headers are complete and body is not buffered. Body will always be None</Text>
<Box display="flex" style={{alignItems: "center"}}>
<Title order={3} my="xs"><CgEditBlackPoint style={{marginBottom: -3}}/> HttpResponse</Title><Space w="sm" /><HttpBadge />
</Box>
<Text size="lg">This data is the Http response processed by nfqueue. This handler can be called twice per response: once when the http headers are complete, and once when the body is complete.</Text>
<Text size="lg">If the http data arrives in 1 single TCP packet, this handler will be called once</Text>
<Space h="sm" />
<Text size="lg" ml="xs">
<List>
<List.Item>
<strong>url: </strong> The url of the response (read only)
</List.Item>
<List.Item>
<strong>headers: </strong> The headers of the response (read only). The keys and values are exactly the same as the original response (case sensitive).
</List.Item>
<List.Item>
<strong>get_header(key:str, default = None): </strong> A function that returns the value of a header: it matches the key without case sensitivity. If the header is not found, it returns the default value.
</List.Item>
<List.Item>
<strong>user_agent: </strong> The user agent of the response (read only)
</List.Item>
<List.Item>
<strong>content_encoding: </strong> The content encoding of the response (read only)
</List.Item>
<List.Item>
<strong>content_length: </strong> The content length of the response (read only)
</List.Item>
<List.Item>
<strong>body: </strong> The body of the response (read only). It's None if the body has not arrived yet.
</List.Item>
<List.Item>
<strong>http_version: </strong> The http version of the response (read only)
</List.Item>
<List.Item>
<strong>keep_alive: </strong> It's true if the connection was marked for keep alive, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>should_upgrade: </strong> It's true if the connection should be upgraded, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>status_code: </strong> The status code of the response (read only) (int)
</List.Item>
<List.Item>
<strong>has_begun: </strong> It's true if the response has begun, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>headers_complete: </strong> It's true if the headers are complete, false if they are not. (read only)
</List.Item>
<List.Item>
<strong>message_complete: </strong> It's true if the message is complete, false if it's not. (read only)
</List.Item>
<List.Item>
<strong>total_size: </strong> The size of the entire http response (read only)
</List.Item>
<List.Item>
<strong>stream: </strong> It's the buffer that contains the stream of the websocket traffic in output. This is used only if should_upgrade is True. (read only)
</List.Item>
</List>
</Text>
<Box display="flex" style={{alignItems: "center"}}>
<Title order={3} my="xs"><CgEditBlackPoint style={{marginBottom: -3}}/> HttpResponseHeader</Title><Space w="sm" /><HttpBadge />
</Box>
<Text size="lg">Same as HttpResponse, but this handler is called only when the headers are complete and body is not buffered. Body will always be None</Text>
<Title order={2} mt="lg" mb="sm">⚠️ Stream Limiter</Title>
<Text size="lg" my="xs">
What happen if in a specific TCP stream you have a lot of data? The stream limiter will be activated and some action will be taken.
You can configure the action performed by setting some option in the globals:
<br /><Space h="sm" />
First import the FullStreamAction enum:
<CodeHighlight code={IMPORT_FULL_ACTION_STREAM} language="python" my="sm" />
Then you can set in the globals these options:
<List>
<List.Item>
<strong>FGEX_STREAM_MAX_SIZE: </strong> Sets the maximum size of the stream. If the stream exceeds this size, the FGEX_FULL_STREAM_ACTION will be performed. (this limit is applyed at the single stream related to the single data handler).
For example if TCPInputStream has reached the limit but HttpResponse has not, the action will be performed only on the TCPInputStream. The default is 1MB.
</List.Item>
<List.Item>
<strong>FGEX_FULL_STREAM_ACTION: </strong> Sets the action performed when the stream exceeds the FGEX_STREAM_MAX_SIZE. The default is FullStreamAction.FLUSH.
</List.Item>
</List>
Heres will be explained every type of action you can set:
<List>
<List.Item>
<strong>FLUSH: </strong> Flush the stream and continue to acquire new packets (default)
</List.Item>
<List.Item>
<strong>DROP: </strong> Drop the next stream packets - like a DROP action by filter
</List.Item>
<List.Item>
<strong>REJECT: </strong> Reject the stream and close the connection - like a REJECT action by filter
</List.Item>
<List.Item>
<strong>ACCEPT: </strong> Stops to call pyfilters and accept the traffic
</List.Item>
</List>
</Text>
<Title order={2} mt="lg" mb="sm">🚀 How It Works</Title>
<Text mb="sm" size="lg">
The proxy is built on a multi-threaded architecture and integrates Python for dynamic filtering:
@@ -71,7 +391,6 @@ export const NFProxyDocs = () => {
allowing for dynamic and flexible packet handling. 🐍
</Text>
</List.Item>
<List.Item>
<Text size="lg">
<strong>HTTP Parsing: </strong>
@@ -80,26 +399,12 @@ export const NFProxyDocs = () => {
</Text>
</List.Item>
</List>
<Title order={2} mt="lg" mb="sm">💡 How to write pyfilters?</Title>
<Space h="xl" />
<Title order={2} mt="lg" mb="sm">📚 Additional Resources</Title>
<Text size="lg">
First of all install the firegex lib and update it running <Code>pip install -U fgex</Code>.
After that you can use <Code>firegex</Code> module.
<CodeHighlight code={IMPORT_CODE_EXAMPLE} language="python" my="sm"/>
With this code we imported the <Code>pyfilter</Code> decorator and the <Code>ACCEPT</Code> and <Code>REJECT</Code> constants.<br />
Let's create a first (useless) filter to see the syntax:
<CodeHighlight code={FOO_FILTER_CODE} language="python" my="sm"/>
You see that the filter must be decorated with the <Code>pyfilter</Code> decorator and must return a statement about how to manage that packet.
<br/><Space h="sm" />
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.
<br/><Space h="sm" />
<strong>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.</strong>
<br/><Space h="sm" />
<strong>Global variables that starts with __firegex_ are reserved for internal use, don't use them.</strong>
Here's a pyfilter code commented example:
<CodeHighlight code={EXAMPLE_PYFILTER} language="python" my="sm"/>
</Text>
</Container>
);
};

View File

@@ -103,7 +103,7 @@ export const EXAMPLE_PYFILTER = `# This in an example of a filter file with http
# From here we can import the DataTypes that we want to use:
# The data type must be specified in the filter functions
# And will also interally be used to decide when call some filters and how aggregate data
from firegex.nfproxy.params import RawPacket
from firegex.nfproxy.models import RawPacket
# global context in this execution is dedicated to a single TCP stream
# - This code will be executed once at the TCP stream start
@@ -158,15 +158,18 @@ def http_filter(http:HTTPRequest):
# If the stream is too big, you can specify what actions to take:
# This can be done defining some variables in the global context
# - FGEX_STREAM_MAX_SIZE: The maximum size of the stream in bytes (default 1MB)
# NOTE: the stream size is calculated by the sum of the dimension of the packets in the stream (both directions)
# NOTE: the stream size is calculated and managed indipendently by the data type handling system
# Only types required by at least 1 filter will be stored.
# - FGEX_FULL_STREAM_ACTION: The action to do when the stream is full
# - FLUSH: Flush the stream and continue to acquire new packets (default)
# - DROP: Drop the next stream packets - like a DROP action by filter
# - REJECT: Reject the stream and close the connection - like a REJECT action by filter
# - ACCEPT: Stops to call pyfilters and accept the traffic
# - FullStreamAction.FLUSH: Flush the stream and continue to acquire new packets (default)
# - FullStreamAction.DROP: Drop the next stream packets - like a DROP action by filter
# - FullStreamAction.REJECT: Reject the stream and close the connection - like a REJECT action by filter
# - FullStreamAction.ACCEPT: Stops to call pyfilters and accept the traffic
from firege.nfproxy import FullStreamAction
# Example of a global context
FGEX_STREAM_MAX_SIZE = 4096
FGEX_FULL_STREAM_ACTION = REJECT
FGEX_FULL_STREAM_ACTION = FullStreamAction.REJECT
# This could be an ideal configuration if we expect to normally have streams with a maximum size of 4KB of traffic
`

View File

@@ -1,9 +1,37 @@
import { Box } from "@mantine/core"
import { CodeHighlight } from "@mantine/code-highlight"
import { Code, Container, Space, Text, Title } from "@mantine/core"
import { HELP_NFPROXY_SIM } from "../NFProxy/NFProxyDocs"
export const PortHijackDocs = () => {
return <Box>
PORT
{/* TODO write me pls */}
</Box>
return <Container size="xl">
<Title order={1}> Hijack port to proxy</Title>
<Title order={2} mt="xl" mb="sm">📖 Overview</Title>
<Text size="lg">
'Hijack port to proxy' uses <a href="https://netfilter.org/">nftables</a> to redirect the traffic from an external IP to a localhost server.
You are responsable to run and keep alive this server, that is your proxy. The original service will be accessible using loopback (127.0.0.1).
In this way you can run your custom proxy without touching the service configuration.
</Text>
<Title order={2} mt="lg" mb="sm"> How to use Hijack port to proxy</Title>
<Text size="lg">
To use this feature, simply create your proxy, run it, than create a new service and set the proxy port and the external ip and port.
The traffic will be redirected to your proxy, that will still be able to contact the original service using loopback.
The responses of your proxy will be redirected to the original client, and teh proxy will see as the requests were made by the original client.
<br /><Space h="sm" />
You can use for instance the proxy simulator of nfproxy feature of firegex, and run it using nfproxy features. This will advantage you if for instance you need to mangle the traffic.
changing packets it's possible but not sure to do with nfproxy, but the simulator can change the packets normally (on PacketRaw data is always == l4_data in the simulator, check the nfproxy docs for more info)
<br /><Space h="sm" />
You will need to install firegex library with <Code>pip install -U fgex</Code> and than use the simulator command
<CodeHighlight code={HELP_NFPROXY_SIM} language="" my="sm"/>
for instance: <Code>fgex nfproxy test_http.py 127.0.0.1 8080 --proto http --from-port 13377</Code>
</Text>
<Title order={2} mt="lg" mb="sm">🚀 How It Works</Title>
<Text mb="sm" size="lg">
This modules works in a simple way: this only thing done is to change the destination and source ip using <a href="https://netfilter.org/">nftables</a> rules so that the kernel will see that the request was done to the proxy port,
but externaly the packets exists as connections to the original service. This mangle is done only for external packet arriving from the external ip indicated, localhost traffic won't be touched.
</Text>
<Space h="xl" />
</Container>
}

View File

@@ -407,15 +407,20 @@ export const Firewall = () => {
)}
</Droppable>
</DragDropContext>:<>
<Space h="xl"/> <Title className='center-flex' style={{textAlign:"center"}} order={3}>No rule found! Add one clicking the "+" buttons</Title>
<Space h="xl" /> <Space h="xl" />
<Box className='center-flex'>
<Tooltip label="Add a new rule" color="blue">
<ActionIcon color="blue" onClick={emptyRuleAdd} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
</Box>
</>}
<Box className='center-flex-row'>
<Space h="xl" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Firewall Rules allows you to use nftables but through a web interface</Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={5}>Add new rules, sort it and enable the firewall: be carefull, wrong rules could also drops out firegex access</Title>
<Space h="lg" />
<Box className='center-flex' style={{gap: 20}}>
<Tooltip label="Add a new rule" color="blue">
<ActionIcon color="blue" onClick={emptyRuleAdd} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
</Box>
</Box>
</>}
<YesNoModal
title='Are you sure to apply the changes to the firewall?'

View File

@@ -23,6 +23,7 @@ import { FiFileText } from "react-icons/fi";
import { ModalLog } from '../../components/ModalLog';
import { useListState } from '@mantine/hooks';
import { ExceptionWarning } from '../../components/NFProxy/ExceptionWarning';
import { DocsButton } from '../../components/DocsButton';
export default function ServiceDetailsNFProxy() {
@@ -202,13 +203,11 @@ export default function ServiceDetailsNFProxy() {
{(!filtersList.data || filtersList.data.length == 0)?<>
<Space h="xl" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>No filters found! Edit the proxy file, install the firegex client:<Space w="xs" /><Code mb={-4} >pip install fgex</Code></Title>
<Title className='center-flex' style={{textAlign:"center"}} order={3}>No filters found! Create some proxy filters, install the firegex client:<Space w="xs" /><Code mb={-4} >pip install -U fgex</Code></Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Read the documentation for more information<Space w="sm" /><DocsButton doc='nfproxy'/></Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Then create a new filter file with the following syntax and upload it here (using the button above)</Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Before upload the filter you can test it using the fgex command installed by the python lib</Title>
<Space h="lg" />
<CodeHighlight code={EXAMPLE_PYFILTER} language="python" />
</>:<>{filtersList.data?.map( (filterInfo) => <PyFilterView filterInfo={filterInfo} key={filterInfo.name}/>)}</>
}
<YesNoModal

View File

@@ -147,22 +147,18 @@ export default function NFProxy({ children }: { children: any }) {
<Space h="xl" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Netfilter proxy is a simulated proxy written using python with a c++ core</Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={5}>Filters are created using a simple python syntax, infact the first you need to do is to install the firegex lib:<Space w="xs" /><Code mb={-4} >pip install firegex</Code></Title>
<Title className='center-flex' style={{textAlign:"center"}} order={5}>Filters are created using a simple python syntax, infact the first you need to do is to install the firegex lib:<Space w="xs" /><Code mb={-4} >pip install -U fgex</Code></Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={5}>Then you can create a new service and write custom filters for the service</Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={5}>Below there is a description and example about how a pyfilter has to be composed (this example is replicated in every empty service)</Title>
<Space h="lg" />
<CodeHighlight code={EXAMPLE_PYFILTER} language="python" />
<Space h="lg" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Add your first service</Title>
<Space h="lg" />
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" />
</ActionIcon>
</Tooltip>
<Box className='center-flex' style={{gap: 20}}>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" />
</ActionIcon>
</Tooltip>
<DocsButton doc="nfproxy" size="xl" />
</Box>
</Box>
</>}
</>}

View File

@@ -70,11 +70,21 @@ function NFRegex({ children }: { children: any }) {
<LoadingOverlay visible={services.isLoading} />
{(services.data && services.data?.length > 0)?services.data.map( srv => <ServiceRow service={srv} key={srv.service_id} onClick={()=>{
navigator("/nfregex/"+srv.service_id)
}} />):<><Space h="xl"/> <Title className='center-flex' style={{textAlign:"center"}} order={3}>No services found! Add one clicking the "+" buttons</Title>
<Box className='center-flex'>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"><BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
}} />):<>
<Box className='center-flex-row'>
<Space h="xl" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Netfilter Regex allows you to filter traffic using regexes</Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={5}>Start a service, add your regexes and it's already done!</Title>
<Space h="lg" />
<Box className='center-flex' style={{gap: 20}}>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" />
</ActionIcon>
</Tooltip>
<DocsButton doc="nfregex" size="xl" />
</Box>
</Box>
</>}
</>}

View File

@@ -51,11 +51,22 @@ function PortHijack() {
<Box className="center-flex-row" style={{gap: 20}}>
<LoadingOverlay visible={services.isLoading} />
{(services.data && services.data.length > 0) ?services.data.map( srv => <ServiceRow service={srv} key={srv.service_id} />):<>
<Space h="xl"/> <Title className='center-flex' style={{textAlign:"center"}} order={3}>No services found! Add one clicking the "+" buttons</Title>
<Box className='center-flex'>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled"><BsPlusLg size="20px" /></ActionIcon>
</Tooltip>
<Box className='center-flex-row'>
<Space h="xl" />
<Title className='center-flex' style={{textAlign:"center"}} order={3}>Hjiack Port to Proxy is a feature that allows you to run your custom proxy without touch the service config</Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={5}>It hijack the traffic to a secondary port, where you can run your proxy, that will still be able to contact the original service using loopback</Title>
<Space h="xs" />
<Title className='center-flex' style={{textAlign:"center"}} order={5}>Start using port hijacking creating a new service and routing the traffic to your proxy not changing the original service configs</Title>
<Space h="lg" />
<Box className='center-flex' style={{gap: 20}}>
<Tooltip label="Add a new service" color="blue">
<ActionIcon color="blue" onClick={()=>setOpen(true)} size="xl" radius="md" variant="filled">
<BsPlusLg size="20px" />
</ActionIcon>
</Tooltip>
<DocsButton doc="porthijack" size="xl" />
</Box>
</Box>
</>}
<AddNewService opened={open} onClose={closeModal} />