Skip to content

Commit

Permalink
docs: add how to config egg behind a proxy (#3614)
Browse files Browse the repository at this point in the history
  • Loading branch information
dead-horse authored Apr 11, 2019
1 parent 2357fbc commit 879fe93
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/source/_data/guide_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Tutorials:
Socket.IO: /tutorials/socketio.html
Assets: /tutorials/assets.html
TypeScript: /tutorials/typescript.html
Proxy: /tutorials/proxy.html
Advanced:
Loader: /advanced/loader.html
Plugin Development: /advanced/plugin.html
Expand Down
72 changes: 72 additions & 0 deletions docs/source/en/tutorials/proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
title: Behind a Proxy
---

Generally, our services will not directly accept external requests, but will deploy the services behind the access layer, thus achieving load balancing of multiple machines and smooth distribution of services to ensure high availability.

In this scenario, we can't directly get the connection to the real user request, so we can't confirm the user's real IP, request protocol, or even the requested host. To solve this problem, the framework provides a set of configuration items by default for developers to configure to enable the application layer to obtain real user request information based on the agreement(de facto) with the access layer.

## Enable Proxy Mode

The proxy mode can be enabled by `config.proxy = true`:

```js
// config/config.default.js

exports.proxy = true;
```

Note that after this mode is enabled, the application defaults to being behind the reverse proxy. It will support the request header of the resolved protocol to obtain the real IP, protocol and host of the client. If your service is not deployed behind a reverse proxy, do not enable this configuration in case a malicious user falsifies information such as requesting IP.

### `config.ipHeaders`

When the proxy configuration is enabled, the app parses the [X-Forwarded-For](https://en.wikipedia.org/wiki/X-Forwarded-For) request header to get the real IP of the client. If your reverse proxy passes this information through other request headers, it can be configured via `config.ipHeaders`, which supports multiple headers (comma separated).

```js
// config/config.default.js

exports.ipHeaders = 'X-Real-Ip, X-Forwarded-For';
```

### `config.maxProxyCount`

The general format of the `X-Forwarded-For` field is:

```
X-Forwarded-For: client, proxy1, proxy2
```

We can use the first IP address as the real IP adderess of the request, but if a malicious user passes the `X-Forwarded-For` header in the request to spoof it after some reverse proxy, it will cause `X-Forwarded-For` to take The value obtained is inaccurate and can be used to spoof the request IP address, breaking some IP restrictions of the application layer.

```
X-Forwarded-For: fake, client, proxy1, proxy2
```

In order to avoid this problem, we can configure the number of reverse proxies through `config.maxProxyCount`, so the fake IP address passed by the user will be ignored. For example, if we deploy the application behind a unified access layer (such as Alibaba Cloud SLB, Amazon ELB), we can configure this configuration to `1` so that users cannot forge IP addresses through the `X-Forwarded-For` request header.

```js
// config/config.default.js

exports.maxProxyCount = 1;
```

### `config.protocolHeaders`

When the proxy configuration is enabled, the application will parse the [X-Forwarded-Proto] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) request header to get the client's Real access protocol. If your reverse proxy passes this information through other request headers, it can be configured via `config.protocolHeaders`, which supports multiple headers (comma separated).

```js
// config/config.default.js

exports.protocolHeaders = 'X-Real-Proto, X-Forwarded-Proto';
```

### `config.hostHeaders`

When the proxy configuration is enabled, the application still reads `host` directly to get the requested domain name. Most of the reverse proxy does not modify this value. But maybe some reverse proxy will pass the client's real access via [X-Forwarded-Host] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) The domain name can be configured via `config.hostHeaders`, which supports multiple headers (comma separated).

```js
// config/config.default.js

exports.hostHeaders = 'X-Forwarded-Host';
```


1 change: 1 addition & 0 deletions docs/source/languages/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ guide_toc:
Resource: Resource
Assets: Assets
TypeScript: TypeScript
Proxy: Behind a Proxy
1 change: 1 addition & 0 deletions docs/source/languages/zh-cn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ guide_toc:
Resource: 资源
Assets: 静态资源
TypeScript: TypeScript
Proxy: 前置代理模式
72 changes: 72 additions & 0 deletions docs/source/zh-cn/tutorials/proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
title: 前置代理模式
---

一般来说我们的服务都不会直接接受外部的请求,而会将服务部署在接入层之后,从而实现多台机器的负载均衡和服务的平滑发布,保证高可用。

在这个场景下,我们无法直接获取到真实用户请求的连接,从而无法确认用户的真实 IP,请求协议,甚至请求的域名。为了解决这个问题,框架默认提供了一系列配置项来让开发者配置,以便基于和接入层的约定(事实标准)来让应用层获取到真实的用户请求信息。

## 开启前置代理模式

通过 `config.proxy = true`,可以打开前置代理模式:

```js
// config/config.default.js

exports.proxy = true;
```

注意,开启此模式后,应用就默认自己处于反向代理之后,会支持通过解析约定的请求头来获取用户真实的 IP,协议和域名。如果你的服务未部署在反向代理之后,请不要开启此配置,以防被恶意用户伪造请求 IP 等信息。

### `config.ipHeaders`

开启 proxy 配置后,应用会解析 [X-Forwarded-For](https://en.wikipedia.org/wiki/X-Forwarded-For) 请求头来获取客户端的真实 IP。如果你的前置代理通过其他的请求头来传递该信息,可以通过 `config.ipHeaders` 来配置,这个配置项支持配置多个头(逗号分开)。

```js
// config/config.default.js

exports.ipHeaders = 'X-Real-Ip, X-Forwarded-For';
```

### `config.maxProxyCount`

`X-Forwarded-For` 等传递 IP 的头,通用的格式是:

```
X-Forwarded-For: client, proxy1, proxy2
```

我们可以拿第一个作为请求的真实 IP,但是如果有恶意用户在请求中传递了 `X-Forwarded-For` 参数来伪造其在反向代理之后,就会导致 `X-Forwarded-For` 拿到的值不准确了,可以被用来伪造请求 IP 地址,突破应用层的一些 IP 限制。

```
X-Forwarded-For: fake, client, proxy1, proxy2
```

为了避免此问题,我们可以通过 `config.maxProxyCount` 来配置前置的反向代理数量,这样在获取请求真实 IP 地址时,就会忽略掉用户多传递的伪造 IP 地址了。例如我们将应用部署在一个统一的接入层之后(例如阿里云 SLB),我们可以将此参数配置为 `1`,这样用户就无法通过 `X-Forwarded-For` 请求头来伪造 IP 地址了。

```js
// config/config.default.js

exports.maxProxyCount = 1;
```

### `config.protocolHeaders`

开启 proxy 配置后,应用会解析 [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) 请求头来获取客户端的真实访问协议。如果你的前置代理通过其他的请求头来传递该信息,可以通过 `config.protocolHeaders` 来配置,这个配置项支持配置多个头(逗号分开)。

```js
// config/config.default.js

exports.protocolHeaders = 'X-Real-Proto, X-Forwarded-Proto';
```

### `config.hostHeaders`

开启 proxy 配置后,应用仍然还是直接读取 `host` 来获取请求的域名,绝大部分反向代理并不会修改这个值。但是也许有些反向代理会通过 [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) 来传递客户端的真实访问域名,可以通过在 `config.hostHeaders` 中配置,这个配置项支持配置多个头(逗号分开)。

```js
// config/config.default.js

exports.hostHeaders = 'X-Forwarded-Host';
```


0 comments on commit 879fe93

Please sign in to comment.