Skip to content

Commit dbde635

Browse files
committed
fix: security audit remediation — 29 findings across 92 files
1 parent 961ee90 commit dbde635

53 files changed

Lines changed: 31421 additions & 244 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dfmt/journal.jsonl

Whitespace-only changes.

cover_admin.html

Lines changed: 2906 additions & 0 deletions
Large diffs are not rendered by default.

deploy/.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# TLS certificates (bring your own)
2+
certs/
3+
*.crt
4+
*.key
5+
6+
# Data volumes
7+
prometheus-data/
8+
grafana-data/
9+
alertmanager-data/
10+
redis-data/
11+
olb-logs/
12+
13+
# Environment files
14+
.env
15+
.env.local

deploy/README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# OpenLoadBalancer Deployment
2+
3+
## Quick Start with Docker
4+
5+
### 1. Pull the image
6+
```bash
7+
docker pull ghcr.io/openloadbalancer/olb:latest
8+
```
9+
10+
### 2. Create your configuration
11+
```bash
12+
mkdir -p configs certs
13+
# Create olb.yaml in configs/ directory
14+
```
15+
16+
### 3. Run
17+
```bash
18+
docker compose up -d
19+
```
20+
21+
## Docker Compose Files
22+
23+
### Single Node (`deploy/docker-compose.yml`)
24+
Full stack with Prometheus, Grafana, and Alertmanager.
25+
26+
```yaml
27+
services:
28+
olb:
29+
image: ghcr.io/openloadbalancer/olb:latest
30+
ports:
31+
- "80:80" # HTTP
32+
- "443:443" # HTTPS
33+
- "8081:8081" # Admin API
34+
- "8082:8082" # MCP Server
35+
volumes:
36+
- ./configs/olb.yaml:/etc/olb/configs/olb.yaml:ro
37+
- ./certs:/etc/olb/certs:ro
38+
- olb-logs:/var/log/olb
39+
environment:
40+
- OLB_CONFIG=/etc/olb/configs/olb.yaml
41+
- OLB_LOG_LEVEL=info
42+
```
43+
44+
### 3-Node Cluster (`docker-compose.yml` in repo root)
45+
See cluster deployment in the repo root.
46+
47+
## Environment Variables
48+
49+
| Variable | Default | Description |
50+
|----------|---------|-------------|
51+
| `OLB_CONFIG` | `/etc/olb/olb.yaml` | Config file path |
52+
| `OLB_LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |
53+
| `OLB_ADMIN_ADDR` | `:8081` | Admin API address |
54+
| `GRAFANA_ADMIN_PASSWORD` | `changeme` | Grafana admin password |
55+
56+
## Ports
57+
58+
| Port | Service | Description |
59+
|------|---------|-------------|
60+
| 80 | HTTP | Load balancer HTTP listener |
61+
| 443 | HTTPS | Load balancer HTTPS listener |
62+
| 8081 | Admin API | REST API for management |
63+
| 8082 | MCP Server | Model Context Protocol |
64+
| 9090 | Prometheus | Metrics collection |
65+
| 9093 | Alertmanager | Alert routing |
66+
| 3000 | Grafana | Dashboards |
67+
68+
## Example Config
69+
70+
```yaml
71+
listeners:
72+
- name: http
73+
address: ":80"
74+
protocol: http
75+
76+
pools:
77+
- name: web
78+
algorithm: round_robin
79+
backends:
80+
- address: "localhost:8080"
81+
- address: "localhost:8081"
82+
83+
admin:
84+
address: ":8081"
85+
```
86+
87+
## Health Check
88+
89+
```bash
90+
docker exec olb olb health
91+
```
92+
93+
## Observability Stack
94+
95+
The full stack includes:
96+
- **Prometheus** — Metrics collection (port 9090)
97+
- **Grafana** — Visualization (port 3000)
98+
- **Alertmanager** — Alert routing (port 9093)
99+
- **Node Exporter** — System metrics
100+
101+
Start with observability:
102+
```bash
103+
docker compose up -d prometheus grafana alertmanager
104+
```
105+
106+
## TLS Certificates
107+
108+
Place certificates in `./certs/`:
109+
```
110+
certs/
111+
├── server.crt # TLS certificate
112+
└── server.key # TLS private key
113+
```

deploy/configs/olb.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# OpenLoadBalancer Configuration
2+
# Copy this file to configs/olb.yaml and modify as needed
3+
4+
listeners:
5+
- name: http
6+
address: ":80"
7+
protocol: http
8+
9+
- name: https
10+
address: ":443"
11+
protocol: https
12+
tls:
13+
enabled: true
14+
cert_file: /etc/olb/certs/server.crt
15+
key_file: /etc/olb/certs/server.key
16+
17+
pools:
18+
- name: web
19+
algorithm: round_robin
20+
backends:
21+
- address: "localhost:8080"
22+
weight: 1
23+
- address: "localhost:8081"
24+
weight: 1
25+
health_check:
26+
type: http
27+
path: /health
28+
interval: 10s
29+
timeout: 2s
30+
31+
admin:
32+
address: ":8081"
33+
34+
logging:
35+
level: info
36+
format: json
37+
output: /var/log/olb/olb.log

docker-compose.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
services:
2020
# ─── OLB Cluster Nodes ────────────────────────────────────────────────
2121
olb-1:
22-
image: openloadbalancer/olb:latest
22+
image: ghcr.io/openloadbalancer/olb:latest
2323
build:
2424
context: .
2525
dockerfile: Dockerfile
@@ -63,7 +63,7 @@ services:
6363
condition: service_healthy
6464

6565
olb-2:
66-
image: openloadbalancer/olb:latest
66+
image: ghcr.io/openloadbalancer/olb:latest
6767
build:
6868
context: .
6969
dockerfile: Dockerfile
@@ -107,7 +107,7 @@ services:
107107
condition: service_healthy
108108

109109
olb-3:
110-
image: openloadbalancer/olb:latest
110+
image: ghcr.io/openloadbalancer/olb:latest
111111
build:
112112
context: .
113113
dockerfile: Dockerfile

docs/configuration.md

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,192 @@ See [mcp.md](mcp.md) for integration details.
683683

684684
---
685685

686+
## Profiling
687+
688+
Go runtime profiling via pprof HTTP endpoint.
689+
690+
```yaml
691+
profiling:
692+
enabled: true
693+
pprof_addr: "localhost:6060" # pprof HTTP endpoint (localhost only recommended)
694+
cpu_profile_path: "" # Write CPU profile to file on shutdown
695+
mem_profile_path: "" # Write heap profile to file on shutdown
696+
block_profile_rate: 0 # Fraction of goroutine blocking events to report (0 = off)
697+
mutex_profile_fraction: 0 # Fraction of mutex contention events to report (0 = off)
698+
token: "" # Bearer token for pprof auth (empty = no auth, localhost-only recommended)
699+
```
700+
701+
When `token` is set, all pprof endpoints require `Authorization: Bearer <token>`.
702+
703+
---
704+
705+
## WAF (Web Application Firewall)
706+
707+
Six-layer security pipeline: SQLi, XSS, CMDi, XXE, SSRF, and Path Traversal detection.
708+
709+
```yaml
710+
waf:
711+
enabled: true
712+
mode: enforce # "enforce" (block), "monitor" (log only), "disabled"
713+
714+
ip_acl:
715+
enabled: true
716+
whitelist: # Always allowed, bypasses all checks
717+
- cidr: "10.0.0.0/8"
718+
blacklist: # Always blocked
719+
- cidr: "192.168.1.100/32"
720+
auto_ban:
721+
enabled: true
722+
threshold: 100 # Requests in window before auto-ban
723+
window: "60s" # Time window for threshold counting
724+
duration: "3600s" # How long the ban lasts
725+
726+
rate_limit:
727+
enabled: true
728+
requests_per_second: 100 # Max requests per second per IP
729+
burst: 200 # Burst allowance
730+
window: "60s" # Fixed window duration
731+
732+
sanitizer:
733+
enabled: true
734+
strip_null_bytes: true
735+
normalize_unicode: true
736+
max_header_value_length: 8192
737+
738+
detection:
739+
enabled: true
740+
sqli:
741+
enabled: true
742+
mode: pattern # "pattern" or "semantic"
743+
xss:
744+
enabled: true
745+
mode: pattern
746+
cmdi:
747+
enabled: true
748+
xxe:
749+
enabled: true
750+
ssrf:
751+
enabled: true
752+
blocked_cidrs:
753+
- "127.0.0.0/8"
754+
- "10.0.0.0/8"
755+
- "172.16.0.0/12"
756+
- "192.168.0.0/16"
757+
- "169.254.0.0/16"
758+
- "0.0.0.0/0"
759+
path_traversal:
760+
enabled: true
761+
762+
bot_detection:
763+
enabled: true
764+
user_agent_blacklist:
765+
- "malicious-bot"
766+
challenge_mode: "none" # "none", "captcha", "javascript"
767+
768+
response:
769+
enabled: true
770+
hide_server_header: true
771+
hide_powered_by: true
772+
773+
logging:
774+
enabled: true
775+
log_body: false # Log request body (may contain sensitive data)
776+
max_body_log_size: 1024
777+
```
778+
779+
---
780+
781+
## GeoDNS
782+
783+
Geographic DNS routing based on client IP location.
784+
785+
```yaml
786+
geodns:
787+
enabled: true
788+
default_pool: "us-east-pool" # Fallback pool when no rule matches
789+
db_path: "/etc/olb/GeoLite2-City.mmdb" # MaxMind GeoLite2 database
790+
791+
rules:
792+
- id: "eu-rule"
793+
country: "DE" # ISO 3166-1 alpha-2 country code
794+
pool: "eu-west-pool" # Route to this pool
795+
weight: 100 # Routing weight
796+
797+
- id: "asia-rule"
798+
country: "JP"
799+
pool: "ap-northeast-pool"
800+
weight: 100
801+
802+
- id: "fallback-rule"
803+
country: "*" # Wildcard matches all
804+
pool: "us-east-pool"
805+
weight: 50
806+
```
807+
808+
Requires a MaxMind GeoLite2 City database (MMDB format). Download from [MaxMind](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data).
809+
810+
---
811+
812+
## Shadow Traffic
813+
814+
Mirror production traffic to a shadow backend for testing and analysis. Shadow responses are discarded — never returned to the client.
815+
816+
```yaml
817+
shadow:
818+
enabled: true
819+
percentage: 10.0 # Percentage of traffic to mirror (0-100)
820+
copy_headers: true # Copy request headers to shadow
821+
copy_body: true # Copy request body to shadow
822+
timeout: "5s" # Shadow request timeout
823+
824+
targets:
825+
- pool: "shadow-pool" # Target pool for mirrored traffic
826+
percentage: 100.0 # Percentage of shadowed traffic to this target
827+
```
828+
829+
Sensitive headers (Authorization, Cookie, Proxy-Authorization, X-Session-ID, X-CSRF-Token) are automatically stripped from shadow requests.
830+
831+
---
832+
833+
## Service Discovery
834+
835+
Service discovery is configured per-pool, not at the top level. Each pool can use one or more discovery providers.
836+
837+
```yaml
838+
pools:
839+
- name: "api-pool"
840+
algorithm: round_robin
841+
842+
discovery:
843+
type: "dns" # "dns", "docker", "consul", "static", "file"
844+
interval: "30s" # Refresh interval
845+
846+
# DNS discovery
847+
domain: "_api._tcp.example.com"
848+
nameserver: "8.8.8.8:53"
849+
850+
# Docker discovery
851+
# docker_host: "unix:///var/run/docker.sock"
852+
# docker_label_filter: "com.example.service=api"
853+
854+
# Consul discovery
855+
# consul_addr: "http://127.0.0.1:8500"
856+
# consul_service: "api"
857+
# consul_tag: "production"
858+
859+
backends: [] # Optional static backends merged with discovered ones
860+
```
861+
862+
| Provider | Config Key | Notes |
863+
|----------|-----------|-------|
864+
| DNS | `dns` | SRV record lookup. Queries over plaintext — see warnings at startup. |
865+
| Docker | `docker` | Docker daemon API. Use TLS for remote connections. |
866+
| Consul | `consul` | Consul catalog API. HTTP only. |
867+
| Static | (none) | Uses `backends` list directly. No auto-discovery. |
868+
| File | `file` | Read backends from a JSON/YAML file. |
869+
870+
---
871+
686872
## Complete Example
687873

688874
See [configs/olb.yaml](../configs/olb.yaml) for a full annotated configuration example.

0 commit comments

Comments
 (0)