{"id":50686199,"url":"https://github.com/buzzqw/log2iptables","last_synced_at":"2026-06-08T23:03:23.948Z","repository":{"id":351989923,"uuid":"1213336234","full_name":"buzzqw/log2iptables","owner":"buzzqw","description":"Automatic IP blocking from log files — bruteforce, port scans, web attacks","archived":false,"fork":false,"pushed_at":"2026-05-26T09:34:42.000Z","size":63,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-26T11:28:50.861Z","etag":null,"topics":["blocklist","bruteforce-attacks","iptables","linux","log2iptables","security","ssh"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/buzzqw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-17T09:18:45.000Z","updated_at":"2026-05-26T09:34:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/buzzqw/log2iptables","commit_stats":null,"previous_names":["buzzqw/log2iptables"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/buzzqw/log2iptables","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buzzqw%2Flog2iptables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buzzqw%2Flog2iptables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buzzqw%2Flog2iptables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buzzqw%2Flog2iptables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/buzzqw","download_url":"https://codeload.github.com/buzzqw/log2iptables/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buzzqw%2Flog2iptables/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34083848,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blocklist","bruteforce-attacks","iptables","linux","log2iptables","security","ssh"],"created_at":"2026-06-08T23:03:20.618Z","updated_at":"2026-06-08T23:03:23.942Z","avatar_url":"https://github.com/buzzqw.png","language":"Shell","funding_links":["https://www.paypal.com/cgi-bin/webscr?cmd=_donations\u0026business=azanzani@gmail.com\u0026item_name=Support+Log2Iptables+Project"],"categories":[],"sub_categories":[],"readme":"# log2iptables\n\n\u003e Automatic IP blocking from log files — bruteforce, port scans, web attacks, and more.\n\n## Support the project\n\nIf you find log2iptables useful and want to thank the developer for his work, you can buy him a coffee via PayPal. Any contribution, big or small, is greatly appreciated and helps keep the project alive and actively developed!\n\n[![Donate with PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations\u0026business=azanzani@gmail.com\u0026item_name=Support+Log2Iptables+Project)\n\n*Thank you so much!* 🙏\n\n---\n\n**log2iptables** is a Bash script that parses log files (or systemd journals) and automatically blocks offending IP addresses via `iptables`, `ip6tables`, and `/etc/hosts.deny`. It requires no external dependencies beyond standard Linux tools and runs entirely in bash.\n\n---\n\n## Features\n\n- **Multi-pattern detection** — SSH bruteforce, invalid user scans, preauth disconnects, port scanners, sudo abuse, PAM failures, web scanners (Nikto, 404 floods), FTP/SMTP/IMAP attacks, all in a single pass\n- **Time window** — optionally limit analysis to the last N hours (`-w`) to avoid blocking on ancient log history\n- **Auto-detect log source** — prefers `journalctl` on systemd systems, falls back to `/var/log/auth.log` automatically\n- **Dual blocking** — blocks via both `iptables`/`ip6tables` and `/etc/hosts.deny`\n- **IPv6 support** — optional `ip6tables` integration via `-6`\n- **Whitelist** — reads `/etc/hosts.allow`, supports exact IPs and CIDR notation (pure bash, no `ipcalc` needed)\n- **Unblock** — remove an IP from all blocking mechanisms with a single flag\n- **Dry-run mode** — safe testing without touching iptables, hosts.deny, or sending any notifications\n- **Lock file** — prevents concurrent executions (safe for cron), atomic creation to avoid race conditions\n- **Notifications** — Telegram bot, HTTP POST, email via sendmail (production mode only, never in dry-run)\n- **Custom commands** — execute arbitrary commands on new blocks, with `IPLISTCSV`/`IPLISTPIPE` placeholders\n- **Legacy mode** — fully retrocompatible with the original single-regex `-r/-p/-l` interface\n\n---\n\n## Requirements\n\n**Required:**\n- `bash` 4.0+ (for associative arrays and `mapfile`)\n- `iptables`\n- `grep`, `wc`, `column` (standard coreutils)\n\n**Optional:**\n- `ip6tables` — for IPv6 blocking (`-6`)\n- `journalctl` — for systemd journal reading\n- `curl` — for Telegram and HTTP POST notifications\n- `sendmail` — for email notifications\n- `sed` — for IP unblocking from hosts.deny\n\n---\n\n## Installation\n\n```bash\ngit clone https://github.com/youruser/log2iptables.git\ncd log2iptables\nchmod +x log2iptables.sh\n```\n\nNo compilation, no Python, no Node. Just bash.\n\n---\n\n## Quick Start\n\n**Simplest usage** — auto-detects log source, applies all patterns, dry-run:\n```bash\nsudo ./log2iptables.sh\n```\n\n**Production mode** — actually blocks IPs:\n```bash\nsudo ./log2iptables.sh -x 1\n```\n\n**Last 24 hours only** (recommended for cron):\n```bash\nsudo ./log2iptables.sh -x 1 -w 24\n```\n\n**Lower the threshold** for all patterns at once:\n```bash\nsudo ./log2iptables.sh -x 1 -l 3\n```\n\n**Unblock an IP:**\n```bash\nsudo ./log2iptables.sh -x 1 -d 1.2.3.4\n```\n\n---\n\n## Usage\n\n```\nUsage: log2iptables.sh -x [0|1] [options]\n\n  -h              This help\n  -f \u003cfile\u003e       Force reading from a log file (default: /var/log/auth.log)\n  -j \u003cunit\u003e       Force reading from journalctl (e.g. 'ssh')\n                  Default: auto-detect (journalctl if active, otherwise auth.log)\n  -w \u003chours\u003e      Time window: only consider log lines from the last N hours\n                  (default: 0 = all history). Recommended: -w 24 for cron use.\n  -l \u003cnumber\u003e     Global threshold: overrides per-pattern thresholds\n  -x \u003c1|0\u003e        Production mode: 1=execute, 0=dry-run (default: 0)\n  -a \u003caction\u003e     iptables action (-j argument, default: DROP)\n  -i \u003cI|A\u003e        iptables insert (I) or append (A) mode (default: I)\n  -c \u003cchain\u003e      iptables chain (INPUT, OUTPUT, etc., default: INPUT)\n  -6              Enable IPv6 support via ip6tables\n  -d \u003cip\u003e         Unblock an IP: removes from iptables and hosts.deny\n\n  -m \u003caddress\u003e    Send email when new rules are added\n  -M \u003caddress\u003e    Mail from address\n  -X \u003ccmd\u003e        Execute command after new rules (use IPLISTCSV or IPLISTPIPE as placeholders)\n\n  -u \u003c1|0\u003e        Enable HTTP POST request (default: 0)\n  -U \u003curl\u003e        Destination URL\n  -H \u003cparam\u003e      Extra curl header parameters\n\n  -t \u003c1|0\u003e        Send Telegram message (default: 0)\n  -T \u003ctoken\u003e      Telegram bot token\n  -C \u003cchat id\u003e    Telegram chat ID\n\nLegacy single-pattern mode (backward compatible):\n  -r \u003cregex\u003e      Custom regular expression (activates single-pattern mode)\n  -p \u003cnumber\u003e     Regex group number containing the IP address\n  -l \u003cnumber\u003e     Match threshold (required in legacy mode)\n```\n\n---\n\n## Default Patterns\n\nIn automatic multi-pattern mode (default, no `-r`), all of the following patterns are applied simultaneously on a single log read:\n\n| Pattern | What it detects | Default threshold |\n|---|---|---|\n| SSH bruteforce | Failed password / authentication (`sshd`) | 5 |\n| SSH invalid user | Non-existent username probes (`Invalid user`) | 5 |\n| SSH disconnect preauth | Disconnected before authentication — typical scanner | 10 |\n| SSH no auth | Port scanner: no identification string sent | 10 |\n| sudo abuse | Unauthorized escalation attempts | 3 |\n| PAM failure | Generic PAM authentication failure with IP | 5 |\n| Web scan Nikto | Nikto scanner in nginx/apache logs | 1 |\n| Web scan 404 | 404 flood from the same IP | 20 |\n| FTP bruteforce | Failed logins (vsftpd, proftpd) | 5 |\n| SMTP bruteforce | Failed SASL auth (postfix) | 5 |\n| IMAP bruteforce | Failed logins (dovecot) | 5 |\n\n\u003e **Note:** Web scan patterns (Nikto, 404) are designed for web server access logs. They will never match `/var/log/auth.log`. Use `-f /var/log/nginx/access.log` or `-f /var/log/apache2/access.log` to activate them.\n\nPatterns are defined as four parallel bash arrays at the top of the script (`PATTERN_NAMES`, `PATTERN_REGEX`, `PATTERN_IPPOS`, `PATTERN_LIMIT`). To disable a pattern, comment out its entry in all four arrays. To add a new one, append a line to each array at the same index.\n\n---\n\n## Log Source Auto-Detection\n\nThe script automatically selects the best available log source:\n\n```\njournalctl ≥50 lines  +  auth.log exists  →  read BOTH, deduplicated (streaming awk)\njournalctl ≥50 lines  +  no auth.log      →  journalctl only\nno journalctl          +  auth.log exists  →  auth.log only\nneither available                          →  error with guidance\n```\n\nOn Debian/Ubuntu with rsyslog active, SSH/PAM/sudo logs are intercepted by rsyslog and written to `/var/log/auth.log` before journald sees them. Reading only the journal would miss all authentication events. In `both` mode the two sources are merged and deduplicated (via streaming `awk '!seen[$0]++'`) so each event is counted exactly once.\n\nOverride with `-j \u003cunit\u003e` (force journalctl) or `-f \u003cfile\u003e` (force file).\n\n---\n\n## Time Window (-w)\n\nBy default the script processes the entire log history. This means an IP that had 5 failed SSH attempts two years ago would still be blocked today. The `-w` flag limits analysis to the last N hours:\n\n```bash\n# Only look at events from the last 24 hours\nsudo ./log2iptables.sh -x 1 -w 24\n```\n\nFor journalctl sources, `-w` uses `journalctl --since` (exact). For file sources, lines are filtered by comparing syslog timestamps (works correctly within the same month; may miss lines at month boundaries). This is the recommended mode for cron use.\n\n---\n\n## Whitelist\n\nAny IP present in `/etc/hosts.allow` is automatically skipped. The whitelist supports:\n\n- **Exact match**: `ALL: 1.2.3.4`\n- **CIDR notation**: `sshd: 192.168.1.0/24`\n\nThe CIDR check is implemented in pure bash with bitwise arithmetic — no `ipcalc` required. Prefix-style wildcards (e.g. `ALL: 10.0.`) are intentionally not supported to prevent accidentally whitelisting IPs that share a numeric prefix with a listed entry.\n\n---\n\n## Dry-Run Mode\n\nRunning without `-x 1` activates dry-run mode: no iptables rules are written, no hosts.deny entries are added, and **no notifications are sent** (Telegram, email, HTTP POST, custom commands). This makes dry-run safe for testing without side effects.\n\n---\n\n## Cron Setup\n\nRun every 5 minutes, only looking at the last 30 minutes of logs:\n```\n*/5 * * * * root /path/to/log2iptables.sh -x 1 -w 1 \u003e\u003e /var/log/log2iptables.log 2\u003e\u00261\n```\n\nOr run once per hour, looking at the last 2 hours (with overlap to tolerate missed runs):\n```\n0 * * * * root /path/to/log2iptables.sh -x 1 -w 2 \u003e\u003e /var/log/log2iptables.log 2\u003e\u00261\n```\n\nThe lock file at `/var/run/log2iptables.lock` prevents overlapping runs. It is created atomically (bash `noclobber`) to avoid race conditions. Stale locks from crashed instances are automatically detected and removed.\n\n---\n\n## Notifications\n\nNotifications are only sent in **production mode** (`-x 1`). Dry-run runs never send notifications.\n\n### Telegram\n```bash\nsudo ./log2iptables.sh -x 1 -t 1 -T \"your_bot_token\" -C \"your_chat_id\"\n```\n\n### Email\n```bash\nsudo ./log2iptables.sh -x 1 -m \"admin@example.com\" -M \"log2iptables@yourhost\"\n```\n\n### HTTP POST\n```bash\nsudo ./log2iptables.sh -x 1 -u 1 -U \"https://yourserver/endpoint\"\n```\n\n### Custom command\nRun a script after new blocks, with the IP list injected:\n```bash\nsudo ./log2iptables.sh -x 1 -X \"echo IPLISTCSV \u003e\u003e /var/log/blocked.csv\"\n```\nUse `IPLISTCSV` (comma-separated) or `IPLISTPIPE` (pipe-separated) as placeholders.\n\n---\n\n## Examples\n\nBlock all SSH attackers with 3+ attempts in the last 24 hours, notify via Telegram:\n```bash\nsudo ./log2iptables.sh -x 1 -w 24 -l 3 -t 1 -T \"TOKEN\" -C \"CHATID\"\n```\n\nForce journalctl for SSH, dry-run to preview:\n```bash\nsudo ./log2iptables.sh -j ssh\n```\n\nBlock from a web server access log (enables Nikto/404 patterns):\n```bash\nsudo ./log2iptables.sh -x 1 -f /var/log/nginx/access.log -w 24\n```\n\nLegacy mode — custom regex, single pattern:\n```bash\nsudo ./log2iptables.sh -x 1 -f /var/log/auth.log \\\n  -r 'sshd.*(f|F)ail.*(\\=| )([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})' \\\n  -p 3 -l 5\n```\n\nUnblock an IP (dry-run first):\n```bash\nsudo ./log2iptables.sh -d 87.251.64.147\nsudo ./log2iptables.sh -x 1 -d 87.251.64.147\n```\n\n---\n\n## Sample Output\n\n```\n[DRY-RUN] No changes will be applied. Use -x 1 for production mode.\n\nWhitelist: 1 address(es) loaded from /etc/hosts.allow.\nWARN: Web scan patterns (Nikto, 404) require a web server access log.\n      Current log: /var/log/auth.log. Use -f /var/log/nginx/access.log to enable them.\n\nLog source: journalctl + /var/log/auth.log (auto-detect: reading both to ensure full coverage)\nTime window: last 24 hour(s) only.\nLog lines read: 4821 (source: both)\n\n[Multi-pattern automatic mode — 11 active patterns]\n\n[Pattern] SSH bruteforce (threshold: 5) — 2 unique IP(s) seen\n[Found] 87.251.64.147 matched 20 time(s) — above threshold\n   `-- [Skip ] 87.251.64.147 already present in iptables.\n   `-- [Skip ] 87.251.64.147 already present in /etc/hosts.deny.\n[Watch] 12.34.56.78 matched 2 time(s) — below threshold (5)\n\n[Pattern] SSH invalid user (threshold: 5) — 1 unique IP(s) seen\n[Found] 203.0.113.5 matched 12 time(s) — above threshold\n   `-- [Add  ] 203.0.113.5 added to iptables (-j DROP) [DRY-RUN]\n   `-- [Add  ] 203.0.113.5 added to /etc/hosts.deny [DRY-RUN]\n\n[Pattern] SSH disconnect preauth (threshold: 10) — 0 unique IP(s) seen\n   `-- [Clean] No matches found.\n\n[Currently blocked IPs]\n   5 IP(s) currently blocked:\n   [Block] 87.251.64.149  (iptables)\n   [Block] 87.251.64.147  (iptables + hosts.deny)\n\nDone.\n```\n\n---\n\n## History\n\n### Original (v1.x) — by Andrea \"theMiddle\" Menin\n\nThe original `log2iptables` was a single-file bash script created by Andrea Menin. Its design was intentionally minimal: one regex, one log file, one iptables command. Users specified everything on the command line — including the regular expression and the IP group position — which made it flexible but required manual invocation for every use case. It introduced Telegram and HTTP POST notification, a whitelist via `/etc/hosts.allow`, and predefined templates for common scenarios (SSH bruteforce, Nikto scans).\n\nThe original script had several limitations that accumulated over time:\n- The iptables check used `iptables -L | grep | wc -l`, which was slow on large rulesets and vulnerable to false positives (e.g. `1.2.3.4` matching `1.2.3.40`)\n- The `-e` template flag used `-eq` (numeric comparison) instead of `==` (string comparison), making predefined templates silently non-functional\n- IP deduplication during log parsing used an O(n²) nested loop\n- Backtick command substitution and `expr` arithmetic were used throughout\n- CIDR whitelist matching relied on `ipcalc` with fragile `grep | awk | cut` parsing that varied by distro\n- No locking mechanism, making cron-based use unsafe with large log files\n- `/etc/hosts.deny` was not updated alongside iptables\n\n### Enhanced (v2.x) — by Andres Zanzani\n\nVersion 2 was a complete audit and rewrite of the internals, keeping full backward compatibility with the v1 command-line interface.\n\n**v2.0** fixed all known bugs and added major features:\n- Fixed iptables check: replaced `grep | wc` with atomic `iptables -C` (O(1), no false positives)\n- Fixed template matching bug (`-eq` → `==`)\n- Replaced O(n²) IP parsing with O(1) associative array counting\n- Replaced all backticks and `expr` with modern `$(...)` and `$(( ))`\n- Replaced fragile ipcalc-based CIDR matching with pure bash bitwise arithmetic\n- Added lock file with PID validation and stale lock cleanup\n- Added `/etc/hosts.deny` integration (independent from iptables, respects dry-run)\n- Added IPv6 support via `ip6tables` (`-6`)\n- Added IP unblock mode (`-d`)\n- Added `journalctl` support (`-j`)\n- Added log source auto-detection (journalctl → auth.log fallback)\n- Graceful handling of missing optional binaries (curl, sendmail) with warnings instead of silent failures\n- Dry-run mode now consistently prevents all writes (iptables, hosts.deny)\n\n**v2.1** replaced the single-pattern model with automatic multi-pattern detection:\n- Introduced four parallel arrays (`PATTERN_NAMES`, `PATTERN_REGEX`, `PATTERN_IPPOS`, `PATTERN_LIMIT`) replacing the pipe-delimited `PATTERNS` array — the `|` separator conflicted with regex alternations like `(f|F)` and `(\\=| )`, silently corrupting patterns at parse time\n- Log file is read once into memory (`mapfile`), all patterns applied on the same data\n- Default patterns cover SSH, sudo, PAM, Nikto, 404 floods, FTP, SMTP, IMAP/POP3\n- Per-pattern thresholds configurable independently; `-l` overrides all at once\n- `run_pattern` now always prints results: `[Found]` above threshold, `[Watch]` below threshold, `[Clean]` if no matches — no more silent output\n- Added `[Currently blocked IPs]` section: reads directly from `iptables` and `hosts.deny` and reports all currently blocked IPs with their blocking source, shown on every run regardless of log content\n- Legacy single-pattern mode (`-r/-p/-l`) fully preserved for backward compatibility\n- `-e` template flag removed (superseded by always-on multi-pattern mode)\n- Full English translation of all output messages\n\n**v2.2** fixed log source coverage on Debian/Ubuntu:\n- Auto-detect now reads `journalctl` + `auth.log` simultaneously in `both` mode; on Debian with rsyslog active, SSH/PAM/sudo logs are intercepted before journald sees them, causing journal-only mode to return zero auth matches despite 18000+ system lines\n- Merged sources are deduplicated via `sort -u` so each event is counted exactly once\n- Log lines output now includes the effective source mode (`source: both`, `file`, etc.)\n\n**v2.3** — security audit and coverage improvements:\n- **Fixed `is_in_hosts_deny` false positives**: replaced `grep -qF \"$ip\"` (substring match) with an anchored regex `grep -qE \"^ALL:[[:space:]]*${ip}[[:space:]]*$\"` — the old code would falsely skip blocking `1.1.1.1` if `1.1.1.10` was already present\n- **Fixed dry-run notifications**: Telegram, email, HTTP POST, and custom commands are now gated by `IPTABLESEXEC=1`; dry-run runs no longer send any notifications\n- **Fixed whitelist prefix-glob false positives**: removed the `[[ \"$ip\" == ${key}* ]]` prefix match which would accidentally whitelist `1.2.3.40` when `1.2.3.4` was in the whitelist; only exact and CIDR matches are now used\n- **Fixed lock file race condition**: replaced the TOCTOU-prone check-then-write sequence with an atomic `(set -C; echo $$ \u003e \"$LOCKFILE\")` noclobber write\n- **Fixed `cidr_contains` input validation**: added bounds check on prefix length (must be 0–32) to prevent silent arithmetic errors on malformed CIDR entries\n- **Fixed journalctl auto-detect performance**: the initial line count now uses `-n 500` instead of reading the entire journal, avoiding multi-minute stalls on servers with large journals\n- **Fixed `sort -u` memory usage**: replaced with streaming `awk '!seen[$0]++'` deduplication in `both` mode — no longer loads the entire combined log into a sort buffer\n- **Fixed duplicate `declare -A addedip`**: removed the redundant declaration at line 522 (only one remains, before first use)\n- **Fixed `eval` command execution**: replaced `eval \"$CMDREPLACE\"` with `bash -c \"$CMDREPLACE\"` for explicit subprocess isolation\n- **Fixed `do_unblock` sed pattern**: anchored the sed pattern with `^` and `$` to prevent partial-line matches when removing hosts.deny entries\n- **Fixed `blocked_ips` grep in report section**: now uses anchored `^ALL:...$` pattern consistent with `is_in_hosts_deny`\n- **Added `-w \u003chours\u003e` time window**: limits log analysis to the last N hours; uses `journalctl --since` for journal sources and syslog timestamp comparison for file sources; prevents ancient log entries from triggering new blocks\n- **Added SSH invalid user pattern**: detects `Invalid user \u003cname\u003e from \u003cip\u003e` lines, a primary vector for automated credential scanning\n- **Added SSH disconnect preauth pattern**: detects `Disconnecting/Disconnected ... [preauth]` lines, typical signature of port scanners and brute-force tooling\n- **Added web pattern warning**: when web scan patterns are active but the log source is `auth.log` or `syslog`, a visible warning is printed explaining that those patterns require a web server access log\n\n---\n\n## License\n\nOriginal work © Andrea \"theMiddle\" Menin — [github.com/theMiddleBlue/log2iptables](https://github.com/theMiddleBlue/log2iptables)\n\nEnhancements © Andres Zanzani\n\nReleased under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuzzqw%2Flog2iptables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbuzzqw%2Flog2iptables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuzzqw%2Flog2iptables/lists"}