-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Description
Problem Description
Currently, Xray's routing rules support matching based on destination port (port), source port (sourcePort), and various other criteria, but there is no way to route traffic based on which port the server is listening on. This creates significant limitations when trying to implement port-based traffic distribution in multi-port deployment scenarios.
Current Behavior
In the current implementation:
-
port in RuleObject matches the destination port (the port the client wants to connect to, e.g., 80, 443)
-
sourcePort matches the client's source port
-
inboundTag can differentiate between different inbounds, but requires separate inbound configurations
Proposed Solution
Add a new field listenPort or serverPort to the RuleObject:
{
"routing": {
"rules": [
{
"listenPort": "25001-26000",
"outboundTag": "out-group-1"
},
{
"listenPort": "26001-27000",
"outboundTag": "out-group-2"
}
]
}
}
This would match against the port that the server accepted the connection on, not the destination port in the traffic.
Why This Is Important
- Scalability: Allows port-based routing without creating hundreds of duplicate inbounds
- Simplicity: Maintains single user database instead of duplicating across inbounds
- Compatibility: Works well with frontend proxies (HAProxy, Nginx) that use PROXY protocol
- Real-world need: Many proxy services use port numbers to differentiate service levels or routing paths
Alternative Considerations
We've explored workarounds like:
- Using source IP manipulation (breaks client IP preservation)
- Creating multiple inbounds (configuration explosion)
- Using user-based routing (not applicable for protocols without user identification)
None of these solutions are practical for large-scale deployments.
Implementation Notes
The listening port information should already be available in the connection context, as it's needed for the initial socket accept. This feature would simply expose it to the routing engine.
Backward Compatibility
This would be a new optional field, so existing configurations would continue to work without modification.