| name | reverse-proxy |
| description | Manage incoming internet traffic and reverse proxy configuration on the home network gateway. Configure Caddy, OAuth2 authentication, fail2ban security, and traffic routing. |
Reverse Proxy & Traffic Management Skill
This skill enables management of incoming internet traffic and reverse proxy configuration on the home network, specifically focused on the Raspberry Pi gateway running Caddy, OAuth2-proxy, and fail2ban security.
Overview
The reverse-proxy skill provides capabilities to manage the public-facing gateway server (raspberrypi.local) that handles:
- HTTPS termination with Let's Encrypt
- OAuth2 authentication for protected services
- Security monitoring with fail2ban
- Reverse proxying to internal services
This server is the source of truth for all incoming traffic configuration. Reference repository: /home/seth/Software/dev/squelch
Gateway Server
raspberrypi (Gateway/Proxy Server)
- Host: raspberrypi.local (192.168.0.76)
- SSH:
ssh pi (port 2222)
- Public Domain: lab.sethlakowske.com
- Role: Internet gateway, reverse proxy, OAuth gateway, security enforcement
- Key Services:
- Caddy (port 443 HTTPS, port 80 HTTP)
- oauth2-proxy-google (port 4180)
- oauth2-proxy-good-neighbor (port 4182)
- oauth2-proxy-service-monitor (port 4183)
- fail2ban (security)
- service-monitor (port 8000)
Configuration Repository
- Location:
/home/seth/Software/dev/squelch
- Structure:
oauth-caddy-package/ - OAuth2 authentication package
squelch-package/ - fail2ban security package
config-backup/ - Production configuration backups
CLAUDE.md - Complete architecture documentation
Architecture
Internet (lab.sethlakowske.com)
|
v
[Caddy :443] ────── Let's Encrypt HTTPS
|
├─> /oauth2/* ──> [oauth2-proxy :4180] Google Auth
├─> /good-neighbor/* ──> [oauth2-proxy :4182] ──> Backend :3000
├─> /service-monitor/* ──> [oauth2-proxy :4183] ──> Backend :8000
└─> /* ──> Backend :8080 (public)
|
v
[fail2ban] monitors /var/log/caddy/access.log
|
v
[iptables] blocks malicious IPs
Common Operations
1. Check Gateway Status
ssh pi "systemctl status caddy oauth2-proxy-google oauth2-proxy-good-neighbor oauth2-proxy-service-monitor fail2ban"
ssh pi "systemctl is-active caddy oauth2-proxy-google fail2ban"
ssh pi "sudo ss -tlnp | grep -E '(443|4180|4182|4183|8000)'"
2. Manage Caddy
ssh pi "systemctl status caddy"
ssh pi "cat /etc/caddy/Caddyfile"
ssh pi "sudo caddy validate --config /etc/caddy/Caddyfile"
ssh pi "sudo systemctl reload caddy"
ssh pi "sudo systemctl restart caddy"
ssh pi "journalctl -u caddy -n 100 --no-pager"
ssh pi "journalctl -u caddy -f"
ssh pi "tail -f /var/log/caddy/access.log"
ssh pi "tail -100 /var/log/caddy/access.log | jq ."
3. Manage OAuth2-Proxy Services
ssh pi "systemctl status oauth2-proxy-google"
ssh pi "systemctl status oauth2-proxy-good-neighbor"
ssh pi "systemctl status oauth2-proxy-service-monitor"
ssh pi "sudo systemctl restart oauth2-proxy-google"
ssh pi "journalctl -u oauth2-proxy-google -n 50 --no-pager"
ssh pi "journalctl -u oauth2-proxy-good-neighbor -f"
ssh pi "cat /etc/oauth2-proxy/google.cfg"
ssh pi "cat /etc/oauth2-proxy/good-neighbor.cfg"
ssh pi "curl -s http://localhost:4180/ping"
4. Manage fail2ban Security
ssh pi "sudo systemctl status fail2ban"
ssh pi "sudo fail2ban-client status"
ssh pi "sudo fail2ban-client status sshd"
ssh pi "sudo fail2ban-client status squelch-caddy-auth"
ssh pi "sudo fail2ban-client status squelch-caddy-badbots"
ssh pi "sudo fail2ban-client status squelch-caddy-scan"
ssh pi "sudo squelch-ban list"
ssh pi "sudo squelch-ban list squelch-caddy-auth"
ssh pi "sudo squelch-ban ban 1.2.3.4 squelch-caddy-auth"
ssh pi "sudo squelch-ban unban 1.2.3.4"
ssh pi "sudo squelch-ban check 1.2.3.4"
ssh pi "sudo journalctl -u fail2ban -n 100 --no-pager"
ssh pi "sudo journalctl -u fail2ban | grep Ban"
5. Security Status Dashboard
ssh pi "sudo squelch-status"
ssh pi "sudo squelch-monitor"
ssh pi "sudo journalctl -u fail2ban --since '1 hour ago' | grep -E '(Ban|Found)'"
ssh pi "tail -100 /var/log/caddy/access.log | jq -r '.request.remote_ip' | sort | uniq -c | sort -nr"
6. Add New Protected Route
To add a new service behind OAuth authentication:
-
Verify backend service is running:
curl -s http://ubuntu-box.local:3001/health
-
Create OAuth2-proxy configuration:
ssh pi
sudo cp /etc/oauth2-proxy/good-neighbor.cfg.template /etc/oauth2-proxy/new-service.cfg
sudo nano /etc/oauth2-proxy/new-service.cfg
-
Create systemd service:
sudo cat > /etc/systemd/system/oauth2-proxy-new-service.service << 'EOF'
[Unit]
Description=OAuth2 Proxy for New Service
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
ExecStart=/usr/bin/oauth2-proxy --config=/etc/oauth2-proxy/new-service.cfg
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable oauth2-proxy-new-service
sudo systemctl start oauth2-proxy-new-service
sudo systemctl status oauth2-proxy-new-service
4. **Update Caddyfile**:
```bash
sudo nano /etc/caddy/Caddyfile
# Add route (before the catch-all /* route):
# route /new-service* {
# reverse_proxy localhost:4184
# }
-
Apply Caddy changes:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
-
Verify setup:
curl -s http://localhost:4184/ping
curl -I https://lab.sethlakowske.com/new-service/
-
Backup configuration:
scp pi:/etc/caddy/Caddyfile ~/Software/dev/squelch/config-backup/caddy/
scp pi:/etc/oauth2-proxy/new-service.cfg ~/Software/dev/squelch/config-backup/oauth2-proxy/
7. Add Public (Non-Authenticated) Route
For services that don't require OAuth:
-
Update Caddyfile:
ssh pi "sudo nano /etc/caddy/Caddyfile"
-
Reload Caddy:
ssh pi "sudo caddy validate --config /etc/caddy/Caddyfile && sudo systemctl reload caddy"
-
Test:
curl -s https://lab.sethlakowske.com/public-api/health | jq .
8. Update Backend Port Mapping
To change where a route proxies to:
-
For OAuth-protected routes, update OAuth2-proxy config:
ssh pi "sudo nano /etc/oauth2-proxy/good-neighbor.cfg"
ssh pi "sudo systemctl restart oauth2-proxy-good-neighbor"
-
For public routes, update Caddyfile:
ssh pi "sudo nano /etc/caddy/Caddyfile"
ssh pi "sudo systemctl reload caddy"
9. View Current Route Configuration
ssh pi "cat /etc/caddy/Caddyfile | grep -A 2 'route'"
ssh pi "grep 'upstreams' /etc/oauth2-proxy/*.cfg"
ssh pi "sudo ss -tlnp | grep -E '(caddy|oauth2-proxy)'"
10. Analyze Traffic Patterns
ssh pi "tail -1000 /var/log/caddy/access.log | jq -r '.request.remote_ip' | sort | uniq -c | sort -nr | head -10"
ssh pi "tail -1000 /var/log/caddy/access.log | jq -r '.request.uri' | sort | uniq -c | sort -nr | head -10"
ssh pi "tail -1000 /var/log/caddy/access.log | jq 'select(.status == 401 or .status == 403)'"
ssh pi "tail -1000 /var/log/caddy/access.log | jq -r '.duration' | awk '{sum+=\$1; count++} END {print \"Average:\", sum/count, \"seconds\"}'"
ssh pi "tail -1000 /var/log/caddy/access.log | jq -r '.status' | sort | uniq -c | sort -nr"
Configuration Files Reference
Critical Configuration Files
| File | Purpose | Service |
|---|
/etc/caddy/Caddyfile | Main reverse proxy configuration | caddy |
/etc/oauth2-proxy/google.cfg | Google OAuth for general use | oauth2-proxy-google |
/etc/oauth2-proxy/good-neighbor.cfg | OAuth for good-neighbor service | oauth2-proxy-good-neighbor |
/etc/oauth2-proxy/service-monitor.cfg | OAuth for service-monitor | oauth2-proxy-service-monitor |
/etc/fail2ban/jail.d/squelch.conf | fail2ban jail configuration | fail2ban |
/etc/fail2ban/filter.d/squelch-*.conf | fail2ban filters | fail2ban |
/var/log/caddy/access.log | HTTP access logs (JSON) | caddy |
Configuration Backup Location
All production configs should be backed up to:
~/Software/dev/squelch/config-backup/
├── caddy/
│ ├── Caddyfile
│ └── Caddyfile.template
└── oauth2-proxy/
├── google.cfg
├── good-neighbor.cfg
├── service-monitor.cfg
└── *.cfg.template
Backup Workflow
ssh pi "cat /etc/caddy/Caddyfile" > ~/Software/dev/squelch/config-backup/caddy/Caddyfile
ssh pi "cat /etc/oauth2-proxy/google.cfg" > ~/Software/dev/squelch/config-backup/oauth2-proxy/google.cfg
scp pi:/etc/caddy/Caddyfile ~/Software/dev/squelch/config-backup/caddy/
scp pi:/etc/oauth2-proxy/*.cfg ~/Software/dev/squelch/config-backup/oauth2-proxy/
cd ~/Software/dev/squelch
git add config-backup/
git commit -m "Backup production proxy configs"
git push
Routing Patterns
Current Routes (lab.sethlakowske.com)
Based on the production Caddyfile:
| Route | Auth | Backend | Port | Description |
|---|
/oauth2/* | No | oauth2-proxy | 4180 | OAuth callback handler |
/good-neighbor* | Yes (Google) | good-neighbor | 3000 | Protected service |
/service-monitor* | Yes (Google) | service-monitor | 8000 | Protected monitoring |
/* | No | default backend | 8080 | Public routes |
Caddy Route Ordering
IMPORTANT: Caddy processes routes in order. More specific routes must come BEFORE catch-all routes:
lab.sethlakowske.com {
log {
output file /var/log/caddy/access.log
}
# OAuth callback (most specific)
route /oauth2/* {
reverse_proxy localhost:4180
}
# Protected service routes
route /good-neighbor* {
reverse_proxy localhost:4182
}
route /service-monitor* {
reverse_proxy localhost:4183
}
# Catch-all public routes (LAST)
route /* {
reverse_proxy localhost:8080
}
}
Security Monitoring
fail2ban Jails
| Jail Name | Purpose | Trigger | Max Retry | Ban Time |
|---|
sshd | SSH brute force | Failed SSH login | 2 | 24h |
squelch-caddy-auth | Auth failures | 401/403 responses | 5 | 1h+ |
squelch-caddy-badbots | Bad bots/scanners | Attack paths | 2 | 1h+ |
squelch-caddy-scan | Directory scanning | Multiple 404s | 3 | 1h+ |
Ban Escalation
fail2ban uses progressive ban times:
- 1st offense: 1 hour
- 2nd offense: 2 hours
- 3rd offense: 4 hours
- Continues doubling up to max 168h (7 days)
Monitoring Commands
ssh pi "sudo journalctl -u fail2ban -f | grep Ban"
ssh pi "sudo journalctl -u fail2ban --since '1 hour ago' | grep 'Ban '"
ssh pi "sudo fail2ban-client status | grep 'Currently banned:'"
ssh pi "tail -1000 /var/log/caddy/access.log | jq 'select(.status >= 400) | {ip: .request.remote_ip, status: .status, uri: .request.uri}'"
Troubleshooting
Problem: Service Not Accessible from Internet
-
Check Caddy is running and listening:
ssh pi "systemctl status caddy"
ssh pi "sudo ss -tlnp | grep :443"
-
Check route configuration:
ssh pi "cat /etc/caddy/Caddyfile | grep -A 3 'route /your-service'"
-
Test from gateway server:
ssh pi "curl -I http://localhost:4180/ping"
ssh pi "curl -I https://localhost/your-service/"
-
Check DNS:
dig lab.sethlakowske.com
-
Check firewall:
ssh pi "sudo iptables -L -n | grep -E '(443|80)'"
Problem: OAuth Loop/Redirect Issues
-
Check OAuth proxy is running:
ssh pi "systemctl status oauth2-proxy-google"
-
Verify OAuth config:
ssh pi "grep redirect_url /etc/oauth2-proxy/google.cfg"
-
Check cookie settings:
ssh pi "grep -E '(cookie_secure|cookie_domain)' /etc/oauth2-proxy/google.cfg"
-
View OAuth logs:
ssh pi "journalctl -u oauth2-proxy-google -n 50 --no-pager"
Problem: fail2ban Banning Legitimate IPs
-
Check which jail banned the IP:
ssh pi "sudo squelch-ban check 192.168.1.100"
-
Review why IP was banned:
ssh pi "sudo journalctl -u fail2ban | grep '192.168.1.100'"
-
Unban the IP:
ssh pi "sudo squelch-ban unban 192.168.1.100"
-
Add to ignore list (if trusted):
ssh pi "sudo nano /etc/fail2ban/jail.d/squelch.conf"
ssh pi "sudo systemctl restart fail2ban"
Problem: Backend Service Not Receiving Traffic
-
Check backend is running:
curl -s http://ubuntu-box.local:3000/health
-
Verify OAuth proxy upstream:
ssh pi "grep upstreams /etc/oauth2-proxy/good-neighbor.cfg"
-
Test OAuth proxy directly:
ssh pi "curl -I http://localhost:4182/"
-
Check Caddy route:
ssh pi "cat /etc/caddy/Caddyfile | grep -A 2 'good-neighbor'"
Problem: SSL Certificate Issues
-
Check certificate status:
ssh pi "journalctl -u caddy | grep -i certificate"
-
Verify DNS is correct:
dig lab.sethlakowske.com
-
Check port 80 is accessible (needed for Let's Encrypt):
ssh pi "sudo ss -tlnp | grep :80"
-
Force certificate renewal:
ssh pi "sudo systemctl restart caddy"
Reference Documentation
Complete architecture documentation available at:
~/Software/dev/squelch/CLAUDE.md
This includes:
- Detailed component interactions
- Security architecture (defense-in-depth)
- Attack scenario walkthroughs
- Configuration patterns
- Best practices
- Maintenance procedures
Integration with Other Skills
network-admin Skill
- Use network-admin for general server management commands
- reverse-proxy focuses specifically on traffic/proxy configuration
- Coordinate for service deployments requiring both skills
service-monitor Skill
Usage Guidelines
When to Use reverse-proxy
Use this skill for:
- Configuring new public-facing routes
- Managing OAuth authentication for services
- Analyzing traffic patterns and security events
- Troubleshooting access issues from internet
- Managing fail2ban security
- Updating SSL/TLS configuration
- Monitoring gateway health
When to Delegate to Remote Claude
For complex gateway changes:
ssh pi -t "cd ~/Software/dev/squelch && lfg"
Best Practices
-
Always backup configs before changes:
scp pi:/etc/caddy/Caddyfile ~/Software/dev/squelch/config-backup/caddy/
-
Validate Caddy config before reload:
ssh pi "sudo caddy validate --config /etc/caddy/Caddyfile"
-
Use reload instead of restart (when possible):
ssh pi "sudo systemctl reload caddy"
-
Monitor logs after changes:
ssh pi "journalctl -u caddy -f"
-
Document route changes in git commits
-
Test from multiple locations:
- From gateway:
ssh pi "curl http://localhost:PORT"
- From LAN:
curl http://raspberrypi.local:PORT
- From internet:
curl https://lab.sethlakowske.com/route
Common Workflows
Workflow 1: Deploy New Protected Service
- Service is running on ubuntu-box:3001
- Create OAuth proxy config on gateway
- Create systemd service for OAuth proxy
- Update Caddyfile with new route
- Reload Caddy
- Test from internet
- Backup configs to git
Workflow 2: Investigate Security Event
- Check fail2ban status:
ssh pi "sudo squelch-status"
- Review banned IPs:
ssh pi "sudo squelch-ban list"
- Analyze access logs:
ssh pi "tail -1000 /var/log/caddy/access.log | jq 'select(.status >= 400)'"
- Review fail2ban logs:
ssh pi "sudo journalctl -u fail2ban --since '1 hour ago'"
- Determine if legitimate or attack
- Take action (unban or leave banned)
Workflow 3: Update Backend Port
- Verify new backend works:
curl http://ubuntu-box.local:NEW_PORT/health
- Update OAuth proxy config: edit
/etc/oauth2-proxy/SERVICE.cfg
- Restart OAuth proxy:
sudo systemctl restart oauth2-proxy-SERVICE
- Test:
curl https://lab.sethlakowske.com/service/
- Backup config
Workflow 4: Add Temporary Public Route
- Edit Caddyfile:
ssh pi "sudo nano /etc/caddy/Caddyfile"
- Add route BEFORE catch-all
- Validate:
ssh pi "sudo caddy validate --config /etc/caddy/Caddyfile"
- Reload:
ssh pi "sudo systemctl reload caddy"
- Test:
curl https://lab.sethlakowske.com/new-route/
Examples
Example 1: Check Gateway Health
ssh pi "systemctl is-active caddy oauth2-proxy-google fail2ban && echo 'Gateway healthy'"
ssh pi "sudo squelch-status"
Example 2: Analyze Failed Auth Attempts
ssh pi "tail -500 /var/log/caddy/access.log | jq 'select(.status == 401 or .status == 403) | {time: .ts, ip: .request.remote_ip, uri: .request.uri, status: .status}'"
ssh pi "tail -1000 /var/log/caddy/access.log | jq -r 'select(.status == 401) | .request.remote_ip' | sort | uniq -c | sort -nr"
Example 3: Emergency IP Ban
ssh pi "sudo squelch-ban ban 1.2.3.4 squelch-caddy-auth"
ssh pi "sudo squelch-ban ban 1.2.3.4 squelch-caddy-badbots"
ssh pi "sudo squelch-ban ban 1.2.3.4 squelch-caddy-scan"
ssh pi "sudo squelch-ban check 1.2.3.4"
Example 4: View Current Configuration
ssh pi "cat /etc/caddy/Caddyfile | grep -E '(route|reverse_proxy)'"
ssh pi "grep -E '(http_address|upstreams)' /etc/oauth2-proxy/*.cfg"
ssh pi "systemctl list-units --type=service --state=running | grep -E '(caddy|oauth2-proxy|fail2ban)'"