diff --git a/.goreleaser.yml b/.goreleaser.yml index 6b55a29..fbf775c 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -28,7 +28,7 @@ builds: env: - CGO_ENABLED=0 archives: - - format: tar.gz + - formats: [tar.gz] name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" nfpms: @@ -48,6 +48,15 @@ nfpms: scripts: postinstall: build/postinstall.sh postremove: build/postremove.sh + contents: + - src: docs/man/banforge.1 + dst: /usr/share/man/man1/banforge.1 + file_info: + mode: 0644 + - src: docs/man/banforge.5 + dst: /usr/share/man/man5/banforge.5 + file_info: + mode: 0644 release: gitea: owner: d3m0k1d @@ -60,7 +69,6 @@ changelog: exclude: - "^docs:" - "^test:" - checksum: name_template: "{{ .ProjectName }}_{{ .Version }}_checksums.txt" algorithm: sha256 diff --git a/Makefile b/Makefile index 693c6e7..91efba4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build build-daemon build-tui clean help +.PHONY: build build-daemon build-tui clean help install-man check-man help: @echo "BanForge build targets:" @@ -6,7 +6,9 @@ help: @echo " make build-daemon - Build only daemon" @echo " make build-tui - Build only TUI" @echo " make clean - Remove binaries" - @echo " make test - Run tests" + @echo " make test - Run tests" + @echo " make install-man - Install manpages to system" + @echo " make check-man - Validate manpage syntax" build: build-daemon build-tui @echo "✅ Build complete!" @@ -31,3 +33,16 @@ test-cover: lint: golangci-lint run --fix + +check-man: + @echo "Checking manpage syntax..." + @man -l docs/man/banforge.1 > /dev/null && echo "✅ banforge.1 OK" + @man -l docs/man/banforge.5 > /dev/null && echo "✅ banforge.5 OK" + +install-man: + @echo "Installing manpages..." + install -d $(DESTDIR)/usr/share/man/man1 + install -d $(DESTDIR)/usr/share/man/man5 + install -m 644 docs/man/banforge.1 $(DESTDIR)/usr/share/man/man1/banforge.1 + install -m 644 docs/man/banforge.5 $(DESTDIR)/usr/share/man/man5/banforge.5 + @echo "✅ Manpages installed!" diff --git a/docs/man/banforge.1 b/docs/man/banforge.1 new file mode 100644 index 0000000..4ff35bd --- /dev/null +++ b/docs/man/banforge.1 @@ -0,0 +1,249 @@ +.TH BANFORGE 1 "24 February 2026" "BanForge 1.0" +. +.SH NAME +banforge \- BanForge IPS utility for Linux +. +.SH SYNOPSIS +.B banforge +[\fIOPTIONS\fR] \fICOMMAND\fR [\fIARGUMENTS\fR] +. +.SH DESCRIPTION +BanForge is an Intrusion Prevention System (IPS) utility for Linux. +It monitors service logs, detects anomalies and malicious activity, +and automatically applies firewall rules to block suspicious IP addresses. +. +.PP +The program consists of two components: +.RS +.IP \(bu 2 +\fBbanforge\fR \- CLI utility for management +.IP \(bu 2 +\fBbanforge daemon\fR \- background service for real-time monitoring +.RE +. +.SH COMMANDS +. +.SS init \- Create configuration files +.PP +\fBbanforge init\fR +.PP +Creates the necessary directories and base configuration files: +.RS +.IP \(bu 2 +\fI/etc/banforge/config.toml\fR \- main configuration +.IP \(bu 2 +\fI/etc/banforge/rules.toml\fR \- default rules file +.IP \(bu 2 +\fI/etc/banforge/rules.d/\fR \- directory for individual rule files +.RE +. +.SS version \- Display BanForge version +.PP +\fBbanforge version\fR +.PP +Displays the current version of the BanForge software. +. +.SS daemon \- Start the BanForge daemon +.PP +\fBbanforge daemon\fR +.PP +Starts the BanForge daemon process in the background. +The daemon continuously monitors incoming requests, detects anomalies, +and applies firewall rules in real-time. +. +.SS firewall \- Manage firewall rules +.PP +\fBbanforge ban\fR \fI\fR [\fIOPTIONS\fR] +.br +\fBbanforge unban\fR \fI\fR +.PP +These commands provide an abstraction over your firewall. +.PP +\fBoptions:\fR +.RS +.IP \(bu 2 +\fB-t\fR, \fB--ttl\fR \- Ban duration (default: 1 year) +.RE +.PP +\fBExamples:\fR +.RS +.IP \(bu 2 +\fBbanforge ban 192.168.1.100 -t 1h\fR \- Ban IP for 1 hour +.IP \(bu 2 +\fBbanforge unban 192.168.1.100\fR \- Unban IP +.RE +. +.SS ports \- Manage firewall ports +.PP +\fBbanforge open\fR \fB-port\fR \fI\fR \fB-protocol\fR \fI\fR +.br +\fBbanforge close\fR \fB-port\fR \fI\fR \fB-protocol\fR \fI\fR +.PP +Open or close ports on the firewall. +.PP +\fBflags:\fR +.RS +.IP \(bu 2 +\fB-port\fR \- Port number (e.g., 80) \fI(required)\fR +.IP \(bu 2 +\fB-protocol\fR \- Protocol (tcp/udp) \fI(required)\fR +.RE +.PP +\fBExamples:\fR +.RS +.IP \(bu 2 +\fBbanforge open -port 80 -protocol tcp\fR +.IP \(bu 2 +\fBbanforge close -port 443 -protocol tcp\fR +.RE +. +.SS list \- List blocked IP addresses +.PP +\fBbanforge list\fR +.PP +Outputs a table of IP addresses that are currently blocked. +. +.SS rule \- Manage detection rules +.PP +Rules are stored in \fI/etc/banforge/rules.d/\fR as individual \fI.toml\fR files. +. +.SS "rule add \- Add a new rule" +.PP +\fBbanforge rule add\fR \fB-n\fR \fI\fR \fB-s\fR \fI\fR [\fIOPTIONS\fR] +.PP +\fBflags:\fR +.RS +.IP \(bu 2 +\fB-n\fR, \fB--name\fR \- Rule name (used as filename) \fI(required)\fR +.IP \(bu 2 +\fB-s\fR, \fB--service\fR \- Service name (nginx, apache, ssh, etc.) \fI(required)\fR +.IP \(bu 2 +\fB-p\fR, \fB--path\fR \- Request path to match +.IP \(bu 2 +\fB-m\fR, \fB--method\fR \- HTTP method (GET, POST, etc.) +.IP \(bu 2 +\fB-c\fR, \fB--status\fR \- HTTP status code (403, 404, etc.) +.IP \(bu 2 +\fB-t\fR, \fB--ttl\fR \- Ban duration (default: 1y) +.IP \(bu 2 +\fB-r\fR, \fB--max_retry\fR \- Max retries before ban (default: 0) +.RE +.PP +\fBNote:\fR At least one of \fB-p\fR, \fB-m\fR, or \fB-c\fR must be specified. +.PP +\fBExamples:\fR +.RS +.IP \(bu 2 +\fBbanforge rule add -n "Forbidden" -s nginx -c 403 -t 30m\fR +.IP \(bu 2 +\fBbanforge rule add -n "Admin Access" -s nginx -p "/admin/*" -t 2h -r 3\fR +.IP \(bu 2 +\fBbanforge rule add -n "SSH Bruteforce" -s ssh -c "Failed" -t 1h -r 5\fR +.RE +. +.SS "rule list \- List all rules" +.PP +\fBbanforge rule list\fR +.PP +Displays all configured rules in a table format. +. +.SS "rule edit \- Edit an existing rule" +.PP +\fBbanforge rule edit\fR \fB-n\fR \fI\fR [\fIOPTIONS\fR] +.PP +Edit fields of an existing rule. Only specified fields will be updated. +.PP +\fBflags:\fR +.RS +.IP \(bu 2 +\fB-n\fR, \fB--name\fR \- Rule name to edit \fI(required)\fR +.IP \(bu 2 +\fB-s\fR, \fB--service\fR \- New service name +.IP \(bu 2 +\fB-p\fR, \fB--path\fR \- New path +.IP \(bu 2 +\fB-m\fR, \fB--method\fR \- New method +.IP \(bu 2 +\fB-c\fR, \fB--status\fR \- New status code +.RE +.PP +\fBExamples:\fR +.RS +.IP \(bu 2 +\fBbanforge rule edit -n "SSH Bruteforce" -t 2h\fR +.IP \(bu 2 +\fBbanforge rule edit -n "Forbidden" -c 403\fR +.RE +. +.SS "rule remove \- Remove a rule" +.PP +\fBbanforge rule remove\fR \fI\fR +.PP +Permanently delete a rule by name. +.PP +\fBExample:\fR \fBbanforge rule remove "Old Rule"\fR +. +.SH "BAN TIME FORMAT" +.PP +Use the following suffixes for ban duration: +.RS +.IP \(bu 2 +\fBs\fR \- Seconds +.IP \(bu 2 +\fBm\fR \- Minutes +.IP \(bu 2 +\fBh\fR \- Hours +.IP \(bu 2 +\fBd\fR \- Days +.IP \(bu 2 +\fBM\fR \- Months (30 days) +.IP \(bu 2 +\fBy\fR \- Years (365 days) +.RE +.PP +\fBExamples:\fR 30s, 5m, 2h, 1d, 1M, 1y +. +.SH "CONFIGURATION FILES" +.PP +Configuration files are stored in \fI/etc/banforge/\fR: +.RS +.IP \(bu 2 +\fIconfig.toml\fR \- main daemon configuration +.IP \(bu 2 +\fIrules.toml\fR \- default rules +.IP \(bu 2 +\fIrules.d/*.toml\fR \- individual rule files +.RE +. +.SH "EXIT STATUS" +.PP +\fB0\fR \- Success +.br +\fB1\fR \- General error +.br +\fB2\fR \- Configuration error +. +.SH EXAMPLES +.PP +.RS +.IP \(bu 2 +Initialize configuration: \fBbanforge init\fR +.IP \(bu 2 +Start daemon: \fBbanforge daemon\fR +.IP \(bu 2 +Ban an IP: \fBbanforge ban 192.168.1.100 -t 1h\fR +.IP \(bu 2 +Add a rule: \fBbanforge rule add -n "404" -s nginx -c 404 -t 30m\fR +.IP \(bu 2 +List blocked IPs: \fBbanforge list\fR +.RE +. +.SH "SEE ALSO" +.BR iptables (8), +.BR nftables (8), +.BR fail2ban (1), +.BR nginx (8) +. +.SH AUTHOR +.PP +Ilya "d3m0k1d" Chernishev contact@d3m0k1d.ru diff --git a/docs/man/banforge.5 b/docs/man/banforge.5 new file mode 100644 index 0000000..9de837b --- /dev/null +++ b/docs/man/banforge.5 @@ -0,0 +1,339 @@ +.TH BANFORGE 5 "24 February 2026" "BanForge 1.0" +. +.SH NAME +banforge \- BanForge configuration file format +. +.SH DESCRIPTION +BanForge uses TOML configuration files stored in \fI/etc/banforge/\fR: +.RS +.IP \(bu 2 +\fIconfig.toml\fR \- main daemon configuration +.IP \(bu 2 +\fIrules.toml\fR \- default rules (legacy) +.IP \(bu 2 +\fIrules.d/*.toml\fR \- individual rule files (recommended) +.RE +. +.SH "CONFIG.TOML FORMAT" +.PP +Main configuration file for BanForge daemon. +.PP +\fBStructure:\fR +.RS +.IP \(bu 2 +\fB[firewall]\fR \- firewall parameters +.IP \(bu 2 +\fB[[service]]\fR \- service monitoring configuration (multiple allowed) +.IP \(bu 2 +\fB[metrics]\fR \- Prometheus metrics configuration (optional) +.RE +. +.SS "Firewall Section" +.PP +\fB[firewall]\fR +.PP +Defines firewall parameters. The \fBbanforge init\fR command automatically +detects your installed firewall (nftables, iptables, ufw, firewalld). +.PP +\fBFields:\fR +.RS +.IP \(bu 2 +\fBname\fR \- Firewall type (nftables, iptables, ufw, firewalld) +.IP \(bu 2 +\fBconfig\fR \- Path to firewall configuration file +.RE +.PP +\fBExample:\fR +.RS +.nf +[firewall] + name = "nftables" + config = "/etc/nftables.conf" +.fi +.RE +. +.SS "Service Section" +.PP +\fB[[service]]\fR +.PP +Configures service monitoring. Multiple service blocks are allowed. +.PP +\fBFields:\fR +.RS +.IP \(bu 2 +\fBname\fR \- Service name (nginx, apache, ssh, etc.) \fI(required)\fR +.IP \(bu 2 +\fBlogging\fR \- Log source type: "file" or "journald" \fI(required)\fR +.IP \(bu 2 +\fBlog_path\fR \- Path to log file or journal unit name \fI(required)\fR +.IP \(bu 2 +\fBenabled\fR \- Enable/disable service monitoring (true/false) +.RE +.PP +\fBExamples:\fR +.RS +.nf +# File-based logging +[[service]] + name = "nginx" + logging = "file" + log_path = "/var/log/nginx/access.log" + enabled = true + +# Journald logging +[[service]] + name = "nginx" + logging = "journald" + log_path = "nginx" + enabled = false +.fi +.RE +.PP +\fBNote:\fR When using journald logging, specify the service name in \fBlog_path\fR. +. +.SS "Metrics Section" +.PP +\fB[metrics]\fR +.PP +Configures Prometheus metrics endpoint (optional). +.PP +\fBFields:\fR +.RS +.IP \(bu 2 +\fBenabled\fR \- Enable/disable metrics (true/false) +.IP \(bu 2 +\fBport\fR \- Port for metrics endpoint +.RE +.PP +\fBExample:\fR +.RS +.nf +[metrics] + enabled = true + port = 9090 +.fi +.RE +. +.SH "RULES.TOML FORMAT" +.PP +Detection rules define conditions for blocking IP addresses. +Rules are stored in \fI/etc/banforge/rules.d/\fR as individual \fI.toml\fR files. +. +.SS "Rule Section" +.PP +\fB[[rule]]\fR +.PP +Defines a single detection rule. +.PP +\fBFields:\fR +.RS +.IP \(bu 2 +\fBname\fR \- Rule name (used as filename) \fI(required)\fR +.IP \(bu 2 +\fBservice\fR \- Service name (nginx, apache, ssh, etc.) \fI(required)\fR +.IP \(bu 2 +\fBpath\fR \- Request path to match (e.g., "/admin/*", "*.php") +.IP \(bu 2 +\fBstatus\fR \- HTTP status code (403, 404, 304, etc.) +.IP \(bu 2 +\fBmethod\fR \- HTTP method (GET, POST, etc.) +.IP \(bu 2 +\fBmax_retry\fR \- Max retries before ban (0 = ban on first request) +.IP \(bu 2 +\fBban_time\fR \- Ban duration (e.g., "1m", "1h", "1d", "1M", "1y") +.RE +.PP +\fBNote:\fR At least one of \fBpath\fR, \fBstatus\fR, or \fBmethod\fR must be specified. +.PP +\fBExamples:\fR +.RS +.nf +# Ban on HTTP 304 status +[[rule]] + name = "304 http" + service = "nginx" + path = "" + status = "304" + max_retry = 3 + method = "" + ban_time = "1m" + +# Ban on path pattern (admin panel) +[[rule]] + name = "Admin Access" + service = "nginx" + path = "/admin/*" + status = "" + method = "" + max_retry = 2 + ban_time = "2h" + +# SSH brute force protection +[[rule]] + name = "SSH Bruteforce" + service = "ssh" + path = "" + status = "Failed" + method = "" + max_retry = 5 + ban_time = "1h" +.fi +.RE +. +.SH "BAN TIME FORMAT" +.PP +Use the following suffixes for ban duration: +.RS +.IP \(bu 2 +\fBs\fR \- Seconds +.IP \(bu 2 +\fBm\fR \- Minutes +.IP \(bu 2 +\fBh\fR \- Hours +.IP \(bu 2 +\fBd\fR \- Days +.IP \(bu 2 +\fBM\fR \- Months (30 days) +.IP \(bu 2 +\fBy\fR \- Years (365 days) +.RE +. +.SH "ACTIONS(NOT WORKING ON THIS VERSION)" +.PP +Rules can trigger custom actions when an IP is banned. +. +.SS "Script Action" +.PP +Execute a custom script when an IP is banned. +.PP +\fBFields:\fR +.RS +.IP \(bu 2 +\fBtype\fR \- "script" +.IP \(bu 2 +\fBenabled\fR \- Enable/disable action (true/false) +.IP \(bu 2 +\fBinterpretator\fR \- Script interpretator (e.g., "/bin/bash") +.IP \(bu 2 +\fBscript\fR \- Path to script file +.RE +.PP +\fBExample:\fR +.RS +.nf +[[rule]] + name = "Notify on Ban" + service = "nginx" + status = "403" + ban_time = "1h" + + [[rule.action]] + type = "script" + enabled = true + interpretator = "/bin/bash" + script = "/opt/banforge/scripts/notify.sh" +.fi +.RE +. +.SS "Webhook Action" +.PP +Send HTTP webhook when an IP is banned. +.PP +\fBFields:\fR +.RS +.IP \(bu 2 +\fBtype\fR \- "webhook" +.IP \(bu 2 +\fBenabled\fR \- Enable/disable action (true/false) +.IP \(bu 2 +\fBurl\fR \- Webhook URL +.IP \(bu 2 +\fBmethod\fR \- HTTP method (POST, GET) +.IP \(bu 2 +\fBheaders\fR \- Custom headers (key-value pairs) +.IP \(bu 2 +\fBbody\fR \- Request body (supports templates) +.RE +.PP +\fBExample:\fR +.RS +.nf +[[rule.action]] + type = "webhook" + enabled = true + url = "https://hooks.example.com/ban" + method = "POST" + + [rule.action.headers] + Content-Type = "application/json" + Authorization = "Bearer TOKEN" + + [rule.action.body] + ip = "{{.IP}}" + reason = "{{.Rule}}" +.fi +.RE +. +.SS "Email Action" +.PP +Send email notification when an IP is banned. +.PP +\fBFields:\fR +.RS +.IP \(bu 2 +\fBtype\fR \- "email" +.IP \(bu 2 +\fBenabled\fR \- Enable/disable action (true/false) +.IP \(bu 2 +\fBemail\fR \- Recipient email address +.IP \(bu 2 +\fBemail_sender\fR \- Sender email address +.IP \(bu 2 +\fBemail_subject\fR \- Email subject +.IP \(bu 2 +\fBsmtp_host\fR \- SMTP server host +.IP \(bu 2 +\fBsmtp_port\fR \- SMTP server port +.IP \(bu 2 +\fBsmtp_user\fR \- SMTP username +.IP \(bu 2 +\fBsmtp_password\fR \- SMTP password +.IP \(bu 2 +\fBsmtp_tls\fR \- Enable TLS (true/false) +.RE +.PP +\fBExample:\fR +.RS +.nf +[[rule.action]] + type = "email" + enabled = true + email = "admin@example.com" + email_sender = "banforge@example.com" + email_subject = "IP Banned" + smtp_host = "smtp.example.com" + smtp_port = 587 + smtp_user = "banforge" + smtp_password = "secret" + smtp_tls = true +.fi +.RE +. +.SH FILES +.PP +.RS +.IP \(bu 2 +\fI/etc/banforge/config.toml\fR \- main configuration +.IP \(bu 2 +\fI/etc/banforge/rules.d/\fR \- rule files directory +.RE +. +.SH "SEE ALSO" +.BR banforge (1), +.BR iptables (8), +.BR nftables (8), +.BR systemd (1) +. +.SH AUTHOR +.PP +Ilya "d3m0k1d" Chernishev contact@d3m0k1d.ru