Fix firewall rules not loading on reboot

- Enable and start nftables service during installation
- Create /etc/nftables.conf that includes /etc/nftables.d/wireguard.conf
- nftables service now loads firewall rules automatically on boot
- Update documentation to reflect proper configuration file paths
- Remove historical VALIDATION.md document
- Clean up documentation references to non-existent scripts
This commit is contained in:
Calmcacil
2026-01-12 16:12:06 +01:00
parent 6b97f0532f
commit 22688d96b5
6 changed files with 125 additions and 286 deletions

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads

40
AGENTS.md Normal file
View File

@@ -0,0 +1,40 @@
# Agent Instructions
This project uses **bd** (beads) for issue tracking. Run `bd onboard` to get started.
## Quick Reference
```bash
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --status in_progress # Claim work
bd close <id> # Complete work
bd sync # Sync with git
```
## Landing the Plane (Session Completion)
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
**MANDATORY WORKFLOW:**
1. **File issues for remaining work** - Create issues for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **PUSH TO REMOTE** - This is MANDATORY:
```bash
git pull --rebase
bd sync
git push
git status # MUST show "up to date with origin"
```
5. **Clean up** - Clear stashes, prune remote branches
6. **Verify** - All changes committed AND pushed
7. **Hand off** - Provide context for next session
**CRITICAL RULES:**
- Work is NOT complete until `git push` succeeds
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds

View File

@@ -56,45 +56,7 @@ sudo nft list ruleset
sudo nft list chain inet wireguard input sudo nft list chain inet wireguard input
``` ```
### Enable/disable firewall ### Add a rule
```bash
sudo nftables-firewall enable
sudo nftables-firewall disable
```
### Allow additional ports
```bash
sudo nftables-firewall allow 80/tcp
sudo nftables-firewall allow 443/tcp
```
### Allow from specific IP
```bash
# IPv4
sudo nftables-firewall allow from 192.168.1.100
# IPv6
sudo nftables-firewall allow from 2001:db8::/32
# CIDR range
sudo nftables-firewall allow from 192.168.1.0/24
```
### Delete a rule
```bash
# List rules with numbers
sudo nft -a list chain inet wireguard input
# Delete by handle number
sudo nftables-firewall delete <handle_number>
```
### Reload firewall
```bash
sudo nftables-firewall reload
```
### Manually add a rule
```bash ```bash
# Allow TCP port 8080 # Allow TCP port 8080
sudo nft add rule inet wireguard input tcp dport 8080 accept sudo nft add rule inet wireguard input tcp dport 8080 accept
@@ -103,13 +65,27 @@ sudo nft add rule inet wireguard input tcp dport 8080 accept
sudo nft add rule inet wireguard input udp dport 53 accept sudo nft add rule inet wireguard input udp dport 53 accept
``` ```
### Delete a rule
```bash
# List rules with handle numbers
sudo nft -a list chain inet wireguard input
# Delete by handle number
sudo nft delete rule inet wireguard input handle <handle_number>
```
### Reload firewall
```bash
sudo nft -f /etc/nftables.d/wireguard.conf
```
## Important Notes ## Important Notes
1. **SSH is always allowed**: The setup explicitly allows SSH to prevent lockout 1. **SSH is always allowed**: The setup explicitly allows SSH to prevent lockout
2. **IPv4/IPv6 unified**: Single configuration handles both protocols 2. **IPv4/IPv6 unified**: Single configuration handles both protocols
3. **Persistent rules**: nftables rules are saved in `/etc/nftables.d/wireguard.conf` 3. **Persistent rules**: nftables rules are saved in `/etc/nftables.d/wireguard.conf`
4. **No UFW dependency**: Direct nftables implementation 4. **No UFW dependency**: Direct nftables implementation
5. **Automatic on boot**: nftables service starts automatically 5. **Automatic on boot**: nftables service is enabled and starts automatically, loading rules from `/etc/nftables.conf` (which includes `/etc/nftables.d/wireguard.conf`) on system reboot
## Troubleshooting ## Troubleshooting
@@ -161,7 +137,7 @@ sudo nft list table ip6 nat
sudo nft flush ruleset sudo nft flush ruleset
# Reload from config # Reload from config
sudo nftables-firewall reload sudo nft -f /etc/nftables.conf
``` ```
### Debug with counters ### Debug with counters
@@ -200,7 +176,12 @@ sudo nft add rule inet wireguard input tcp dport 3000 ip saddr @knock update @kn
## Configuration Files ## Configuration Files
### Main configuration ### Main configuration (loaded by nftables service)
```
/etc/nftables.conf
```
### WireGuard rules
``` ```
/etc/nftables.d/wireguard.conf /etc/nftables.d/wireguard.conf
``` ```
@@ -209,21 +190,3 @@ sudo nft add rule inet wireguard input tcp dport 3000 ip saddr @knock update @kn
``` ```
/etc/systemd/system/nftables.service /etc/systemd/system/nftables.service
``` ```
### Management script
```
/usr/local/sbin/nftables-firewall
```
## Migration from UFW
If migrating from a UFW-based setup:
| UFW Command | nftables Equivalent |
|-------------|---------------------|
| `ufw status` | `nft list ruleset` |
| `ufw enable` | `nftables-firewall enable` |
| `ufw disable` | `nftables-firewall disable` |
| `ufw allow 80/tcp` | `nft add rule inet wireguard input tcp dport 80 accept` |
| `ufw delete allow 80/tcp` | `nft delete rule inet wireguard input handle <num>` |
| `ufw reset` | `nft flush ruleset && nftables-firewall reload` |

View File

@@ -1,7 +1,7 @@
# WireGuard VPN Setup for Debian 13 # WireGuard VPN Setup for Debian 13
## Overview ## Overview
Personal WireGuard VPN server with IPv4/IPv6 support, client management via `/etc/wireguard/peer.d/`, designed for 1 CPU / 1GB RAM VPS. Personal WireGuard VPN server with IPv4/IPv6 support, client management via `wireguard.sh`, designed for 1 CPU / 1GB RAM VPS.
## Configuration ## Configuration
- **Server Domain**: velkhana.calmcacil.dev - **Server Domain**: velkhana.calmcacil.dev
@@ -9,63 +9,57 @@ Personal WireGuard VPN server with IPv4/IPv6 support, client management via `/et
- **VPN IPv4 Range**: 10.10.69.0/24 - **VPN IPv4 Range**: 10.10.69.0/24
- **VPN IPv6 Range**: fd69:dead:beef:69::/64 - **VPN IPv6 Range**: fd69:dead:beef:69::/64
- **DNS**: 8.8.8.8, 8.8.4.4 (Google) - **DNS**: 8.8.8.8, 8.8.4.4 (Google)
- **Server-side peer configs**: /etc/wireguard/peer.d/*.conf (loaded dynamically) - **Server-side peer configs**: /etc/wireguard/conf.d/client-*.conf (loaded dynamically)
- **Client-side configs**: /etc/wireguard/clients/*.conf (for distribution) - **Client-side configs**: /etc/wireguard/clients/*.conf (for distribution)
## Installation ## Installation
### 1. Upload files to VPS ### 1. Upload script to VPS
```bash ```bash
scp install-wireguard.sh wg-client-manager calmcacil@velkhana.calmcacil.dev:~/ scp wireguard.sh calmcacil@velkhana.calmcacil.dev:~/
``` ```
### 2. Run installation ### 2. Run installation
```bash ```bash
chmod +x ~/install-wireguard.sh ~/wg-client-manager chmod +x ~/wireguard.sh
sudo ~/install-wireguard.sh sudo ~/wireguard.sh install
```
### 3. Install client manager
```bash
sudo mv ~/wg-client-manager /usr/local/sbin/
sudo chmod +x /usr/local/sbin/wg-client-manager
``` ```
## Usage ## Usage
### Dynamic client loading ### Dynamic client loading
WireGuard automatically loads clients from `/etc/wireguard/peer.d/`: WireGuard automatically loads clients from `/etc/wireguard/conf.d/`:
- Add/remove client configs in `/etc/wireguard/peer.d/*.conf` - Add/remove client configs in `/etc/wireguard/conf.d/client-*.conf`
- Run `sudo /usr/local/sbin/wg-load-clients` to reload - Run `sudo ~/wireguard.sh load-clients` to reload
- Changes are applied immediately without restarting - Changes are applied immediately without restarting
### Add a new client ### Add a new client
```bash ```bash
sudo /usr/local/sbin/wg-client-manager add myphone sudo ~/wireguard.sh add myphone
``` ```
This creates: This creates:
- Server config in `/etc/wireguard/peer.d/myphone.conf` - Server config in `/etc/wireguard/conf.d/client-myphone.conf`
- Client config in `/etc/wireguard/clients/myphone.conf` - Client config in `/etc/wireguard/clients/myphone.conf`
- QR code in `/etc/wireguard/clients/myphone.qr` - QR code in `/etc/wireguard/clients/myphone.qr`
### List all clients ### List all clients
```bash ```bash
sudo /usr/local/sbin/wg-client-manager list sudo ~/wireguard.sh list
``` ```
### Show client config ### Show client config
```bash ```bash
sudo /usr/local/sbin/wg-client-manager show myphone sudo ~/wireguard.sh show myphone
``` ```
### Show QR code ### Show QR code
```bash ```bash
sudo /usr/local/sbin/wg-client-manager qr myphone sudo ~/wireguard.sh qr myphone
``` ```
### Remove a client ### Remove a client
```bash ```bash
sudo /usr/local/sbin/wg-client-manager remove myphone sudo ~/wireguard.sh remove myphone
``` ```
## Server Management ## Server Management
@@ -87,7 +81,7 @@ sudo systemctl restart wg-quick@wg0
### Reload clients (automatic on add/remove) ### Reload clients (automatic on add/remove)
```bash ```bash
sudo /usr/local/sbin/wg-load-clients sudo ~/wireguard.sh load-clients
``` ```
### Firewall management ### Firewall management
@@ -104,21 +98,22 @@ View firewall rules:
sudo nft list ruleset sudo nft list ruleset
``` ```
Enable/disable firewall: Reload firewall:
```bash ```bash
sudo nftables-firewall disable sudo nft -f /etc/nftables.conf
sudo nftables-firewall enable
``` ```
**Note**: nftables rules are automatically loaded on boot by the nftables service from `/etc/nftables.conf`. No manual intervention required after reboot.
Allow additional ports if needed: Allow additional ports if needed:
```bash ```bash
sudo nftables-firewall allow 80/tcp # HTTP sudo nft add rule inet wireguard input tcp dport 80 accept # HTTP
sudo nftables-firewall allow 443/tcp # HTTPS sudo nft add rule inet wireguard input tcp dport 443 accept # HTTPS
``` ```
## Manual Client Configuration ## Manual Client Configuration
To manually add a client, create a file in `/etc/wireguard/peer.d/`: To manually add a client, create a file in `/etc/wireguard/conf.d/`:
```ini ```ini
[Peer] [Peer]
@@ -129,7 +124,7 @@ AllowedIPs = 10.10.69.2/32, fd69:dead:beef:69::2/128
Then run: Then run:
```bash ```bash
sudo /usr/local/sbin/wg-load-clients sudo ~/wireguard.sh load-clients
``` ```
## Client Setup ## Client Setup
@@ -169,16 +164,16 @@ sudo journalctl -u wg-quick@wg0 -f
### Check client directory ### Check client directory
```bash ```bash
ls -la /etc/wireguard/peer.d/ ls -la /etc/wireguard/conf.d/
``` ```
### Manual reload if needed ### Manual reload if needed
```bash ```bash
sudo /usr/local/sbin/wg-load-clients sudo ~/wireguard.sh load-clients
``` ```
## Notes ## Notes
- `/etc/wireguard/peer.d/` - Server-side peer configs, loaded automatically by wg-load-clients - `/etc/wireguard/conf.d/` - Server-side peer configs, loaded automatically by wireguard.sh
- `/etc/wireguard/clients/` - Client-side configs (import to WireGuard apps) and QR codes - `/etc/wireguard/clients/` - Client-side configs (import to WireGuard apps) and QR codes
- Clients are automatically reloaded when added/removed - Clients are automatically reloaded when added/removed
- IPv4 and IPv6 NAT are configured (MASQUERADE) - IPv4 and IPv6 NAT are configured (MASQUERADE)
@@ -188,4 +183,3 @@ sudo /usr/local/sbin/wg-load-clients
- Keepalive is set to 25 seconds for better stability - Keepalive is set to 25 seconds for better stability
- Server private keys are stored in `/etc/wireguard/server_private.key` - Server private keys are stored in `/etc/wireguard/server_private.key`
- Server public key is displayed after installation - Server public key is displayed after installation
- Use `nftables-firewall` script for easy firewall management

View File

@@ -1,190 +0,0 @@
# Firewall Validation Report
## Migration from UFW/iptables to nftables
### Changes Made
#### 1. Package Installation
**Before**: `apt-get install -y wireguard wireguard-tools qrencode iptables ufw`
**After**: `apt-get install -y wireguard wireguard-tools qrencode nftables`
**Rationale**:
- Removed iptables and ufw dependencies
- Added nftables package (modern successor to iptables)
- Cleaner, more efficient packet filtering
#### 2. Firewall Configuration
**Before**: UFW configuration with iptables/ip6tables rules
```bash
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 51820/udp
```
**After**: nftables with unified dual-stack rules
```nft
table inet wireguard {
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state established,related accept
ct state invalid drop
tcp dport 22 accept
udp dport 51820 accept
icmp type { echo-request, echo-reply } accept
icmpv6 type { echo-request, echo-reply, nd-neighbor-solicit, nd-neighbor-advert } accept
}
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
iif wg0 accept
oif wg0 accept
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname eth0 ip saddr 10.10.69.0/24 masquerade
}
}
table ip6 nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname eth0 ip6 saddr fd69:dead:beef:69::/64 masquerade
}
}
```
**Rationale**:
- Single `inet` table handles both IPv4 and IPv6
- More concise and readable configuration
- Better performance on high-traffic systems
- No need for separate UFW route rules
#### 3. WireGuard PostUp/PostDown Rules
**Before**: Multiple iptables/ip6tables/ufw commands
```ini
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -s 10.10.69.0/24 -j MASQUERADE; ufw route allow in on wg0 out on eth0; ufw route allow in on eth0 out on wg0
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -s 10.10.69.0/24 -j MASQUERADE; ufw route delete allow in on wg0 out on eth0; ufw route delete allow in on eth0 out on wg0
```
**After**: No PostUp/PostDown needed
```ini
# No PostUp/PostDown needed - nftables rules are persistent
```
**Rationale**:
- nftables rules are persistent (loaded at boot via service)
- No need for dynamic rule addition/removal
- Cleaner WireGuard configuration
- All firewall logic in one place
#### 4. Management Script
**New**: `/usr/local/sbin/nftables-firewall`
```bash
nftables-firewall status # Show firewall rules
nftables-firewall enable # Enable firewall
nftables-firewall disable # Disable firewall
nftables-firewall allow 80/tcp # Allow TCP port 80
nftables-firewall delete <num> # Delete rule by number
nftables-firewall reload # Reload firewall rules
```
**Rationale**:
- Provides UFW-like interface for nftables
- Easier transition for users familiar with UFW
- Simplified common operations
### Validation Results
#### Functional Equivalence
All UFW/iptables functionality preserved:
| UFW Feature | nftables Equivalent | Status |
|-------------|---------------------|--------|
| Default deny incoming | `policy drop` in input chain | ✅ |
| Default allow outgoing | `policy accept` in output chain | ✅ |
| Allow SSH (22/tcp) | `tcp dport 22 accept` | ✅ |
| Allow WireGuard (51820/udp) | `udp dport 51820 accept` | ✅ |
| IPv4/IPv6 support | Single `inet` table | ✅ (Improved) |
| Forwarding rules | `iif wg0 accept`, `oif wg0 accept` | ✅ |
| NAT masquerade | `masquerade` in NAT tables | ✅ |
| Established/related connections | `ct state established,related accept` | ✅ |
#### Performance Improvements
- Single ruleset for IPv4/IPv6 (previously required separate iptables/ip6tables)
- More efficient rule evaluation
- Lower memory footprint
- Better scalability for high-traffic scenarios
#### Configuration Advantages
- All firewall rules in one file (`/etc/nftables.d/wireguard.conf`)
- No UFW dependency
- No complex PostUp/PostDown hooks
- Simpler WireGuard configuration
- Easier to audit and maintain
### Testing Checklist
- [ ] nftables service starts on boot
- [ ] Firewall rules are loaded correctly
- [ ] SSH access works (not locked out)
- [ ] WireGuard port 51820 is accessible
- [ ] IPv4 VPN clients can connect
- [ ] IPv6 VPN clients can connect
- [ ] VPN traffic is masqueraded correctly
- [ ] Established connections are tracked
- [ ] Forwarding between interfaces works
- [ ] Management script functions correctly
### Migration Notes
#### For Existing Installations
If upgrading from UFW/iptables setup:
1. Stop WireGuard: `systemctl stop wg-quick@wg0`
2. Disable UFW: `ufw disable`
3. Remove UFW: `apt-get remove --purge ufw iptables`
4. Install nftables: `apt-get install nftables`
5. Run updated `install-wireguard.sh` or manually configure nftables
6. Start WireGuard: `systemctl start wg-quick@wg0`
#### Configuration Files Changed
- `install-wireguard.sh`: Replaced UFW with nftables
- `FIREWALL.md`: Updated with nftables documentation
- `README.md`: Updated commands and references
- `VALIDATION.md`: This document (new)
#### New Files Created
- `/etc/nftables.d/wireguard.conf`: Main nftables configuration
- `/usr/local/sbin/nftables-firewall`: Management script
### Advantages Summary
**Over UFW**:
- More direct control over rules
- No abstraction layer
- Better performance
- Single configuration file
- Easier to audit
**Over iptables/ip6tables**:
- Unified IPv4/IPv6 rules
- More concise syntax
- Better performance
- Modern architecture
- Active development
### Conclusion
The migration to nftables provides:
1. ✅ Full functional equivalence with UFW/iptables
2. ✅ Better performance and efficiency
3. ✅ Simpler, more maintainable configuration
4. ✅ Modern, actively-maintained framework
5. ✅ Unified IPv4/IPv6 support
All scripts have been validated and syntax-checked. The new implementation is production-ready.

View File

@@ -155,6 +155,8 @@ EOF
# Configure nftables # Configure nftables
echo "Configuring nftables firewall..." echo "Configuring nftables firewall..."
mkdir -p /etc/nftables.d mkdir -p /etc/nftables.d
# Create wireguard config in /etc/nftables.d
cat > /etc/nftables.d/wireguard.conf <<EOF cat > /etc/nftables.d/wireguard.conf <<EOF
#!/usr/sbin/nft -f #!/usr/sbin/nft -f
# nftables configuration for WireGuard VPN # nftables configuration for WireGuard VPN
@@ -206,7 +208,34 @@ table ip6 nat {
} }
EOF EOF
nft -f /etc/nftables.d/wireguard.conf # Create /etc/nftables.conf that includes wireguard.conf
# The nftables service loads /etc/nftables.conf by default
cat > /etc/nftables.conf <<EOF
#!/usr/sbin/nft -f
# nftables configuration automatically generated by wireguard.sh
flush ruleset
include "/etc/nftables.d/wireguard.conf"
EOF
chmod 600 /etc/nftables.conf
chmod 600 /etc/nftables.d/wireguard.conf
nft -f /etc/nftables.conf
# Enable nftables service to load rules on boot
echo "Enabling nftables service..."
systemctl enable nftables.service
systemctl start nftables.service
# Verify nftables is running
if ! systemctl is-active --quiet nftables.service; then
echo "ERROR: nftables service failed to start"
echo "=== Service Status ==="
systemctl status nftables.service
exit 1
fi
echo "nftables service started successfully"
# Generate server keys # Generate server keys
echo "Generating server keys..." echo "Generating server keys..."