feat: add installer script and builder tools
- Added install.sh for easy setup and teardown - Added build.sh and build.bat to dynamically assemble install.sh - Updated README.md with new installation instructions - Fixed bidirectional WG_POLICY FORWARD rule routing in wg-policy-engine.sh
This commit is contained in:
@@ -15,22 +15,30 @@ Rather than allowing all VPN clients to reach any part of your internal network,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📁 File Locations & Installation
|
## 📁 Installation
|
||||||
|
|
||||||
All scripts must be placed in `/usr/local/bin/` and made executable.
|
The easiest way to install is using the provided `install.sh` script, which automatically installs dependencies, copies all scripts to `/usr/local/bin/`, sets up the systemd daemon, and enables the service.
|
||||||
|
|
||||||
| File | Location | Description |
|
|
||||||
|------|----------|-------------|
|
|
||||||
| `wg-policy-lib.sh` | `/usr/local/bin/wg-policy-lib.sh` | Shared library and core validation tools. |
|
|
||||||
| `wg-sync-policy.sh` | `/usr/local/bin/wg-sync-policy.sh` | Extracts config into atomic JSON format. |
|
|
||||||
| `wg-policy-engine.sh` | `/usr/local/bin/wg-policy-engine.sh` | Translates JSON into iptables & ipset logic. |
|
|
||||||
| `wg-policy-cleanup.sh` | `/usr/local/bin/wg-policy-cleanup.sh` | Reverts and cleans up all firewall traces safely. |
|
|
||||||
| `wg-sync-watch.sh` | `/usr/local/bin/wg-sync-watch.sh` | Debounced file watcher (daemon). |
|
|
||||||
| `wg-policy-ctl` | `/usr/local/bin/wg-policy-ctl` | Handy command-line interface tool. |
|
|
||||||
|
|
||||||
Make sure they are executable:
|
|
||||||
```bash
|
```bash
|
||||||
chmod +x /usr/local/bin/wg-*.sh /usr/local/bin/wg-policy-ctl
|
# Install everything
|
||||||
|
sudo ./install.sh install
|
||||||
|
|
||||||
|
# Uninstall everything
|
||||||
|
sudo ./install.sh uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building the Installer (For Developers)
|
||||||
|
|
||||||
|
If you modify any of the source `.sh` or `.service` files, you must rebuild the `install.sh` script using the provided builders.
|
||||||
|
|
||||||
|
**On Linux (Bash):**
|
||||||
|
```bash
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**On Windows (CMD/PowerShell):**
|
||||||
|
```cmd
|
||||||
|
build.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -132,9 +140,9 @@ wg-policy-ctl validate
|
|||||||
|
|
||||||
## 🔧 Systemd Integration (Watcher Daemon)
|
## 🔧 Systemd Integration (Watcher Daemon)
|
||||||
|
|
||||||
If you are using the daemon mode to auto-sync changes instantly upon editing `wg0.conf` (without needing to run `wg-policy-ctl reload` or restarting the interface).
|
If you use the `install.sh` script, the daemon is automatically installed, enabled, and started for you. It monitors `wg0.conf` for changes and triggers the pipeline seamlessly.
|
||||||
|
|
||||||
### 1. File Installation
|
### Manual File Installation (If not using install.sh)
|
||||||
Place the three provided systemd unit files into `/etc/systemd/system/`.
|
Place the three provided systemd unit files into `/etc/systemd/system/`.
|
||||||
|
|
||||||
| Systemd File | Location | Description |
|
| Systemd File | Location | Description |
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
set INSTALL_SCRIPT=install.sh
|
||||||
|
|
||||||
|
echo Building %INSTALL_SCRIPT%...
|
||||||
|
|
||||||
|
> "%INSTALL_SCRIPT%" echo #!/bin/bash
|
||||||
|
>> "%INSTALL_SCRIPT%" echo # WireGuard Policy Firewall Installer/Uninstaller
|
||||||
|
>> "%INSTALL_SCRIPT%" echo # This file is auto-generated. Do not edit directly. Run build.sh or build.bat instead.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo set -euo pipefail
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo if [[ $EUID -ne 0 ]]; then
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "This script must be run as root."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo exit 1
|
||||||
|
>> "%INSTALL_SCRIPT%" echo fi
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo install_policy^(^) {
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Installing WireGuard Policy Firewall..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Checking dependencies..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo apt-get update -y ^|^| true
|
||||||
|
>> "%INSTALL_SCRIPT%" echo apt-get install -y jq inotify-tools ipset iptables ^|^| true
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Writing scripts to /usr/local/bin/..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
|
||||||
|
call :AppendFile wg-policy-lib.sh /usr/local/bin/wg-policy-lib.sh EOF_WG_POLICY_LIB
|
||||||
|
call :AppendFile wg-policy-engine.sh /usr/local/bin/wg-policy-engine.sh EOF_WG_POLICY_ENGINE
|
||||||
|
call :AppendFile wg-policy-cleanup.sh /usr/local/bin/wg-policy-cleanup.sh EOF_WG_POLICY_CLEANUP
|
||||||
|
call :AppendFile wg-sync-policy.sh /usr/local/bin/wg-sync-policy.sh EOF_WG_SYNC_POLICY
|
||||||
|
call :AppendFile wg-sync-watch.sh /usr/local/bin/wg-sync-watch.sh EOF_WG_SYNC_WATCH
|
||||||
|
call :AppendFile wg-policy-ctl /usr/local/bin/wg-policy-ctl EOF_WG_POLICY_CTL
|
||||||
|
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Writing systemd units to /etc/systemd/system/..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
|
||||||
|
call :AppendFile wg-policy.service /etc/systemd/system/wg-policy.service EOF_WG_POLICY_SERVICE
|
||||||
|
call :AppendFile wg-policy-health.service /etc/systemd/system/wg-policy-health.service EOF_WG_POLICY_HEALTH_SERVICE
|
||||||
|
call :AppendFile wg-policy-health.timer /etc/systemd/system/wg-policy-health.timer EOF_WG_POLICY_HEALTH_TIMER
|
||||||
|
|
||||||
|
>> "%INSTALL_SCRIPT%" echo chmod +x /usr/local/bin/wg-*.sh /usr/local/bin/wg-policy-ctl
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Reloading systemd daemon..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo systemctl daemon-reload
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Enabling and starting services..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo systemctl enable --now wg-policy.service
|
||||||
|
>> "%INSTALL_SCRIPT%" echo systemctl enable --now wg-policy-health.timer
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Installation complete!"
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "You can check status with: wg-policy-ctl status"
|
||||||
|
>> "%INSTALL_SCRIPT%" echo }
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo uninstall_policy^(^) {
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Uninstalling WireGuard Policy Firewall..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Stopping and disabling services..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo systemctl disable --now wg-policy.service wg-policy-health.timer wg-policy-health.service 2^>/dev/null ^|^| true
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Running cleanup script..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo if [ -x /usr/local/bin/wg-policy-cleanup.sh ]; then
|
||||||
|
>> "%INSTALL_SCRIPT%" echo /usr/local/bin/wg-policy-cleanup.sh ^|^| true
|
||||||
|
>> "%INSTALL_SCRIPT%" echo fi
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Removing systemd units..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /etc/systemd/system/wg-policy.service
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /etc/systemd/system/wg-policy-health.service
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /etc/systemd/system/wg-policy-health.timer
|
||||||
|
>> "%INSTALL_SCRIPT%" echo systemctl daemon-reload
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Removing scripts from /usr/local/bin/..."
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /usr/local/bin/wg-policy-lib.sh
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /usr/local/bin/wg-sync-policy.sh
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /usr/local/bin/wg-policy-engine.sh
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /usr/local/bin/wg-policy-cleanup.sh
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /usr/local/bin/wg-sync-watch.sh
|
||||||
|
>> "%INSTALL_SCRIPT%" echo rm -f /usr/local/bin/wg-policy-ctl
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Uninstallation complete!"
|
||||||
|
>> "%INSTALL_SCRIPT%" echo }
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo case "${1:-}" in
|
||||||
|
>> "%INSTALL_SCRIPT%" echo install^)
|
||||||
|
>> "%INSTALL_SCRIPT%" echo install_policy
|
||||||
|
>> "%INSTALL_SCRIPT%" echo ;;
|
||||||
|
>> "%INSTALL_SCRIPT%" echo uninstall^)
|
||||||
|
>> "%INSTALL_SCRIPT%" echo uninstall_policy
|
||||||
|
>> "%INSTALL_SCRIPT%" echo ;;
|
||||||
|
>> "%INSTALL_SCRIPT%" echo *^)
|
||||||
|
>> "%INSTALL_SCRIPT%" echo echo "Usage: $0 {install|uninstall}"
|
||||||
|
>> "%INSTALL_SCRIPT%" echo exit 1
|
||||||
|
>> "%INSTALL_SCRIPT%" echo ;;
|
||||||
|
>> "%INSTALL_SCRIPT%" echo esac
|
||||||
|
|
||||||
|
echo Done! Generated %INSTALL_SCRIPT% successfully.
|
||||||
|
goto :eof
|
||||||
|
|
||||||
|
:AppendFile
|
||||||
|
set SRC=%1
|
||||||
|
set TARGET=%2
|
||||||
|
set EOF_MARKER=%3
|
||||||
|
|
||||||
|
>> "%INSTALL_SCRIPT%" echo cat ^<^< '%EOF_MARKER%' ^> %TARGET%
|
||||||
|
type "%SRC%" >> "%INSTALL_SCRIPT%"
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
>> "%INSTALL_SCRIPT%" echo %EOF_MARKER%
|
||||||
|
>> "%INSTALL_SCRIPT%" echo.
|
||||||
|
goto :eof
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# build.sh - Generates the install.sh file dynamically by embedding .sh and .service files
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
INSTALL_SCRIPT="install.sh"
|
||||||
|
|
||||||
|
echo "Building ${INSTALL_SCRIPT}..."
|
||||||
|
|
||||||
|
# Write the header
|
||||||
|
cat << 'MAIN_EOF' > "$INSTALL_SCRIPT"
|
||||||
|
#!/bin/bash
|
||||||
|
# WireGuard Policy Firewall Installer/Uninstaller
|
||||||
|
# This file is auto-generated. Do not edit directly. Run build.sh or build.bat instead.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "This script must be run as root."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_policy() {
|
||||||
|
echo "Installing WireGuard Policy Firewall..."
|
||||||
|
|
||||||
|
echo "Checking dependencies..."
|
||||||
|
apt-get update -y || true
|
||||||
|
apt-get install -y jq inotify-tools ipset iptables || true
|
||||||
|
|
||||||
|
echo "Writing scripts to /usr/local/bin/..."
|
||||||
|
|
||||||
|
MAIN_EOF
|
||||||
|
|
||||||
|
# Helper function to append file content inside a heredoc
|
||||||
|
append_file() {
|
||||||
|
local file=$1
|
||||||
|
local target=$2
|
||||||
|
local delimiter="EOF_${file//[-.]/_}"
|
||||||
|
delimiter=$(echo "$delimiter" | tr '[:lower:]' '[:upper:]')
|
||||||
|
|
||||||
|
echo " cat << '${delimiter}' > ${target}" >> "$INSTALL_SCRIPT"
|
||||||
|
cat "$file" >> "$INSTALL_SCRIPT"
|
||||||
|
|
||||||
|
# Ensure there is a newline before the EOF marker just in case the file lacks it
|
||||||
|
echo "" >> "$INSTALL_SCRIPT"
|
||||||
|
echo "${delimiter}" >> "$INSTALL_SCRIPT"
|
||||||
|
echo "" >> "$INSTALL_SCRIPT"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Append all necessary files
|
||||||
|
append_file "wg-policy-lib.sh" "/usr/local/bin/wg-policy-lib.sh"
|
||||||
|
append_file "wg-policy-engine.sh" "/usr/local/bin/wg-policy-engine.sh"
|
||||||
|
append_file "wg-policy-cleanup.sh" "/usr/local/bin/wg-policy-cleanup.sh"
|
||||||
|
append_file "wg-sync-policy.sh" "/usr/local/bin/wg-sync-policy.sh"
|
||||||
|
append_file "wg-sync-watch.sh" "/usr/local/bin/wg-sync-watch.sh"
|
||||||
|
append_file "wg-policy-ctl" "/usr/local/bin/wg-policy-ctl"
|
||||||
|
|
||||||
|
cat << 'MAIN_EOF_MID' >> "$INSTALL_SCRIPT"
|
||||||
|
echo "Writing systemd units to /etc/systemd/system/..."
|
||||||
|
|
||||||
|
MAIN_EOF_MID
|
||||||
|
|
||||||
|
append_file "wg-policy.service" "/etc/systemd/system/wg-policy.service"
|
||||||
|
append_file "wg-policy-health.service" "/etc/systemd/system/wg-policy-health.service"
|
||||||
|
append_file "wg-policy-health.timer" "/etc/systemd/system/wg-policy-health.timer"
|
||||||
|
|
||||||
|
# Write the rest of the installation and uninstallation logic
|
||||||
|
cat << 'MAIN_EOF_END' >> "$INSTALL_SCRIPT"
|
||||||
|
chmod +x /usr/local/bin/wg-*.sh /usr/local/bin/wg-policy-ctl
|
||||||
|
|
||||||
|
echo "Reloading systemd daemon..."
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
echo "Enabling and starting services..."
|
||||||
|
systemctl enable --now wg-policy.service
|
||||||
|
systemctl enable --now wg-policy-health.timer
|
||||||
|
|
||||||
|
echo "Installation complete!"
|
||||||
|
echo "You can check status with: wg-policy-ctl status"
|
||||||
|
}
|
||||||
|
|
||||||
|
uninstall_policy() {
|
||||||
|
echo "Uninstalling WireGuard Policy Firewall..."
|
||||||
|
|
||||||
|
echo "Stopping and disabling services..."
|
||||||
|
systemctl disable --now wg-policy.service wg-policy-health.timer wg-policy-health.service 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "Running cleanup script..."
|
||||||
|
if [ -x /usr/local/bin/wg-policy-cleanup.sh ]; then
|
||||||
|
/usr/local/bin/wg-policy-cleanup.sh || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Removing systemd units..."
|
||||||
|
rm -f /etc/systemd/system/wg-policy.service
|
||||||
|
rm -f /etc/systemd/system/wg-policy-health.service
|
||||||
|
rm -f /etc/systemd/system/wg-policy-health.timer
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
echo "Removing scripts from /usr/local/bin/..."
|
||||||
|
rm -f /usr/local/bin/wg-policy-lib.sh
|
||||||
|
rm -f /usr/local/bin/wg-sync-policy.sh
|
||||||
|
rm -f /usr/local/bin/wg-policy-engine.sh
|
||||||
|
rm -f /usr/local/bin/wg-policy-cleanup.sh
|
||||||
|
rm -f /usr/local/bin/wg-sync-watch.sh
|
||||||
|
rm -f /usr/local/bin/wg-policy-ctl
|
||||||
|
|
||||||
|
echo "Uninstallation complete!"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
install)
|
||||||
|
install_policy
|
||||||
|
;;
|
||||||
|
uninstall)
|
||||||
|
uninstall_policy
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {install|uninstall}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
MAIN_EOF_END
|
||||||
|
|
||||||
|
chmod +x "$INSTALL_SCRIPT"
|
||||||
|
|
||||||
|
echo "Done! Generated ${INSTALL_SCRIPT} successfully."
|
||||||
+1312
File diff suppressed because it is too large
Load Diff
+6
-8
@@ -111,12 +111,6 @@ main() {
|
|||||||
sysctl -w net.ipv6.conf.all.forwarding=1 >/dev/null 2>&1 || true
|
sysctl -w net.ipv6.conf.all.forwarding=1 >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Allow return traffic to wg interface
|
|
||||||
if ! iptables -C FORWARD -o "$WG_IF" -j ACCEPT 2>/dev/null; then
|
|
||||||
iptables -I FORWARD 1 -o "$WG_IF" -j ACCEPT
|
|
||||||
log_info "Added FORWARD rule for return traffic to $WG_IF"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Setup MASQUERADE on default interface
|
# Setup MASQUERADE on default interface
|
||||||
if ! iptables -t nat -C POSTROUTING -o "$DEF_IF" -j MASQUERADE 2>/dev/null; then
|
if ! iptables -t nat -C POSTROUTING -o "$DEF_IF" -j MASQUERADE 2>/dev/null; then
|
||||||
iptables -t nat -A POSTROUTING -o "$DEF_IF" -j MASQUERADE
|
iptables -t nat -A POSTROUTING -o "$DEF_IF" -j MASQUERADE
|
||||||
@@ -151,9 +145,13 @@ main() {
|
|||||||
iptables -N "$CHAIN"
|
iptables -N "$CHAIN"
|
||||||
|
|
||||||
if ! iptables -C FORWARD -i "$WG_IF" -j "$CHAIN" 2>/dev/null; then
|
if ! iptables -C FORWARD -i "$WG_IF" -j "$CHAIN" 2>/dev/null; then
|
||||||
iptables -A FORWARD -i "$WG_IF" -j "$CHAIN"
|
iptables -I FORWARD 1 -i "$WG_IF" -j "$CHAIN"
|
||||||
fi
|
fi
|
||||||
log_info "Chain $CHAIN created and linked to FORWARD"
|
|
||||||
|
if ! iptables -C FORWARD -o "$WG_IF" -j "$CHAIN" 2>/dev/null; then
|
||||||
|
iptables -I FORWARD 2 -o "$WG_IF" -j "$CHAIN"
|
||||||
|
fi
|
||||||
|
log_info "Chain $CHAIN created and linked to FORWARD (In/Out)"
|
||||||
|
|
||||||
# === POPULATE IPSET (hash:net,net for source->target mapping) ===
|
# === POPULATE IPSET (hash:net,net for source->target mapping) ===
|
||||||
local use_ipset=false
|
local use_ipset=false
|
||||||
|
|||||||
Reference in New Issue
Block a user