feat: add return port listener for WAF async callbacks/alerts
This commit is contained in:
parent
32d60a3583
commit
6c8815749f
4 changed files with 39 additions and 0 deletions
|
|
@ -12,6 +12,7 @@ import (
|
|||
type Config struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
WAFURL string `json:"waf_url"`
|
||||
ReturnPort int `json:"return_port"` // port for WAF async callbacks
|
||||
HealthInterval int `json:"health_interval"`
|
||||
TimeoutMs int `json:"timeout_ms"`
|
||||
}
|
||||
|
|
|
|||
30
main.go
30
main.go
|
|
@ -41,6 +41,20 @@ func main() {
|
|||
// Start background health checker.
|
||||
startHealthCheck()
|
||||
|
||||
// Return port listener for WAF async callbacks.
|
||||
cfg := getConfig()
|
||||
if cfg.ReturnPort > 0 {
|
||||
go func() {
|
||||
rmux := http.NewServeMux()
|
||||
rmux.HandleFunc("/verdict", handleReturnVerdict)
|
||||
addr := fmt.Sprintf(":%d", cfg.ReturnPort)
|
||||
log.Printf("Firewall: return listener on %s", addr)
|
||||
if err := http.ListenAndServe(addr, rmux); err != nil {
|
||||
log.Printf("Firewall: return listener error: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Static capture handler — all proxied traffic hits this.
|
||||
|
|
@ -85,6 +99,9 @@ func handleSaveConfig(w http.ResponseWriter, r *http.Request) {
|
|||
if u := r.FormValue("waf_url"); u != "" {
|
||||
cfg.WAFURL = u
|
||||
}
|
||||
if v := r.FormValue("return_port"); v != "" {
|
||||
fmt.Sscanf(v, "%d", &cfg.ReturnPort)
|
||||
}
|
||||
if v := r.FormValue("health_interval"); v != "" {
|
||||
fmt.Sscanf(v, "%d", &cfg.HealthInterval)
|
||||
}
|
||||
|
|
@ -105,6 +122,19 @@ func handleGetStats(w http.ResponseWriter, r *http.Request) {
|
|||
writeJSON(w, http.StatusOK, metricsSnapshot())
|
||||
}
|
||||
|
||||
func handleReturnVerdict(w http.ResponseWriter, r *http.Request) {
|
||||
var v struct {
|
||||
Verdict string `json:"verdict"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "bad payload"})
|
||||
return
|
||||
}
|
||||
log.Printf("Firewall: async verdict %s (reason=%s)", v.Verdict, v.Reason)
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
// --- Helpers ---
|
||||
|
||||
func writeJSON(w http.ResponseWriter, status int, v interface{}) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ function loadConfig() {
|
|||
$('#fw-enabled').prop('checked', data.enabled);
|
||||
$('#enabled-label').text(data.enabled ? 'Firewall Enabled' : 'Firewall Disabled');
|
||||
$('#waf-url').val(data.waf_url);
|
||||
$('#return-port').val(data.return_port);
|
||||
$('#health-interval').val(data.health_interval);
|
||||
$('#timeout-ms').val(data.timeout_ms);
|
||||
});
|
||||
|
|
@ -31,6 +32,7 @@ function saveConfig() {
|
|||
data: {
|
||||
enabled: $('#fw-enabled').is(':checked'),
|
||||
waf_url: $('#waf-url').val().trim(),
|
||||
return_port: $('#return-port').val(),
|
||||
health_interval: $('#health-interval').val(),
|
||||
timeout_ms: $('#timeout-ms').val()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@
|
|||
<small>The firewall service that inspects each request and returns a verdict.</small>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="return-port">Return Port (async callbacks)</label>
|
||||
<input type="number" id="return-port" placeholder="9090" min="1" max="65535">
|
||||
<small>WAF sends async verdicts/alerts to this port.</small>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="health-interval">Health Check Interval (s)</label>
|
||||
<input type="number" id="health-interval" placeholder="5" min="1" max="60">
|
||||
|
|
|
|||
Loading…
Reference in a new issue