在envoy作为前端代理时,用户ip的获取很重要,一般获取ip的方式。都是通过Header中的 X-Forward-For
、 X-Real-IP
或 Remote addr
等属性获取,但是如果确保Envoy可以获取到的ip是真实的用户ip呢?本篇继续解密!
概念说明
-
Remote Address
是nginx与客户端进行TCP连接过程中,获得的客户端真实地址。Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求。
一般情况下,在Envoy作为最外层代理时,此IP为真实的IP客户端IP -
X-Real-IP
是一个自定义头。X-Real-Ip 通常被 HTTP 代理用来表示与它产生 TCP 连接的设备 IP,这个设备可能是其他代理,也可能是真正的请求端。X-Real-Ip 目前并不属于任何标准,代理和 Web 应用之间可以约定用任何自定义头来传递这个信息。 -
X-Forwarded-For
X-Forwarded-For 是一个扩展头。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP,现在已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。通常,X-Forwarded-For可被伪造,并且使用CDN会被重写
Envoy中如何获取真实IP
在Envoy中,涉及到客户端IP的配置如下:
use_remote_address: 默认值false,设置为true,使用客户端连接的真实远程地址,false是使用x-forwarded-for
skip_xff_append: 设置为true,则不会将远程地址附加到x-forwarded-for中
request_headers_to_add 添加请求头
request_headers_to_remove 删除一个请求头
实验环境配置准备
admin:
access_log_path: /dev/null
address:
socket_address: {
address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
- name: listener_80
address:
socket_address: {
address: 0.0.0.0, port_value: 80 }
access_log:
filter_chains:
- filters:
- name: envoy_http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
access_log:
- name: envoy.listener.accesslog
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: /var/log/envoy.log
log_format:
text_format: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\