How the Xray-core Router Webhook Works and When to Use It
Xray-core’s router webhook asynchronously sends a JSON POST request to a configured URL whenever a connection matches a specific routing rule, enabling real-time external monitoring and automated responses without blocking traffic flow.
The Xray-core router webhook feature allows operators to attach HTTP callbacks to routing rules for real-time event notification. When a connection matches a rule configured with a webhook, Xray-core immediately dispatches a JSON payload containing connection metadata to the specified endpoint. This capability, implemented in the app/router package of the XTLS/Xray-core repository, enables integration with external monitoring systems, SIEM tools, and automated response workflows.
Architecture and Implementation
The webhook functionality spans three distinct layers in the codebase:
Configuration Layer
WebhookConfig in app/router/config.proto and the generated struct in [app/router/config.pb.go](https://github.com/XTLS/Xray-core/blob/main/app/router/config.pb.go) declare the webhook URL, optional deduplication interval, and custom HTTP headers. The JSON/YAML parsing occurs in [infra/conf/router.go](https://github.com/XTLS/Xray-core/blob/main/infra/conf/router.go) via WebhookRuleConfig.
Rule Handling Layer
During router startup, [app/router/router.go](https://github.com/XTLS/Xray-core/blob/main/app/router/router.go) (lines 68‑82 and 175‑182) parses the configuration and creates a WebhookNotifier for each rule that defines a webhook. The notifier stores an http.Client, a deduplication map, and a done channel for graceful shutdown.
Notifier Execution Layer
The [app/router/webhook.go](https://github.com/XTLS/Xray-core/blob/main/app/router/webhook.go) file contains the core WebhookNotifier implementation. This component builds event payloads, manages optional deduplication logic, and executes HTTP POST requests. It supports both standard TCP endpoints and Unix domain sockets through custom URL parsing.
How the Webhook Triggering Process Works
When a connection traverses the Xray-core router, the webhook fires through a precise seven-stage pipeline:
-
Rule Definition – The
RoutingRuleprotobuf includes awebhookfield (seeWebhookConfig). In JSON configuration, this appears under the"webhook"key within a routing rule object. -
Router Initialization – While loading rules,
router.goinvokesNewWebhookNotifier(cfg)for each rule containing webhook configuration. This initializes the HTTP client and internal state. -
Connection Matching – When
PickRouteselects a rule for an incoming connection, it checksrule.Webhook != niland callsrule.Webhook.Fire(originalCtx, tag). -
Event Construction – The
buildEventfunction (lines 67‑81 inwebhook.go) extracts data from the routing context, including source IP/port, destination, protocol, inbound/outbound tags, user email, and timestamps, populating aneventstruct. -
Deduplication Check – If
deduplication > 0is configured, the notifier stores the user email and discards subsequent events from the same identity within the configured TTL window. -
HTTP Dispatch – The
postmethod marshals the event to JSON, constructs an HTTP request withContent-Type: application/json, injects custom headers, and transmits the payload. For Unix sockets,parseURLandresolveSocketPathconfigure the transport to dial the socket path (e.g.,/tmp/socket.sock:/path) instead of TCP. -
Resource Cleanup – When a rule reloads or the router shuts down, the
Closemethod stops background cleanup goroutines, waits for pending posts to complete, and closes idle connections.
When to Use the Xray-core Router Webhook
Deploy webhooks when you require real-time external visibility into routing decisions without modifying core proxy behavior:
-
External Monitoring and Alerting – Forward connection metadata to Prometheus pushgateway, Grafana Loki, or custom SIEM platforms for real-time visibility into traffic patterns.
-
Automated Security Responses – Trigger scripts that update blocklists or modify firewall rules when specific patterns emerge, such as connections from particular users, destinations, or protocols.
-
Audit Logging – Stream every permitted or denied connection to an immutable log store, Elasticsearch cluster, or SIEM without relying on Xray’s internal logging facilities.
-
Third-Party Service Integration – Notify Discord or Slack channels, trigger webhook-compatible CI/CD pipelines, or invoke cloud functions for additional processing when specific routes activate.
-
Load Balancer Health Checks – Send lightweight pings to health-check endpoints whenever traffic passes through critical routing rules to validate upstream availability.
The webhook executes asynchronously and never blocks the routing decision, ensuring safe deployment in high-throughput environments. The optional deduplication mechanism prevents event flooding when individual users generate many concurrent connections.
Configuration Examples
Standard HTTP Webhook
Configure a routing rule with a webhook that posts to an HTTP endpoint with deduplication enabled:
{
"type": "field",
"outboundTag": "proxy",
"domain": ["example.com"],
"webhook": {
"url": "http://192.168.1.100:8080/xray/webhook",
"deduplication": 30,
"headers": {
"X-Auth-Token": "my-secret-token"
}
}
}
When connections to example.com route through the proxy outbound, Xray-core POSTs a JSON event to the specified URL. Duplicate events from the same email address within 30 seconds are suppressed.
Unix Socket Webhook
For local integration with services like HAProxy, use Unix domain sockets with the socketPath:/http/path syntax:
{
"type": "field",
"outboundTag": "proxy",
"sourceIP": ["10.0.0.0/8"],
"webhook": {
"url": "/var/run/haproxy.sock:/v2/events",
"deduplication": 0
}
}
The parseURL function in webhook.go detects the Unix socket prefix and configures the HTTP transport to dial /var/run/haproxy.sock while posting to the /v2/events path.
Go Webhook Receiver
Implement a minimal HTTP server to receive and process Xray-core webhook events:
package main
import (
"encoding/json"
"log"
"net/http"
)
type XrayEvent struct {
Email *string `json:"email"`
Level *uint32 `json:"level"`
Protocol *string `json:"protocol"`
Network *string `json:"network"`
Source *string `json:"source"`
Destination *string `json:"destination"`
InboundTag *string `json:"inboundTag"`
OutboundTag *string `json:"outboundTag"`
Timestamp int64 `json:"ts"`
}
func handler(w http.ResponseWriter, r *http.Request) {
var ev XrayEvent
if err := json.NewDecoder(r.Body).Decode(&ev); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
log.Printf("Xray event: %+v\n", ev)
w.WriteHeader(http.StatusOK)
}
func main() {
http.HandleFunc("/xray/webhook", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
This handler decodes the same JSON structure constructed in webhook.go (lines 67‑81), allowing you to extract connection metadata for logging or further processing.
Summary
- Xray-core router webhooks provide asynchronous HTTP callbacks triggered by routing rule matches, implemented in
app/router/webhook.goand integrated viaapp/router/router.go. - The feature supports custom HTTP headers, deduplication intervals, and Unix domain sockets for flexible deployment scenarios.
- Webhooks execute non-blocking POST requests containing JSON payloads with source, destination, protocol, user, and tag information.
- Ideal use cases include real-time monitoring, automated security responses, audit logging, and third-party service integration.
- Configuration requires defining a
webhookobject within routing rules ininfra/conf/router.gocompatible JSON/YAML syntax.
Frequently Asked Questions
What happens if the webhook endpoint is unavailable?
Xray-core executes webhooks asynchronously and does not retry failed requests. If the HTTP POST fails or the endpoint is unreachable, the error is logged internally but the routing decision proceeds normally. For reliable delivery, implement a queuing mechanism on the receiver side or use a local Unix socket with a persistent listener.
Can I use HTTPS endpoints with custom certificates?
Yes. The WebhookNotifier uses a standard Go http.Client. For custom TLS configurations, you would need to modify the transport configuration in app/router/webhook.go or ensure the Xray-core process trusts the certificate authority through the system certificate pool.
How does deduplication work with multiple users?
The deduplication mechanism keys events by user email (specifically the email field in the connection context). When deduplication is set to a positive integer (seconds), the notifier stores a timestamp for each email and discards subsequent events from that same email until the TTL expires. This prevents flooding from high-connection-count users while still capturing distinct user activity.
Does the webhook feature impact proxy performance?
No. The webhook fires asynchronously in a separate goroutine and never blocks the main routing path in PickRoute. The HTTP POST operation occurs after the routing decision is complete, ensuring zero latency impact on connection processing. However, high event volumes may increase memory usage due to goroutine creation and JSON marshaling overhead.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →