aibangjuxin / knowledge

My knowledge
1 stars 0 forks source link

Nginx remoteip #146

Open aibangjuxin opened 5 months ago

aibangjuxin commented 5 months ago

要让 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 commented 5 months ago

为了确保 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 commented 5 months ago

理解到你使用的是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

故障排除

如果启用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 commented 5 months ago

在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

示例配置

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

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地址。