Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nginx remoteip #146

Open
aibangjuxin opened this issue Jun 11, 2024 · 3 comments
Open

Nginx remoteip #146

aibangjuxin opened this issue Jun 11, 2024 · 3 comments

Comments

@aibangjuxin
Copy link
Owner

要让 Kong Gateway 获取到客户端的真实 IP 地址,你需要在 Kong 的配置中指定获取客户端 IP 的方式。Kong 支持从不同的 HTTP 头中获取客户端 IP,包括 X-Forwarded-ForX-Real-IP

以下是一些建议:

  1. 在 Kong 中配置获取 IP 的头部

在 Kong 的配置文件中,你可以指定从哪个 HTTP 头中获取客户端 IP。例如,如果你想从 X-Real-IP 头中获取 IP,可以这样配置:

nginx_http_upstream = {
  ...
  headers = {
    ["X-Real-IP"] = "$remote_addr"
  }
}
  1. 使用 Nginx L4 转发 X-Real-IP 头部

由于 Nginx L7 已经在 X-Real-IP 头中设置了客户端 IP,你可以让 Nginx L4 转发这个头部到 Kong Gateway。在 Nginx L4 的配置中添加:

proxy_set_header X-Real-IP $http_x_real_ip;

这样 Kong Gateway 就可以从 X-Real-IP 头中获取客户端真实 IP 了。

  1. 使用 Nginx L4 转发 X-Forwarded-For 头部

如果你更倾向于使用 X-Forwarded-For 头,可以在 Nginx L4 中这样配置:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

然后在 Kong 中配置从 X-Forwarded-For 头获取 IP:

nginx_http_upstream = {
  ...
  headers = {
    ["X-Forwarded-For"] = "$proxy_add_x_forwarded_for"
  }
}

通过上述配置,Kong Gateway 应该可以获取到客户端的真实出口 IP 地址了。记得在做任何更改后重新加载 Nginx 和 Kong 的配置。

@aibangjuxin
Copy link
Owner Author

为了确保 Kong Gateway 能获取客户端的出口 IP 地址,您需要确保在整个请求中转途经的每一层代理都正确转发这个IP地址。

在您提供的配置中,L7 Nginx 已经设置了 X-Real-IP 和 X-Forwarded-For 头信息来转发原始客户端IP。现在关键是确保L4 Nginx 能正确地将这些信息再次转发给 Kong Gateway。

L4 Nginx的配置需要确保它不会覆盖 X-Real-IP 和 X-Forwarded-For 头信息。这通常意味着在相关的 stream 或 server 配置块中要设置相关头信息的转发,不过要注意的是,在处理TCP/SSL流量时,代理不会直接访问到HTTP头信息。

如果您的L4 Nginx是按照四层(传输层)来转发SSL/TCP连接,而没有解包HTTP层。那么L4级别的Nginx将无法修改或添加任何HTTP头部信息。在这种情况下,您需要确保L7 Nginx直接与Kong Gateway通信,或者您的L4 Nginx需要能够解包TCP流以编辑HTTP请求(这将涉及到SSL的终止和创建新的SSL连接)。

一般而言,以下两点是确保Kong Gateway获取客户端出口IP地址的关键所在:

  1. 配置L4 Nginx以支持SSL透明代理(如果L4 Nginx是负责SSL的):
    配置L4 Nginx以使其能够处理SSL透明代理或者SSL中继。这通常意味着安装具备此功能的Nginx模块,使其能够进行SSL解密和重新加密,并正确转发HTTP头信息。

  2. 确保Kong正确解析X-Forwarded-For头部
    在Kong中,您可以配置其使用X-Forwarded-For来获取原始客户端的客户端IP。在Kong配置中确保已经启用了real_ip_recursive并设置了trusted_ips,使Kong能相信来自于你的Nginx代理的头信息。以下是一个配置示例:

yaml
real_ip_header: X-Forwarded-For;
real_ip_recursive: on;
trusted_ips: 0.0.0.0/0, ::/0; # 示例配置,这里需要添加真实的Nginx代理的IP地址。

确保L4 Nginx保留了从L7 Nginx传入的X-Forwarded-For头部。如果需要在L4进行SSL处理,就要确保SSL覆盖过程中头部信息不得丢失。或者更简单的方法是跳过L4(如果没有必须的原因让它介入HTTP头的处理),直接从L7将流量传递到Kong Gateway。如果环境和配置允许,这将减少复杂性和可能出现的错误。在决定最佳做法之前,请细致审查您的安全和架构需求。

@aibangjuxin
Copy link
Owner Author

理解到你使用的是L4级别的Nginx,它只处理TCP/SSL连接,而不会解包HTTP层内容,所以L4 Nginx不能直接修改或添加HTTP头部信息。在这种情况下,要使Kong Gateway获取客户端的真实IP地址,必须通过Nginx的proxy_protocol来传递原始客户端IP地址。这里是详细的配置过程:

1. 配置L7 Nginx

L7 Nginx仍然负责处理HTTP请求,并将原始客户端IP传递到L4 Nginx。这部分配置不会修改:

http {
    server {
        listen 80;

        location /apiname/v1 {
            if ($host !~* aibangjuxin$ ) {
                return 444;
            }

            if ($content_type ~ (multipart/form-data|text/plain)) {
                return 405;
            }

            rewrite ^/apiname/v1(.*)$ $1 break;
            proxy_pass https://10.10.15.1:8081;
            proxy_set_header Host dev-api.cn.aibang;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

2. 配置L4 Nginx

在L4 Nginx上启用proxy_protocol,以便将客户端的原始IP地址传递给下游的Kong Gateway:

stream {
    server {
        listen 8081 proxy_protocol;  # 启用 proxy_protocol

        proxy_pass 192.168.0.5:8443;  # 假设 Kong Gateway 运行在 192.168.0.5:8443
        proxy_protocol on;  # 启用 proxy_protocol 支持
    }
}

3. 配置Kong Gateway

Kong Gateway必须配置为接受并解析来自proxy_protocol的信息,以便获取客户端的真实IP地址。Kong Gateway的配置需要以下步骤:

配置Kong的Nginx模板

如果Kong使用的是Nginx作为前端,那么需要配置Nginx模板以启用proxy_protocol

server {
    listen 8443 ssl proxy_protocol;  # 启用 proxy_protocol

    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;

    location / {
        proxy_pass http://upstream_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $proxy_protocol_addr;  # 使用 proxy_protocol_addr 获取真实的客户端IP
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

更新Kong的配置文件

确保Kong的配置文件接受并解析proxy_protocol头文件:

nginx_http_real_ip_header: "proxy_protocol"
nginx_http_real_ip_recursive: "on"
trusted_ips:
  - 0.0.0.0/0

完整流程图

以下是更新后的流程图,展示了从L7 Nginx到Kong Gateway的请求流动过程:

graph TD
    A(Client) -->|HTTPS| B(Nginx_L7)
    B(Nginx_L7) -->|proxy_pass + X-Forwarded-For| C(Nginx_L4)
    C(Nginx_L4) -->|proxy_pass + proxy_protocol| D(Kong_GW)
    D(Kong_GW) --> E(Upstream_Service)

    subgraph Network
        B
        C
        D
    end
Loading

故障排除

如果启用proxy_protocol后遇到502错误,可能的原因及解决方法包括:

  1. 确认Kong Gateway的Nginx配置

    • 确保Kong Gateway的Nginx配置文件正确启用了proxy_protocol
    • 确认SSL证书和私钥路径正确。
  2. 检查Kong Gateway日志

    • 查看Kong Gateway的错误日志,找出具体的错误原因。
  3. 确保端口和协议匹配

    • 确认所有层之间的端口和协议(HTTP/HTTPS)匹配。
  4. 同步配置文件

    • 确保所有Nginx配置文件已正确更新,并重新加载Nginx服务。

通过以上配置和故障排除步骤,可以确保Kong Gateway能够获取并使用客户端的真实IP地址。

@aibangjuxin
Copy link
Owner Author

在L4层Nginx中启用proxy_protocol后,出现502错误并且报104: connection reset by peer while SSL handshaking to upstream,通常是因为上游服务器没有正确配置为接收proxy_protocol,或者配置不完全。让我们详细解释并正确配置这些步骤,确保proxy_protocol在各层之间正确传递和解析。

配置步骤

1. L7 Nginx 配置

首先,L7 Nginx负责处理HTTP请求并将其转发到L4 Nginx,同时传递原始客户端IP地址:

http {
    server {
        listen 80;

        location /apiname/v1 {
            if ($host !~* aibangjuxin$ ) {
                return 444;
            }

            if ($content_type ~ (multipart/form-data|text/plain)) {
                return 405;
            }

            rewrite ^/apiname/v1(.*)$ $1 break;
            proxy_pass https://10.10.15.1:8081;
            proxy_set_header Host dev-api.cn.aibang;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

2. L4 Nginx 配置

L4 Nginx负责接收从L7 Nginx传来的请求,并使用proxy_protocol将其转发到Kong Gateway:

stream {
    server {
        listen 8081 proxy_protocol;

        proxy_pass 192.168.0.5:8443;  # 假设 Kong Gateway 运行在 192.168.0.5:8443
        proxy_protocol on;
    }
}

3. Kong Gateway 配置

确保Kong Gateway配置正确接收和解析proxy_protocol头信息。假设Kong Gateway使用Nginx作为前端:

Kong 的 Nginx 模板配置:

在Kong的Nginx模板配置文件中,启用proxy_protocol

server {
    listen 8443 ssl proxy_protocol;  # 启用 proxy_protocol

    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;

    location / {
        proxy_pass http://upstream_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $proxy_protocol_addr;  # 使用 proxy_protocol_addr 获取真实的客户端IP
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Kong 配置文件:

确保在Kong的配置文件中设置了正确的头信息解析:

nginx_http_real_ip_header: "proxy_protocol"
nginx_http_real_ip_recursive: "on"
trusted_ips:
  - 0.0.0.0/0

故障排除

  1. 确认上游服务器配置:

    确认Kong Gateway的Nginx配置正确接受proxy_protocol。特别是listen指令中的proxy_protocol

    listen 8443 ssl proxy_protocol;
  2. 检查SSL配置:

    确保SSL证书和私钥路径正确,并且SSL配置没有问题。

  3. 查看日志文件:

    检查Nginx和Kong Gateway的错误日志,以获取更详细的错误信息。

  4. 协议和端口匹配:

    确认所有层之间的协议和端口设置一致。

整体流程图

以下是更新后的流程图,展示从L7 Nginx到Kong Gateway的请求流动过程:

graph TD
    A(Client) -->|HTTPS| B(Nginx_L7)
    B(Nginx_L7) -->|proxy_pass + X-Forwarded-For| C(Nginx_L4)
    C(Nginx_L4) -->|proxy_pass + proxy_protocol| D(Kong_GW)
    D(Kong_GW) --> E(Upstream_Service)

    subgraph Network
        B
        C
        D
    end
Loading

示例配置

假设你有一个基本的设置,以下是各个部分的示例配置:

L7 Nginx:

http {
    server {
        listen 80;

        location /apiname/v1 {
            if ($host !~* aibangjuxin$ ) {
                return 444;
            }

            if ($content_type ~ (multipart/form-data|text/plain)) {
                return 405;
            }

            rewrite ^/apiname/v1(.*)$ $1 break;
            proxy_pass https://10.10.15.1:8081;
            proxy_set_header Host dev-api.cn.aibang;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

L4 Nginx:

stream {
    server {
        listen 8081 proxy_protocol;

        proxy_pass 192.168.0.5:8443;
        proxy_protocol on;
    }
}

Kong Gateway:

server {
    listen 8443 ssl proxy_protocol;

    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;

    location / {
        proxy_pass http://upstream_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $proxy_protocol_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Kong 配置文件:

nginx_http_real_ip_header: "proxy_protocol"
nginx_http_real_ip_recursive: "on"
trusted_ips:
  - 0.0.0.0/0

通过确保各层之间的proxy_protocol配置正确,应该能够解决502错误并让Kong Gateway获取到客户端的真实IP地址。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant