23 days ago
Hello Railway Support,
We run a FastAPI application with Uvicorn 0.34.0 behind Railway Public Networking. A POST endpoint requires HTTPS and a dedicated Bearer token.
Railway terminates TLS before forwarding requests to the application. The internal proxy peer IP varies between requests, so allowlisting individual IPs with FORWARDED_ALLOW_IPS is unreliable. When the proxy is not trusted, the application sees request.url.scheme == "http" and rejects the request.
We do not want to trust all IPs, guess a proxy CIDR, or rely solely on client-spoofable Host/forwarded headers. Bearer authentication must remain, but it does not prove that a request passed through the HTTPS proxy.
Could you confirm:
Is there an officially supported configuration that allows only Railway’s Public HTTPS proxy to reach the application’s listening port, blocking direct public and private-network access? If so, what are the exact settings and limitations?
Does Railway provide a verifiable proxy identity mechanism that does not depend on source IPs—for example, proxy-to-application mTLS or cryptographically signed forwarding metadata?
If neither is available, what supported configuration do you recommend for reliably enforcing HTTPS at this endpoint without trusting all proxies or adding another proxy service?
Please include the relevant documentation, whether X-Forwarded-Proto is overwritten or sanitized by the edge, and any plan or runtime requirements.
Thank you.
Pinned Solution
22 days ago
Those headers are written at the edge, so users can't spoof or overwrite those values.
The application can be reached over the private network at the port it's listening to, but it can only be reached by other services in the same network.
3 Replies
23 days ago
This thread has been opened as a bounty so the community can help solve it.
Status changed to Open Railway • 23 days ago
22 days ago
No. There isn't a CIDR range for Railway's proxies. You'd need to trust all proxies. Also, X-Forwarded-Proto is always https. (https://docs.railway.com/networking/public-networking/specs-and-limits#technical-specifications)
0x5b62656e5d
No. There isn't a CIDR range for Railway's proxies. You'd need to trust all proxies. Also, `X-Forwarded-Proto` is always `https`. (https://docs.railway.com/networking/public-networking/specs-and-limits#technical-specifications)
22 days ago
Thanks. That clarifies that there is no stable proxy CIDR and that Railway expects all proxies to be trusted.
One security point is still unclear:
If Uvicorn is configured to trust all proxies, what prevents a client from reaching the application directly and spoofing X-Forwarded-Proto: https?
Is the application listening port guaranteed to be unreachable from both the public Internet and other private-network clients except through Railway’s edge proxy?
Or does Railway’s edge sanitize/overwrite X-Forwarded-Proto in a way that makes trusting all proxies safe even if a direct connection is possible?
We reproduced locally that a direct HTTP request with a spoofed X-Forwarded-Proto: https can bypass an application-level HTTPS check when all proxies are trusted, so we want to understand what Railway guarantees at the network layer.
mkthero
Thanks. That clarifies that there is no stable proxy CIDR and that Railway expects all proxies to be trusted. One security point is still unclear: If Uvicorn is configured to trust all proxies, what prevents a client from reaching the application directly and spoofing X-Forwarded-Proto: https? Is the application listening port guaranteed to be unreachable from both the public Internet and other private-network clients except through Railway’s edge proxy? Or does Railway’s edge sanitize/overwrite X-Forwarded-Proto in a way that makes trusting all proxies safe even if a direct connection is possible? We reproduced locally that a direct HTTP request with a spoofed X-Forwarded-Proto: https can bypass an application-level HTTPS check when all proxies are trusted, so we want to understand what Railway guarantees at the network layer.
22 days ago
Those headers are written at the edge, so users can't spoof or overwrite those values.
The application can be reached over the private network at the port it's listening to, but it can only be reached by other services in the same network.
Status changed to Solved 0x5b62656e5d • 22 days ago