## Description
Sometimes there can be more than one proxy between the client and the
server. In such cases, the `x-forwarded-for` header is appended with the
full path of IPs, ostensibly with the client IP being the first. For
this reason, we need to fix the parsing to accommodate a list of IPs.
However, we additionally have the problem of knowing which IP in the
list is the client IP. We cannot assume the first IP in the list is the
client IP, as a malicious client could attempt to spoof by writing a
junk value in `x-forwarded-for` in the request, to which the internal
LBs would append. There are two possible solutions to this:
a) define a custom header and configure our gcs LBS to write to this and
overwrite any existing value for that header.
b) add configuration such that the node operator defines the number of
intermediate load balancers (`num_hops`) it runs.
In such a case, for a `num_hops = N`, the client IP should always be the
`N`th **to last**.
To illustrate (note that for N proxies, only the IP addresses of proxy
1, ..., N-1 will be contained in the header, as proxy N
is directly connected to the server and does not write its own IP):
```
[
<whatever the client may have written>,
<actual client IP>, <-- we want this
<1>,
...,
<N - 1>
]
```
The first solution would require extra configuration on their infra by
the node operator, and would be specific to gcs (we'd have to confirm
that something similar is supported in other cloud hosting services). So
this PR implements option (2).
## Test plan
How did you test the new or updated feature?
---
## Release notes
Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.
For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.
- [ ] Protocol:
- [ ] Nodes (Validators and Full nodes):
- [ ] Indexer:
- [ ] JSON-RPC:
- [ ] GraphQL:
- [ ] CLI:
- [ ] Rust SDK: