在后端 JAVA 通过以下代码

    1. private String getRemoteHost(HttpServletRequest request) {
    2. // 查看请求头中的所有信息
    3. final Enumeration<String> headerNames = request.getHeaderNames();
    4. while (headerNames.hasMoreElements()) {
    5. final String nextName = headerNames.nextElement();
    6. System.out.println(nextName + "=" + request.getHeader(nextName));
    7. }
    8. // 需要在 nginx 代理商设置 proxy_set_header REMOTE-HOST $remote_addr;
    9. final String header = request.getHeader("remote-host");
    10. if (header != null) {
    11. return header;
    12. }
    13. return request.getRemoteHost();
    14. }

    nginx 代理配置如下

    1. location ^~ /api/ {
    2. rewrite /api/(.*) /$1 break;
    3. proxy_pass http://host-api;
    4. client_max_body_size 500M;
    5. proxy_set_header Host $host;
    6. proxy_set_header REMOTE-HOST $remote_addr;
    7. proxy_set_header X-Real-IP $remote_addr:$remote_port;
    8. proxy_set_header X-Forwarded-Host $http_host;
    9. proxy_set_header X-Forwarded-Proto $scheme;
    10. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    11. }

    在上述配置中,各种配置都加了,但是获取到的始终是 docker 容器的 IP,查看 nginx 访问日志

    1. 192.168.0.29 - - [06/Jul/2021:09:55:40 +0000] "POST /api/account/search HTTP/1.0" 200 4794 "https://mrcode.com/auth/account" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" "110.110.106.50"

    如上所示,最前面的 IP 就是就是 $remote_addr ,的确是容器的 IP,无论咋折腾都没有效果,改动不了这个,然后看了下 nginx 日志格式

    1. #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    2. # '$status $body_bytes_sent "$http_referer" '
    3. # '"$http_user_agent" "$http_x_forwarded_for"';

    最后一个字段 $http_x_forwarded_for 是日志中看到的 IP (日志最后)的含义,这个 IP 是真实的客户端 IP,修改下代理配置

    1. # proxy_set_header REMOTE-HOST $remote_addr;
    2. # 修改成最后一个字段
    3. proxy_set_header REMOTE-HOST $http_x_forwarded_for;

    总结:不一定要放到 remote-host 上面,只要拿到真实 IP,可以放到任意的一个 header 上面,那么后端的 java 应用就不需要做额外的代码处理了。

    那么为什么真实 IP 会出现在 http_x_forwarded_for 头中呢?这个就要看看一个客户端请求到达你服务器经过了哪些代理转发?我遇到这个就是前面还有一个域名转发的服务器