GitHub repository —
bashforward.com
bashforward
Provides interactive menus for port forwarding (iptables DNAT), WireGuard VPN user administration,
and NGINX reverse proxy with Let's Encrypt automation. All rules and configurations are stored in a
lightweight SQLite database (bashforward.db), making them persistent, reproducible, and easy to audit.
DNAT rules for IPv4/IPv6 using iptables/ip6tables. Custom chains ensure clean management, with systemd service for boot persistence.
Interactive setup & client management. Based on Nyr/wireguard-install, extended with SQLite storage. QR codes, DNS selection, IPv6 support.
Automatic generation of reverse‑proxy configs. HTTP → HTTPS with Certbot webroot integration. Database‑driven domain/backend mapping.
The suite consists of four main scripts (plus a shared SQLite database):
| File | Purpose |
|---|---|
bashforward.sh | Main launcher – menu to enter sub‑tools. |
bashforward-portforwarding.sh | Port forwarding (DNAT) manager. |
bashforward-nyr-wireguard.sh | WireGuard installation & client manager. |
bashforward-nginx.sh | NGINX reverse proxy + Let's Encrypt automation. |
bashforward.db | SQLite database (auto‑created). |
Clone the repository and ensure dependencies are installed:
apt install git -y
git clone https://github.com/babywhale321/bashforward.git
cd bashforward
chmod +x *.sh
Required packages (auto‑detected):
sqlite3 – database backendiptables (and ip6tables for IPv6) – port forwardingwireguard-tools, qrencode – WireGuard modulenginx, certbot – reverse proxy & SSLsystemd – for service persistenceRun the main menu as root:
sudo ./bashforward.sh
bashforward.db). The database is created automatically when needed.
The entry point displays a clean menu:
======================= bashforward =======================
1. Port Forwarding Menu 2. Wireguard Menu 3. NGINX menu
q. Quit
Each option calls the respective sub‑script in a new Bash session.
bashforward-portforwarding.sh manages DNAT port forwards using iptables (IPv4) and ip6tables (IPv6).
All entries are stored in the portforward_entries table.
PORT_FORWARDING_PREROUTING, PORT_FORWARDING_POSTROUTING) keep rules isolated.port-forwarding.service) applies rules at boot and survives reboots.port-forwarding.sh) is generated from the database and contains the exact iptables commands.s – Show current rules (iptables list + database entries).1 – Add a new forwarding rule (interactive prompts).2 – Delete a rule by ID.3 – Reset all port forwarding rules (clears database and flushes chains).portforward_entries| Column | Type | Description |
|---|---|---|
| id | INTEGER PRIMARY KEY | Auto‑increment ID |
| ip_version | TEXT | 'v4' or 'v6' |
| external_port | INTEGER | Public listening port |
| dest_ip | TEXT | Target internal IP |
| dest_port | INTEGER | Target port on dest_ip |
Enter the IP version (v4/v6): v4
Enter the external port (1-65535): 8080
Enter the destination IP (v4): 10.7.0.2
Enter the destination port (1-65535): 22
The script adds two DNAT rules (TCP+UDP) and a MASQUERADE rule for return traffic. After each change, the systemd service is updated and the rules are applied instantly.
ensure_iptables_chains() creates the custom chains and adds jump rules if missing.
regenerate_script() builds a fresh port-forwarding.sh that flushes the custom chains and
re‑adds all DNAT rules. The systemd service runs this script on start.
IPv6 rules use the same logic with ip6tables.
bashforward-nyr-wireguard.sh is a fork/adaptation of Nyr/wireguard-install
extended with SQLite storage and integration into the bashforward ecosystem.
If /etc/wireguard/wg0.conf does not exist, the script guides through a full WireGuard setup:
wg0 with subnet 10.7.0.0/24 (IPv6 ULA fddd:2c4:2c4:2c4::/64).wg-iptables.service).After installation, the script presents a menu for ongoing administration:
s – List all clients from the wireguard_entries table.1 – Add a new client (asks name, DNS, generates keys).2 – Remove a client (removes peer from wg0.conf and database).wireguard_entries| Column | Type | Description |
|---|---|---|
| id | INTEGER PRIMARY KEY | Auto‑increment |
| name | TEXT UNIQUE | Client identifier (sanitized) |
| public_key | TEXT | WireGuard public key |
| preshared_key | TEXT | Preshared key for post‑quantum resistance |
| ipv4_octet | INTEGER | Last octet of the client IP (10.7.0.2‑10.7.0.254) |
| dns | TEXT | DNS servers for the client config |
| created_at | DATETIME | Timestamp (auto) |
The script offers several preset DNS options (Google, Cloudflare, Quad9, etc.) or custom resolvers.
The chosen DNS is embedded in the generated .conf file.
When adding a client, the script automatically:
find_free_octet().wireguard_entries.[Peer] block to /etc/wireguard/wg0.conf (marked with # BEGIN_PEER name).name.conf) and displays QR code.wg addconf.fddd:2c4:2c4:2c4::/64 is used, and each client gets a matching IPv6 address
(e.g., fddd:2c4:2c4:2c4::octet/128).
The systemd service wg-iptables.service manages NAT and firewall rules.
It is created during installation and remains active. The service uses ExecStart and ExecStop
to add/remove rules cleanly.
bashforward-nginx.sh provides a database‑driven NGINX reverse proxy with automatic Let's Encrypt
certificate issuance using Certbot webroot method.
/etc/nginx/conf.d/reverse-proxy-generated.conf.nginx_entries SQLite table.nginx -t) before reload.certbot certonly --webroot) and automatically included in the HTTPS server block.nginx_entries| Column | Type | Description |
|---|---|---|
| id | INTEGER PRIMARY KEY | Auto‑increment |
| domain | TEXT UNIQUE | Domain name (e.g., app.example.com) |
| backend_host | TEXT | Upstream server IP/hostname |
| backend_port | INTEGER | Upstream port |
| ssl | INTEGER | 1 = SSL enabled, 0 = HTTP only |
s – List all configured domains.1 – Add a new reverse proxy entry (prompts for domain, backend, SSL).2 – Delete an entry by ID.
Domain (e.g., example.com): myapp.example.org
Backend host (IP or hostname): 10.7.0.2
Backend port: 80
Enable SSL (via Certbot)? (y/n): y
The process:
reverse-proxy-generated.conf with an HTTP server block (including the .well-known/acme-challenge location).The webroot (/var/www/html) is used for ACME challenges. Ensure port 80 is reachable.
Generated server blocks include standard proxy headers:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
If SSL is enabled and certificates exist, the HTTPS block listens on port 443 and references
/etc/letsencrypt/live/domain/fullchain.pem and privkey.pem.
systemctl reload nginx). The webroot directory is created if missing.
Before overwriting the generated config, a backup is saved as reverse-proxy-generated.conf.bak.
If the NGINX configuration test fails, the backup is restored automatically.
All three modules share the same bashforward.db file. The tables are created automatically
when the respective script runs for the first time:
-- portforward_entries
CREATE TABLE IF NOT EXISTS portforward_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip_version TEXT NOT NULL,
external_port INTEGER NOT NULL,
dest_ip TEXT NOT NULL,
dest_port INTEGER NOT NULL
);
-- wireguard_entries
CREATE TABLE IF NOT EXISTS wireguard_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL,
public_key TEXT NOT NULL,
preshared_key TEXT NOT NULL,
ipv4_octet INTEGER UNIQUE NOT NULL,
dns TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- nginx_entries
CREATE TABLE IF NOT EXISTS nginx_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
domain TEXT UNIQUE NOT NULL,
backend_host TEXT NOT NULL,
backend_port INTEGER NOT NULL,
ssl INTEGER DEFAULT 0
);
WEBROOT variable in bashforward-nginx.sh.Address line in /etc/wireguard/wg0.conf (requires manual adjustment).
bashforward is created by Kyle Schroeder (BabyWhale).
The WireGuard module is based on Nyr/wireguard-install (MIT License).
This documentation is part of the bashforward project.
For issues, contributions, or feature requests, please visit the GitHub repository.