reverse-proxy
reverse-proxy copied to clipboard
Support port routes
What should we add or change to make your life better?
Support port routes
Why is this important to you?
Host routing is currently supported, but the host may change due to the pre agent. The only thing you can know is the port currently listening
Can you give some examples of the expected server configuration, request fields, and the YARP configuration you'd like to see?
@Tratcher
"Kestrel": {
"Endpoints": {
"http1": {
"Url": "http://*:13500",
"Protocols": "Http1"
},
"http2": {
"Url": "http://*:51001",
"Protocols": "Http2"
}
}
},
"ReverseProxy": {
"Routes": {
"grpc": {
"ClusterId": "grpccluster",
"Match": {
"Ports": [ 51001 ] or "Port": 51001
}
},
"http": {
"ClusterId": "httpcluster",
"Match": {
"Ports": [13500] or "Port": 13500
}
}
},
"Clusters": {
"grpccluster": {
"HttpRequest": {
"Version": "2",
"VersionPolicy": "RequestVersionExact"
},
"Destinations": {
"50001": {
"Address": "http://grpccluster:30923"
}
}
},
"httpcluster": {
"Destinations": {
"30913": {
"Address": "http://httpcluster:30913"
}
}
}
}
}
Seems reasonable.
There are a few ways to go about this.
- You might be able to approximate this behavior using the Host header, it often contains the port.
"Hosts" : [ "*:51001" ],. - This can be implemented in your project today using AspNetCore's routing extensibility just like how YARP added support for header based routing. https://github.com/microsoft/reverse-proxy/blob/1ad89df30ac6d58fcb3e1f3231d81fa6d100bb98/src/ReverseProxy/Routing/HeaderMatcherPolicy.cs. You can add the information in config via route metadata and then add it to routes with ConfigureEndpoints. https://github.com/microsoft/reverse-proxy/blob/1ad89df30ac6d58fcb3e1f3231d81fa6d100bb98/src/ReverseProxy/Routing/ReverseProxyConventionBuilder.cs#L57
- It can be implemented in YARP
- It can be implemented in AspNetCore
Long term we'd like to move most routing features to AspNetCore. We've added some in YARP to support older framework versions and to experiment.
https://github.com/dotnet/aspnetcore/issues/46057
Being able to match on ports would be really helpful. In my use-case I want to differentiate between a port providing the proxy services and a port for internal purposes like prometheus, health endpoints, management and so on. Using the existing host header based matching, you can still request proxy endpoints from the internal purposes port and the other way around just by messing with the port stated in the Hosts header which is not good. For security reasons I want to be able to cleanly separate what is offered on what port.
@Tratcher with the upstream issue being closed is there still a chance of this happening?
The linked issue said that since the port is part of the host header you can use that:
{
"ReverseProxy": {
"Routes": {
"route1" : {
"ClusterId": "cluster1",
"Match": {
"Hosts" : [ "*:80", "*:8080"],
},
}
},
// ...
}
}
The linked issue said that since the port is part of the host header you can use that:
{ "ReverseProxy": { "Routes": { "route1" : { "ClusterId": "cluster1", "Match": { "Hosts" : [ "*:80", "*:8080"], }, } }, // ... } }
But that's the problem. The host header ist whatever the client sets it to. So if I setup Kestrel to listen on 80 and 9000 and I set a host match to only *:9000 for a route in YARP I can still connect to port 80 and just send "whatever:9000" in the Host header and it will match the route for *:9000 and respond.
It's easy enough to make a middleware that validates the host header matches the local port.
For me I work around this using an endpoint filter checking against localport. I still think there should be a integrated way to do this right because many people will use the "obvious" but unsafe solution.
Proposing host matching for port restrictions in ASP.NET core seems to be a widespread pattern. After stumbling over it again in the Microsoft documentation on health checks today I opened a issue there. Hopefully the documentation can at least be clarified (https://github.com/dotnet/AspNetCore.Docs/issues/29399)