refactoring workflows

This commit is contained in:
Domingo Dirutigliano
2025-08-04 11:02:29 +02:00
parent f83928eae4
commit d868e046de
3 changed files with 235 additions and 99 deletions

View File

@@ -1,4 +1,4 @@
name: Create and publish a Docker image name: Create and publish Docker images
on: on:
release: release:
@@ -10,7 +10,7 @@ env:
IMAGE_NAME: ${{ github.repository }} IMAGE_NAME: ${{ github.repository }}
jobs: jobs:
build-and-push-image: build-amd64:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -26,11 +26,6 @@ jobs:
- name: Run tests - name: Run tests
run: sudo apt-get install -y iperf3 && cd tests && ./run_tests.sh run: sudo apt-get install -y iperf3 && cd tests && ./run_tests.sh
- name: Set up QEMU
uses: docker/setup-qemu-action@master
with:
platforms: all
- name: Set up Docker Buildx - name: Set up Docker Buildx
id: buildx id: buildx
uses: docker/setup-buildx-action@master uses: docker/setup-buildx-action@master
@@ -47,22 +42,182 @@ jobs:
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Extract tag name - name: Extract tag name
id: tag id: tag
run: echo TAG_NAME=$(echo $GITHUB_REF | cut -d / -f 3) >> $GITHUB_OUTPUT run: echo TAG_NAME=$(echo $GITHUB_REF | cut -d / -f 3) >> $GITHUB_OUTPUT
- name: Update version in setup.py - name: Update version in setup.py
run: >- run: >-
sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" backend/utils/__init__.py; sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" backend/utils/__init__.py;
sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" fgex-lib/setup.py; sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" fgex-lib/setup.py;
sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" fgex-lib/firegex/__init__.py; sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" fgex-lib/firegex/__init__.py;
- name: Build and push Docker image
- name: Build and push AMD64 Docker image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: . context: .
builder: ${{ steps.buildx.outputs.name }} builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64 platforms: linux/amd64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}-amd64
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha cache-from: type=gha,scope=amd64
cache-to: type=gha,mode=max cache-to: type=gha,mode=max,scope=amd64
build-arm64:
runs-on: ubuntu-latest-arm64
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build and run firegex
run: python3 start.py start -P testpassword
- name: Run tests
run: sudo apt-get install -y iperf3 && cd tests && ./run_tests.sh
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@master
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Extract tag name
id: tag
run: echo TAG_NAME=$(echo $GITHUB_REF | cut -d / -f 3) >> $GITHUB_OUTPUT
- name: Update version in setup.py
run: >-
sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" backend/utils/__init__.py;
sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" fgex-lib/setup.py;
sed -i "s/{{VERSION_PLACEHOLDER}}/${{ steps.tag.outputs.TAG_NAME }}/g" fgex-lib/firegex/__init__.py;
- name: Build and push ARM64 Docker image
uses: docker/build-push-action@v5
with:
context: .
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}-arm64
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=arm64
cache-to: type=gha,mode=max,scope=arm64
create-manifest:
runs-on: ubuntu-latest
needs: [build-amd64, build-arm64]
permissions:
contents: read
packages: write
steps:
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Create and push multi-platform manifest
run: |
# Create manifest list
docker buildx imagetools create \
--tag ${{ steps.meta.outputs.tags }} \
${{ steps.meta.outputs.tags }}-amd64 \
${{ steps.meta.outputs.tags }}-arm64
create-rootfs-assets:
runs-on: ubuntu-latest
needs: [create-manifest]
permissions:
contents: write
packages: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@master
with:
platforms: all
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@master
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get latest release tag
id: get_tag
run: |
LATEST_TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.tag_name')
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "Latest release tag: $LATEST_TAG"
- name: Export rootfs for amd64
run: |
echo "Creating and exporting amd64 container..."
CONTAINER_ID=$(docker create --platform linux/amd64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.tag }})
docker export $CONTAINER_ID --output="firegex-rootfs-amd64.tar"
docker rm $CONTAINER_ID
echo "Compressing amd64 rootfs..."
gzip firegex-rootfs-amd64.tar
ls -lh firegex-rootfs-amd64.tar.gz
- name: Export rootfs for arm64
run: |
echo "Creating and exporting arm64 container..."
CONTAINER_ID=$(docker create --platform linux/arm64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.tag }})
docker export $CONTAINER_ID --output="firegex-rootfs-arm64.tar"
docker rm $CONTAINER_ID
echo "Compressing arm64 rootfs..."
gzip firegex-rootfs-arm64.tar
ls -lh firegex-rootfs-arm64.tar.gz
- name: Calculate checksums
run: |
echo "Calculating checksums..."
sha256sum firegex-rootfs-amd64.tar.gz > firegex-rootfs-amd64.tar.gz.sha256
sha256sum firegex-rootfs-arm64.tar.gz > firegex-rootfs-arm64.tar.gz.sha256
cat *.sha256
- name: Upload rootfs assets to release
run: |
echo "Uploading assets to release ${{ steps.get_tag.outputs.tag }}..."
gh release upload ${{ steps.get_tag.outputs.tag }} \
firegex-rootfs-amd64.tar.gz \
firegex-rootfs-amd64.tar.gz.sha256 \
firegex-rootfs-arm64.tar.gz \
firegex-rootfs-arm64.tar.gz.sha256 \
--clobber
echo "Assets uploaded successfully!"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,87 +0,0 @@
name: Create Docker rootfs assets
on:
workflow_run:
workflows: ["Create and publish a Docker image"]
types:
- completed
branches:
- main
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
create-rootfs-assets:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
permissions:
contents: write
packages: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@master
with:
platforms: all
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@master
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get latest release tag
id: get_tag
run: |
LATEST_TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.tag_name')
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "Latest release tag: $LATEST_TAG"
- name: Export rootfs for amd64
run: |
echo "Creating and exporting amd64 container..."
CONTAINER_ID=$(docker create --platform linux/amd64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.tag }})
docker export $CONTAINER_ID --output="firegex-rootfs-amd64.tar"
docker rm $CONTAINER_ID
echo "Compressing amd64 rootfs..."
gzip firegex-rootfs-amd64.tar
ls -lh firegex-rootfs-amd64.tar.gz
- name: Export rootfs for arm64
run: |
echo "Creating and exporting arm64 container..."
CONTAINER_ID=$(docker create --platform linux/arm64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.tag }})
docker export $CONTAINER_ID --output="firegex-rootfs-arm64.tar"
docker rm $CONTAINER_ID
echo "Compressing arm64 rootfs..."
gzip firegex-rootfs-arm64.tar
ls -lh firegex-rootfs-arm64.tar.gz
- name: Calculate checksums
run: |
echo "Calculating checksums..."
sha256sum firegex-rootfs-amd64.tar.gz > firegex-rootfs-amd64.tar.gz.sha256
sha256sum firegex-rootfs-arm64.tar.gz > firegex-rootfs-arm64.tar.gz.sha256
cat *.sha256
- name: Upload rootfs assets to release
run: |
echo "Uploading assets to release ${{ steps.get_tag.outputs.tag }}..."
gh release upload ${{ steps.get_tag.outputs.tag }} \
firegex-rootfs-amd64.tar.gz \
firegex-rootfs-amd64.tar.gz.sha256 \
firegex-rootfs-arm64.tar.gz \
firegex-rootfs-arm64.tar.gz.sha256 \
--clobber
echo "Assets uploaded successfully!"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -9,6 +9,8 @@
Firegex is a firewall that includes different functionalities, created for CTF Attack-Defense competitions that has the aim to limit or totally deny malicious traffic through the use of different kind of filters. Firegex is a firewall that includes different functionalities, created for CTF Attack-Defense competitions that has the aim to limit or totally deny malicious traffic through the use of different kind of filters.
## Get started firegex ## Get started firegex
### Docker Mode (Recommended)
What you need is a linux machine and docker ( + docker-compose ) What you need is a linux machine and docker ( + docker-compose )
```bash ```bash
sh <(curl -sLf https://pwnzer0tt1.it/firegex.sh) sh <(curl -sLf https://pwnzer0tt1.it/firegex.sh)
@@ -19,6 +21,32 @@ Or, you can start in a similar way firegex, cloning this repository and executin
```bash ```bash
python3 start.py start --prebuilt python3 start.py start --prebuilt
``` ```
### Standalone Mode
If Docker is not available or you're running in a rootless environment, Firegex can run in standalone mode:
```bash
# Automatic detection (fallback to standalone if Docker unavailable)
python3 start.py start
# Force standalone mode
python3 start.py start --standalone
# Check status
python3 start.py status
# Stop standalone mode
python3 start.py stop
```
Standalone mode automatically:
- Downloads pre-built rootfs from GitHub releases
- Detects your architecture (amd64/arm64)
- Sets up chroot environment with necessary bind mounts
- Runs as a background daemon process
- Manages PID files for process control
If the server is restarted, docker mode will automatically restart the service, while standalone mode will require you to run the start command again manually.
Cloning the repository start.py will automatically build the docker image of firegex from source, and start it. Cloning the repository start.py will automatically build the docker image of firegex from source, and start it.
Image building of firegex will require more time, so it's recommended to use the version just builded and available in the github packages. Image building of firegex will require more time, so it's recommended to use the version just builded and available in the github packages.
This is default behaviour if start.py is not in the firegex source root directory. This is default behaviour if start.py is not in the firegex source root directory.
@@ -36,6 +64,46 @@ All the configuration at the startup is customizable in [firegex.py](./start.py)
- Port Hijacking allows you to redirect the traffic on a specific port to another port. Thanks to this you can start your own proxy, connecting to the real service using the loopback interface. Firegex will be resposable about the routing of the packets using internally [nftables](https://netfilter.org/projects/nftables/) - Port Hijacking allows you to redirect the traffic on a specific port to another port. Thanks to this you can start your own proxy, connecting to the real service using the loopback interface. Firegex will be resposable about the routing of the packets using internally [nftables](https://netfilter.org/projects/nftables/)
- EXPERIMENTAL: Netfilter Proxy uses [nfqueue](https://netfilter.org/projects/libnetfilter_queue/) to simulate a python proxy, you can write your own filter in python and use it to filter the traffic. There are built-in some data handler to parse protocols like HTTP, and before apply the filter you can test it with fgex command (you need to install firegex lib from pypi). - EXPERIMENTAL: Netfilter Proxy uses [nfqueue](https://netfilter.org/projects/libnetfilter_queue/) to simulate a python proxy, you can write your own filter in python and use it to filter the traffic. There are built-in some data handler to parse protocols like HTTP, and before apply the filter you can test it with fgex command (you need to install firegex lib from pypi).
## Deployment Modes
### Docker Mode
The default and recommended deployment method using Docker containers. Provides complete isolation and easy management.
### Standalone Mode
When Docker is not available or when running in environments where Docker cannot be used (e.g., rootless containers, restricted environments), Firegex can run in standalone mode.
**How Standalone Mode Works:**
1. **Automatic Detection**: If Docker is unavailable or in rootless mode, standalone mode is automatically enabled
2. **Rootfs Download**: Downloads pre-built filesystem archives from GitHub releases based on your architecture
3. **Chroot Environment**: Creates an isolated chroot environment with necessary system mounts
4. **Daemon Process**: Runs as a background daemon with PID management
5. **Process Control**: Provides start/stop/status commands for service management
**Standalone Mode Commands:**
```bash
# Start (automatically detects if standalone needed)
python3 start.py start
# Force standalone mode
python3 start.py --standalone start
# Check if running
python3 start.py status
# Stop the service
python3 start.py stop
# Clean up rootfs (removes downloaded files)
python3 start.py --clear-standalone
```
**Technical Details:**
- Downloads `firegex-rootfs-{arch}.tar.gz` from latest GitHub release
- Creates chroot environment in `~/.firegex/rootfs/`
- Bind mounts `/dev`, `/proc`, and network configuration files
- Manages daemon process with PID file in `~/.firegex/firegex.pid`
- Automatically handles privilege escalation using sudo when needed
## Documentation ## Documentation
Documentation about how the filters works, what features are available and how to use them are available on firegex interface. Documentation about how the filters works, what features are available and how to use them are available on firegex interface.