-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ConnectionInfo::realip_remote_addr()
may or may not contain a port number which makes it difficult to handle robustly
#2528
Milestone
Comments
5 tasks
First of all, thanks for the excellent write up 👍🏻 Feels to me that having the port is never useful anyway. The PR to fix this just removes it in the peer address case. |
mpalmer
added a commit
to mpalmer/actix-web
that referenced
this issue
Apr 26, 2024
This is something of a followup to actix#2528, which asked for port information to not be included in when it was taken from the local socket. The header's element may optionally contain port information (https://datatracker.ietf.org/doc/html/rfc7239#section-6). However, as I understand it, is *supposed* to only contain an IP address, without port (per actix#2528). This PR corrects that discrepancy, making it easier to parse the result of this method in application code. There should not be any compatibility concerns, as anyone parsing the output of would already need to handle both port and portless cases anyway.
5 tasks
mpalmer
added a commit
to mpalmer/actix-web
that referenced
this issue
Apr 26, 2024
This is something of a followup to actix#2528, which asked for port information to not be included in when it was taken from the local socket. The header's element may optionally contain port information (https://datatracker.ietf.org/doc/html/rfc7239#section-6). However, as I understand it, is *supposed* to only contain an IP address, without port (per actix#2528). This PR corrects that discrepancy, making it easier to parse the result of this method in application code. There should not be any compatibility concerns, as anyone parsing the output of would already need to handle both port and portless cases anyway.
mpalmer
added a commit
to mpalmer/actix-web
that referenced
this issue
Apr 26, 2024
This is something of a followup to actix#2528, which asked for port information to not be included in when it was taken from the local socket. The header's element may optionally contain port information (https://datatracker.ietf.org/doc/html/rfc7239#section-6). However, as I understand it, is *supposed* to only contain an IP address, without port (per actix#2528). This PR corrects that discrepancy, making it easier to parse the result of this method in application code. There should not be any compatibility concerns, as anyone parsing the output of would already need to handle both port and portless cases anyway.
mpalmer
added a commit
to mpalmer/actix-web
that referenced
this issue
Apr 26, 2024
This is something of a followup to actix#2528, which asked for port information to not be included in when it was taken from the local socket. The header's element may optionally contain port information (https://datatracker.ietf.org/doc/html/rfc7239#section-6). However, as I understand it, is *supposed* to only contain an IP address, without port (per actix#2528). This PR corrects that discrepancy, making it easier to parse the result of this method in application code. There should not be any compatibility concerns, as anyone parsing the output of would already need to handle both port and portless cases anyway.
github-merge-queue bot
pushed a commit
that referenced
this issue
Jun 9, 2024
* Strip non-address characters from Forwarded for= This is something of a followup to #2528, which asked for port information to not be included in when it was taken from the local socket. The header's element may optionally contain port information (https://datatracker.ietf.org/doc/html/rfc7239#section-6). However, as I understand it, is *supposed* to only contain an IP address, without port (per #2528). This PR corrects that discrepancy, making it easier to parse the result of this method in application code. There should not be any compatibility concerns, as anyone parsing the output of would already need to handle both port and portless cases anyway. * Update CHANGES.md --------- Co-authored-by: Rob Ede <robjtede@icloud.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Expected Behavior
The expected behavior is for
ConnectionInfo::realip_remote_addr()
to return a consistently formatted address, either with or without a port number. Preferably without as appending one when theX-Forwarded-For
header is supplied would be incorrect (as the port number of the peer will not be the same port as the true peer if the request is being forwarded via a proxy, so copying the port number over is misleading).Current Behavior
If there is no
Forwarded
orX-Forwarded-For
header,.realip_remote_addr()
returns the same value as.remote_addr()
which is a socket address containing both an IP address and a port number.However, if one of those headers is present then
realip_remote_addr()
will return just a bare IP address.This makes it very difficult to parse and consume this value because
IpAddr::from_str()
will reject it in the former case andSocketAddr::from_str()
will reject it in the latter case, so one is forced to attempt both.Of course, since this value is set by the client and potentially untrustworthy (as the docs make very clear), then it may not be any kind of address at all. However, the issue here is that even when it's valid, it's still unnecessarily difficult to work with.
Possible Solution
Instead of directly forwarding to
.remote_addr()
, since the latter is set usingSocketAddr::to_string()
anyway,realip_remote_addr
should default tosocket_addr.ip().to_string()
.This shouldn't break any existing usages that are correctly implemented as any attempt to parse this string as either a socket address or IP address without attempting both would have been error-prone to begin with.
This does have the downside of an extra, semi-redundant string allocation. As an optimization, the value stored internally could be an enum that's either a separately allocated
String
or aRange
that can be used to slice theremote_addr()
string to just the IP address segment. I'm not certain this would be necessary, though.Steps to Reproduce (for bugs)
ConnectionInfo::realip_remote_addr()
as aSocketAddr
:X-Forwarded-For: <any IP address>
to the request.Context
When using the API of Circle, a payment provider, mutating requests that touch real money require passing a
metadata
object with information that can be used to find the user that originated the request in case of an audit: https://developers.circle.com/reference#payments-payments-createThis includes the user's IP address.
When the Actix-web application is deployed as part of a Kubernetes cluster in Google Cloud, and configured with an external load balancer, the
.peer_addr()
of the request will be that of the load balancer itself in Gcloud, so this cannot be used. Gcloud will append the IP address that originated to the request to theX-Forwarded-For
header, creating it if it does not exist: https://cloud.google.com/load-balancing/docs/https#x-forwarded-for_headerThus, the
.realip_remote_addr()
will be a socket address when testing the application locally, but a bare IP address when deployed. Ideally it would just always be an IP address for consistency and ease of handling.Your Environment
rustc -V
): 1.56.04.0.0-beta.8
(looking at the code, the behavior is identical on-beta.15
)The text was updated successfully, but these errors were encountered: