我正在尝试使用Nginx作为TCP守护进程的代理,以使Nginx成为SSL / TLS前端以及负载控制。
我的后端应用程序需要真实的客户端IP,这是一个问题。
stream {
server {
listen 3333;
proxy_pass 127.0.0.1:2222;
}
}
Run Code Online (Sandbox Code Playgroud)
我在文档中找到了一种解决方案:
proxy_bind $remote_addr transparent;
Run Code Online (Sandbox Code Playgroud)
但这太复杂了:
“为了使该参数起作用,必须以超级用户特权运行nginx worker进程,并配置内核路由表以拦截来自代理服务器的网络流量。”
还有其他方法可以将$ remote_addr传递到后端吗?
我尝试使用sub_filter修改客户端消息正文,发送HTTP标头等。但是,所有这些都只能在http上下文中使用,不幸的是,不能在流中使用。
据我所知,只有两种解决方案:proxy_bind
和proxy_protocol
。
正如您从文档中引用的那样,工作流程将需要超级用户权限。明显地。这不是最佳实践。此外,它可能会导致远程客户端出现连接问题。
假设 Nginx 以nginx
用户身份运行,运行此命令为其授予权限。
usermod -aG sudo nginx
Run Code Online (Sandbox Code Playgroud)
该解决方案要求上游目的地(例如后端应用程序)接受PROXY协议。
stream {
server {
listen 3333;
proxy_pass 127.0.0.1:2222;
proxy_protocol on;
}
}
Run Code Online (Sandbox Code Playgroud)
上述解决方案假设 Nginx 服务器是网络的入口点。如果有边缘设备(例如负载均衡器),则很可能正在更改源 IP。在这种情况下,您需要在边缘设备上启用代理协议proxy_protocol
并在server
块中启用侦听器。我还没有测试过,但类似的东西应该有效。
stream {
server {
listen 3333 proxy_protocol;
proxy_pass 127.0.0.1:2222;
proxy_protocol on;
set_real_ip_from $proxy_protocol_addr;
}
}
Run Code Online (Sandbox Code Playgroud)
我的设置:
我的要求:在 access.log 中拥有真实的客户端 IP(而不是来自流模块的 127.0.0.1)并且也用于地理封锁
我的解决方案:
对于地理封锁,您还必须使用 proxy_protocol_addr,但为了简短起见,我将省略此处的描述。
nginx.conf:
...
stream {
upstream ssh {
server 127.0.0.1:2222;
}
upstream https {
server 127.0.0.1:444;
}
map $ssl_preread_protocol $upstream {
default ssh;
"TLSv1.2" https;
"TLSv1.3" https;
"TLSv1.1" https;
"TLSv1.0" https;
}
server {
listen 443;
proxy_pass $upstream;
proxy_protocol on;
ssl_preread on;
}
server {
listen 2222 proxy_protocol;
proxy_pass 192.168.2.76:22;
}
}
http {
log_format main '$proxy_protocol_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
...
server {
listen 444 ssl proxy_protocol;
...
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6238 次 |
最近记录: |