apache / apache/shenyu

[BUG] ForwardedRemoteAddressResolver ignores single X-Forwarded-For values

Open Beginner friendly
#6,503 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
8.8k
Forks
3.1k
Avg merge
7d 1h
Merged PRs (30d)
85

Description

### Search before asking

- [x] I had searched in the [issues](https://github.com/apache/shenyu/issues) and found no similar issues.

### Apache ShenYu Component

shenyu-web

### What happened

`ForwardedRemoteAddressResolver` is the default `RemoteAddressResolver` bean in the gateway starter:

```java
@Bean
@ConditionalOnMissingBean(RemoteAddressResolver.class)
public RemoteAddressResolver remoteAddressResolver() {
return new ForwardedRemoteAddressResolver(1);
}
```

It is used by `HostAddressUtils.acquireHost/acquireIp(...)`, including selector/rule host/ip condition data and logging client IP collection.

However, `extractXForwardedValues(...)` discards a single non-empty `X-Forwarded-For` value:

```java
List values = Arrays.asList(xForwardedValues.get(0).split(", "));
if (values.size() == 1 && StringUtils.isNotEmpty(values.get(0))) {
return Collections.emptyList();
}
return values;
```

For the common header:

```text
X-Forwarded-For: 203.0.113.10
```

`values.size()` is `1` and the value is non-empty, so the resolver returns an empty list and falls back to the TCP remote address instead of using `203.0.113.10`.

The parser also splits only on `", "`, so a valid comma-separated header without a space, such as `203.0.113.10,198.51.100.1`, is treated as one non-empty value and is also ignored.

### Expected behavior

A single non-empty `X-Forwarded-For` value should be accepted. Comma-separated values should be split independent of optional whitespace around the comma, trimmed, and empty values should be ignored.

For example, with the default `ForwardedRemoteAddressResolver(1)`, the resolved address should come from the right trusted index of the `X-Forwarded-For` chain instead of falling back whenever the header contains only one value.

### How to reproduce

1. Start the gateway with the default `RemoteAddressResolver` bean.
2. Send a request with:

```text
X-Forwarded-For: 203.0.113.10
```

3. Use a selector/rule condition that depends on client IP, or inspect logging plugin `clientIp`.
4. The gateway uses `exchange.getRequest().getRemoteAddress()` instead of `203.0.113.10` because `ForwardedRemoteAddressResolver.extractXForwardedValues(...)` returns an empty list for the single non-empty header value.

### Debug logs

_No response_

### Environment

Current `master` branch.

### Are you willing to submit a PR?

- [ ] Yes I am willing to submit a PR!

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with ForwardedRemoteAddressResolver.extractXForwardedValues(...) and trace its use through HostAddressUtils.acquireHost/acquireIp(...). Done means single values are retained, comma-separated values are split despite optional whitespace, empty values are ignored, and the trusted index resolves the forwarded address instead of falling back to the TCP address.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.