| img | ||
| pyfrc2g | ||
| pyfrc2g.egg-info | ||
| .gitignore | ||
| LICENSE | ||
| pyfrc2g.py | ||
| pyproject.toml | ||
| README.md | ||
| requirements.txt | ||
| setup.py | ||
PyFRC2G - Unified Firewall Rules to Graph Converter
Unified Python package to convert pfSense and OPNSense firewall rules into graphical flow diagrams.
Quick start: Configure pyfrc2g/config.py then run pyfrc2g or python -m pyfrc2g (API mode), or run pyfrc2g --backup config.xml to use an XML backup without API config.
👋 Overview
PyFRC2G was designed to meet two main objectives:
- Visual Documentation: Provide a global graphical view of firewall rules (a picture is worth a thousand words)
- Compliance Evidence: Provide evidence to meet IT security requirements defined in various compliance frameworks
⚡ Features
Core Features
- Two Input Modes: Fetch rules via API (pfSense/OPNSense) or read from XML backup (config.xml)
- Unified Support: Single package for both pfSense and OPNSense
- Automatic Interface Detection: Auto-detects all available interfaces for OPNSense
- API-Based Alias Mapping: Retrieves all aliases from firewall API or from the backup XML
- Per-Interface Output: Generates separate CSV and PDF files for each interface
- Smart Change Detection: Only regenerates graphs when rules have changed (MD5 comparison)
- Configuration Check: Validates
pyfrc2g/config.pybefore API mode (optional bypass with--skip-config-check) - Modular Architecture: Clean, maintainable, and extensible codebase
Technical Features
- Graphical Flows: Generates visual flow diagrams using Graphviz
- PDF Generation: Produces A4 PDF files with one page per interface
- Color Coding:
- 🟢 Green for PASS rules
- 🔴 Red for BLOCK rules
- 🟡 Yellow for disabled rules
- Network Mapping: Distinguishes between VLANs/networks and destination hosts
- Comprehensive Coverage: Handles floating rules, disabled rules, and all interface types
- CISO Assistant Integration: Optional automatic upload of PDFs to CISO Assistant as evidence revisions
📋 Prerequisites
Python Requirements
- Python 3.7 or higher
- Required packages (see Installation)
System Requirements
- Graphviz: Must be installed on your system
- Windows: Download from Graphviz website
- Linux:
sudo apt-get install graphviz(Debian/Ubuntu) orsudo yum install graphviz(RHEL/CentOS) - macOS:
brew install graphviz
Firewall API Setup
pfSense
- Install pfSense REST API Package: pfSense REST API Documentation
- Configure the listening interface(s) on pfSense
- Generate an API key for authentication
OPNSense
- Create API credentials in OPNSense:
- Go to System > Access > Users
- Create or edit a user
- Generate API key and secret in API Keys section
💾 Installation
Option 1: Install as Package (Recommended)
# Clone the repository
git clone https://github.com/olivierb46/PyFRC2G.git
cd PyFRC2G
# Install setuptools (required by setup.py)
pip install setuptools
# Install in development mode
pip install -e .
# Or install directly
pip install .
Option 2: Direct Usage
# Install dependencies
pip install -r requirements.txt
# Use the script directly
pyfrc2g
⚙️ Configuration
Configuration is required only for API mode. When using --backup, no API config is needed.
1. Edit Configuration File
Edit pyfrc2g/config.py to configure your gateway:
For pfSense:
GATEWAY_TYPE = "pfsense"
PFS_BASE_URL = "https://pfs01.domain.lan"
PFS_TOKEN = "YOUR_API_KEY_GENERATED_WITH_PFSENSE_REST_API"
GATEWAY_NAME = "PFS01"
For OPNSense:
GATEWAY_TYPE = "opnsense"
# OPNSense Configuration
OPNS_BASE_URL = "https://opnsense.domain.lan"
OPNS_KEY = "YOUR_API_KEY"
OPNS_SECRET = "YOUR_API_SECRET"
# Option 1: Auto-detection (recommended)
INTERFACES = [] # Leave empty for automatic detection
# Option 2: Manual specification
INTERFACES = ["wan", "lan", "opt1", "opt2"]
GATEWAY_NAME = "OPNS01" # Display name for gateway (used in labels)
2. Configuration Check (API Mode)
Before running in API mode, the tool checks that PFS_BASE_URL/PFS_TOKEN (pfSense) or OPNS_BASE_URL/OPNS_KEY/OPNS_SECRET (OPNSense) are not left as placeholders. If the config is invalid, the script exits with instructions. Use --skip-config-check to bypass (e.g. in scripts).
3. CISO Assistant Integration (Optional)
If you want to automatically upload generated PDFs to CISO Assistant as evidence revisions, configure the following in pyfrc2g/config.py:
# CISO Assistant Configuration
CISO_URL = "https://ciso-assistant.example.com"
CISO_TOKEN = "YOUR_CISO_ASSISTANT_API_TOKEN"
CISO_EVIDENCE_PATH = f"{CISO_URL}/api/evidence-revisions/"
CISO_FORLDER_ID = "<CISO_FOLDER_ID>" # Folder ID from CISO Assistant to which the evidence is linked.
CISO_EVIDENCE_ID = "<CISO_EVIDENCE_ID>" # Evidence ID from CISO Assistant.
Note: Leave these as default values (<CISO_ASSISTANT_ADDRESS>, etc.) to disable CISO Assistant integration.
4. Aliases (API Mode)
In API mode, the package automatically retrieves all aliases from the firewall API:
- Interface names and descriptions
- Network aliases
- Address aliases
- Port aliases
No manual alias mapping is required. In backup mode, aliases are read from the XML file.
🚀 Usage
Command-Line Options (argparse)
| Option | Short | Description |
|---|---|---|
--api |
-a |
Fetch rules from firewall API (default if no mode) |
--backup FILE |
-b |
Read rules from XML backup (pfSense or OPNSense config.xml) |
--gateway-name NAME |
-g |
Gateway display name (for backup or when not using API) |
--skip-config-check |
Skip configuration check before API mode | |
--debug |
-d |
Enable debug logging |
--verbose |
-v |
Verbose output (same as --debug) |
Basic Usage
Mode API (default)
Configure pyfrc2g/config.py, then run:
pyfrc2g
# or explicitly
pyfrc2g --api
Before running, a configuration check ensures that API URL and credentials are set. If the config is still using placeholders, the tool exits with a clear message. Use --backup to work without API config, or --skip-config-check to bypass (not recommended).
Mode XML Backup
Use a pfSense or OPNSense backup file (e.g. from Diagnostics > Backup & Restore). No API config needed.
pyfrc2g --backup config-backup.xml
# Optional: set gateway name (otherwise derived from filename)
pyfrc2g --backup config-backup.xml --gateway-name my-firewall
The tool detects automatically whether the backup is pfSense or OPNSense and parses rules and aliases from the XML. PDFs are generated the same way as in API mode.
Other Examples
# Debug / verbose
pyfrc2g --api --debug
pyfrc2g --backup config.xml --verbose
# Bypass config check (e.g. in scripts)
pyfrc2g --api --skip-config-check
As an Installed Package:
pyfrc2g
pyfrc2g --backup config.xml
As a Python Module:
from pyfrc2g import Config, APIClient, GraphGenerator
from pyfrc2g.main import main
# Option 1: Use the main function
main()
# Option 2: Use components directly
config = Config()
api_client = APIClient(config)
graph_generator = GraphGenerator(config)
# Fetch aliases
api_client.fetch_aliases()
# Fetch rules
rules = api_client.fetch_rules()
# Generate graphs
graph_generator.generate_graphs(csv_path, output_dir)
What the Script Does
Mode API
- Runs a configuration check (unless
--skip-config-checkor--backupis used) - Connects to your gateway (pfSense or OPNSense)
- Fetches all aliases and firewall rules from the API
- Auto-detects interfaces (for OPNSense, if not specified)
Mode Backup
- Parses the XML backup (pfSense or OPNSense), extracts rules and aliases
- No API call; gateway type and name come from the file or
--gateway-name
Common steps 5. Generates a temporary CSV file with all rules 6. Compares with previous version (MD5 checksum) 7. If changes detected, generates graphs and PDFs (Graphviz + ReportLab) 8. Uploads PDFs to CISO Assistant (if configured)
Generated Files
The script generates files in results/<GATEWAY_NAME>/:
Global Files:
<GATEWAY_NAME>_FLOW_MATRIX.pdf- PDF with all interfaces (one page per interface)
Per-Interface Files:
<GATEWAY_NAME>_<interface>_flows.csv- CSV file with rules for specific interface<GATEWAY_NAME>_<interface>_FLOW_MATRIX.pdf- PDF with graphs for specific interface
Tracking:
md5sum.txt- MD5 hash of last generated CSV (for change detection)
Example Output Structure
results/PFS01/
├── PFS01_FLOW_MATRIX.pdf # Global PDF (all interfaces)
├── PFS01_wan_FLOW_MATRIX.pdf # WAN interface PDF
├── PFS01_wan_flows.csv # WAN interface CSV
├── PFS01_lan_FLOW_MATRIX.pdf # LAN interface PDF
├── PFS01_lan_flows.csv # LAN interface CSV
└── PFS01_opt1_FLOW_MATRIX.pdf # OPT1 interface PDF
📊 Output Format
CSV Columns
The temporary and per-interface CSV files use the same columns for both pfSense and OPNsense:
| Column | Description |
|---|---|
| SOURCE | Source network or address (mapped from API aliases when available) |
| GATEWAY | Gateway name and interface(s), e.g. OPNS01/wan,lan or OPNS01/Floating-rules |
| ACTION | Pass, block, reject (mapped to display value) |
| PROTOCOL | IP layer and protocol: IPv4 tcp, IPv6 udp, IPv4+IPv6 Any, etc. Empty protocol is shown as Any. |
| PORT | Destination port or range |
| DESTINATION | Destination network or address |
| COMMENT | Rule description |
| DISABLED | True / False |
| FLOATING | True for floating rules |
| RULE ORDER | Rule order index |
PDF Content
The generated PDFs contain:
- One page per interface with flow diagrams
- One page for floating rules when applicable
- Graphical flow diagrams showing:
- Sources: Network/host sources
- Gateway/Interface: Firewall interface name
- Actions: PASS (green) / BLOCK (red) with color coding
- Protocols: IP protocol (e.g. IPv4 tcp, IPv6 Any)
- Ports: Destination ports or port ranges
- Destinations: Network/host destinations
- Comments: Rule descriptions
- Disabled Rules: Highlighted in yellow
🏗️ Project Structure
PyFRC2G/
├── pyfrc2g/ # Main package
│ ├── __init__.py # Package initialization and exports
│ ├── config.py # Configuration management
│ ├── config_checker.py # Configuration validation (API mode)
│ ├── api_client.py # API client for firewalls
│ ├── xml_parser.py # XML backup parser (pfSense/OPNSense)
│ ├── graph_generator.py # Graph and PDF generation
│ ├── ciso_client.py # CISO Assistant integration
│ ├── utils.py # Utility functions
│ └── main.py # CLI and main execution logic
├── pyfrc2g.py # Compatibility launcher (python pyfrc2g.py)
├── pyproject.toml # Build and metadata (PEP 517/621)
├── setup.py # Package installation (minimal; use pyproject.toml)
├── requirements.txt # Python dependencies
├── README.md # This file
└── img/ # Example images
Module Descriptions
config.py
- Configuration class and constants
- Gateway type settings (pfSense/OPNSense)
- API credentials management
- Output paths configuration
config_checker.py
- Validates
pyfrc2g/config.pybefore running in API mode - Ensures API URL and credentials are not placeholders
- Optional prompt to continue on warnings;
--skip-config-checkto bypass
api_client.py
APIClientclass for firewall API interactions- Alias retrieval (interfaces, networks, addresses, ports)
- Firewall rules retrieval
- Interface auto-detection for both pfSense and OPNSense
xml_parser.py
- Parses pfSense and OPNSense XML backup files (config.xml)
- Auto-detects backup type from root element
- Extracts rules and aliases in API-compatible format
graph_generator.py
GraphGeneratorclass for graph and PDF generation- CSV parsing and grouping by interface
- Graphviz graph creation
- PDF generation from PNG files (ReportLab)
utils.py
- Utility functions (MD5, URL extraction, filename sanitization)
- Value mapping using API aliases
- Global API alias maps management
main.py
- Main execution function (API or backup mode)
- Configuration check for API mode
- Orchestrates the entire workflow
- Change detection using MD5
- File cleanup
- CISO Assistant integration
ciso_client.py
CISOCClientclass for CISO Assistant integration- Uploads generated PDFs as evidence revisions
- Handles authentication and error reporting
🔍 pfSense: Interfaces and Rules
Automatic Interface Detection
When INTERFACES is empty, the package tries to detect pfSense interfaces in this order:
- Interfaces API (v2) —
GET /api/v2/interfaces; usesidof each enabled interface (skipslo0,enc0,pflog0). - Fallback (v1) —
GET /api/v1/firewall/interface; uses theiffield from the response. - From firewall rules — If both above fail, interfaces are extracted from the list of rules returned by the global rules API.
If detection fails, rules are still fetched globally; for per-interface CSV/PDF you can set INTERFACES = ["wan", "lan", "opt1"] in pyfrc2g/config.py.
Rules Fetching (pfSense)
- Global rules — Fetched first from the pfSense firewall rules endpoint (
datain the response). - Per-interface rules — If interfaces were specified or detected, rules are also requested per interface (with
interfacequery when supported); entries are filtered by interface so each rule appears under the correct interface.
Rule identity uses tracker or id. The same _normalize_floating_rules logic applies: rules with interface floating or no interface are tagged as floating; the GATEWAY column shows the interface list or "Floating-rules" accordingly. The API may return interface as a list (e.g. multiple interfaces); it is normalized for display.
Example Logs
INFO:root:Attempting auto-detection of interfaces...
INFO:root:✓ 2 interfaces detected: ['wan', 'lan']
INFO:root: → 85 global rules retrieved
INFO:root:Fetching rules for interface: wan
INFO:root: → 24 rules found for wan
INFO:root:Fetching rules for interface: lan
INFO:root: → 32 rules found for lan
INFO:root:✓ Total of 85 unique rules retrieved
🔍 OPNsense: Interfaces and Rules
Automatic Interface Detection
The package attempts multiple methods to automatically detect interfaces:
- Interface API:
/api/core/interfaces/listAllor/api/core/interfaces/list - From Firewall Rules: Analyzes all rules to extract used interfaces
- Fallback: If auto-detection fails, specify interfaces manually in
INTERFACES
The floating interface is always included so that floating rules are fetched from the API.
Rules Fetching (OPNSense)
Rules are retrieved in two steps for accurate protocol information:
- Global rules — Fetched first to get the full list (with
show_all=1). - Per-interface rules — Fetched for each interface (lan, wan, floating, etc.). When a rule already exists (same UUID), its fields (e.g.
ipprotocol,protocol) are updated from the per-interface response, which often contains complete data.
Floating rules are tagged (floating=True, interface=floating). The GATEWAY column shows Floating-rules for floating-only rules, or the interface list (e.g. wan,lan) when the rule is bound to specific interfaces.
Detection Logs
INFO:root:Attempting auto-detection of interfaces...
INFO:root:✓ Auto-detected interfaces: ['lan', 'wan']
INFO:root:Including 'floating' interface to fetch floating rules
INFO:root: → 42 global rules retrieved
INFO:root:Fetching rules for interface: lan
...
INFO:root:✓ Total of 42 unique rules retrieved
🛠️ Troubleshooting
Configuration check fails (API mode)
If you see "Configuration is missing or invalid":
- Edit
pyfrc2g/config.pyand setPFS_BASE_URL/PFS_TOKEN(pfSense) orOPNS_BASE_URL/OPNS_KEY/OPNS_SECRET(OPNSense) to real values. - Or use
--backup config.xmlto read from an XML backup instead of the API. - Or use
--skip-config-checkonly if you are sure the config is valid.
Error: "Could not auto-detect interfaces"
Solution: Manually specify interfaces in pyfrc2g/config.py:
INTERFACES = ["wan", "lan", "opt1"]
API Connection Error
Check:
- API URL is correct
- Credentials (token/secret/key) are valid
- SSL certificate (package ignores SSL errors with
verify=False) - Firewall allows API access from your IP
No Rules Retrieved
- Verify API returns data (test with curl or browser)
- For OPNSense, check that specified interfaces exist
- Check logs for detailed error messages
- Verify API user has proper permissions
Graphviz Not Found
Windows:
- Download and install Graphviz from official website
- Add Graphviz to system PATH
Linux:
sudo apt-get install graphviz # Debian/Ubuntu
sudo yum install graphviz # RHEL/CentOS
macOS:
brew install graphviz
PDF Generation Fails
- Ensure Graphviz is properly installed
- Check that PNG files are generated in output directory
- Verify write permissions in output directory
📝 Notes
- Change Detection: Package only regenerates PDFs when rules have changed (MD5 comparison)
- Force Regeneration: Delete or empty
md5sum.txtfile to force regeneration - Temporary Files: CSV and PNG files are automatically cleaned up after processing
- API Aliases: All aliases are fetched from API - no manual mapping needed
- Performance: Large rule sets may take several minutes to process
- CISO Assistant: PDFs are uploaded automatically after generation (if configured). Each upload creates a new revision in the evidence record, maintaining a history of firewall rule changes.
🔄 Migration from Old Versions
If you were using an older version:
- Configuration: Edit
pyfrc2g/config.py; a config check runs in API mode unless you use--skip-config-check. - Aliases: In API mode, aliases are fetched from the API; in backup mode, they are read from the XML.
- Interfaces: For OPNSense, you can leave
INTERFACES = []for auto-detection. - Usage: Run
pyfrc2gorpyfrc2g --apifor API;pyfrc2g --backup config.xmlfor XML backup.
🆕 What's New (recent)
Major Improvements
- Modular architecture — Codebase split into dedicated modules (
config,api_client,xml_parser,graph_generator,ciso_client, etc.) - Two input modes — API (pfSense/OPNSense) and XML backup (
config.xml) with--api/--backup - CLI (argparse) —
--api,--backup,--gateway-name,--skip-config-check,--debug/--verbose - Configuration check — Validates config before API mode (
config_checker.py, overridable with--skip-config-check) - XML backup parser — Rules and aliases read from pfSense/OPNSense backup files without API
- API-based aliases — No manual alias file in API mode; aliases fetched from API
- Per-interface output — Separate CSV and PDF per interface; filenames sanitized
- PROTOCOL column — Unified format for pfSense and OPNsense:
ipprotocol+protocol(e.g.IPv4 tcp,IPv6 Any). Empty protocol is displayed asAny. - CISO Assistant — Automatic upload of generated PDFs as evidence revisions
- Change detection — Graphs regenerated only when rules change (MD5 comparison)
- OPNSense support — Full support for OPNsense firewalls
📝 Todo
Planned improvements:
- Code improvements — Further improve code quality and structure
- Admin notifications — Notify administrators when graphs are generated
- Destination VLAN display — Show destination VLAN before de host in the graph
- Rule metadata — Retrieve timestamps and authors for rule creation/modification
- Enhanced error reporting — More detailed error messages and recovery suggestions
- Multiple gateway support — Process multiple gateways in a single run
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
See the LICENSE file for details.
📧 Support
For issues, questions, or contributions, please open an issue on the GitHub repository.
Made with ❤️ for network administrators and security professionals

