使用 nginx 将附加标头发送到 FastCGI 后端

问题描述 投票:0回答:5

我将 nginx 与多个 fastcgi 后端(php-cgi、mod-mono-fastcgi4)一起使用。现在我需要向fastcgi后端发送一个额外的http标头,基本上与使用nginx作为反向代理时的proxy_set_header相同。但根据我的发现,nginx中没有fastcgi_set_header这样的东西。

有人知道如何做到这一点吗?我不想使用额外的 nginx 模块,因为解决方案必须能够轻松部署在各种客户系统上。

nginx http-headers fastcgi
5个回答
17
投票

我快速浏览了手册,我认为您会发现最接近的是传递 fastcgi 参数:

请求标头以参数的形式传输到FastCGI服务器。在从 FastCGI 服务器运行的应用程序和脚本中,这些参数通常可以以环境变量的形式访问。例如,标头“User-agent”作为参数 HTTP_USER_AGENT 进行传输。除了 HTTP 请求的标头之外,还可以借助指令 fastcgi_param 传输任意参数。

http://wiki.nginx.org/HttpFcgiModule#Parameters.2C_transferred_to_FastCGI-server.

fastcgi_param

语法:fastcgi_param参数值

http://wiki.nginx.org/HttpFcgiModule#fastcgi_param


11
投票

上述 nginx wiki 文章的 URL 已损坏。

nginx 通过前缀为 $http_ 的变量公开请求标头值,因此可以通过 $http_user_agent 获得 HTTP_USER_AGENT 的请求标头。

同样,名为 CHICKEN_SOUP 的请求标头可以通过 $http_chicken_soup 获得。

下面的示例展示了如何将 Authorization HTTP 请求标头传递给在 php-fpm(PHP FastCGI 进程管理器)下运行的 PHP 脚本。

location ~ \.php$ {
    fastcgi_pass   unix:/path/to/socket;
    fastcgi_index  index.php;
    fastcgi_param  HTTP_AUTHORIZATION $http_authorization;
    ... other settings
}

0
投票

我认为Zoot的答案很好,并基于它,我想为任何它能帮助的人走得更远。为了涵盖这两种情况,“上游反向代理”和“独立”,所以我将发布我为完成任务以将正确的标头转发到“最后一个”服务器所做的工作,以便应用程序可以拥有必要的信息(通过

SSL_*
标头)来分配正确的用户标识,而不是只允许通过而不管身份。这些示例涵盖 php 和 fastcgi,但我确信如果需要,它们可以轻松适应其他堆栈:

首先,在“独立”服务器(即中间没有反向代理)中执行验证:

server {
    listen 443 ssl http2;

...

    ssl_certificate /etc/XXX.pem;
    ssl_certificate_key /etc/XXX.key;
    ssl_client_certificate /etc/XXX/CA.pem;
    ssl_verify_client optional; # Or whatever

    location ~ ^/index\.php(/|$) {
        fastcgi_pass php;
        # The provided fastcgi script by nginx
        include snippets/fastcgi-php.conf;

        # A custom snippet to manage headers
        include snippets/sslclient-fastcgi.conf;

    }
}

定制

sslclient-fastcgi.conf

# Custom snippet to be used in a standalone server that performs verification
# by using a x509 client certificate. The nginx variables are transformed into
# SSL_* headers (trying to mimic Apache documentation with StdEnvVars and ExportCertData)
# and passes the result to an upstream using cgi to process headers.

fastcgi_param SSL_CIPHER $ssl_cipher;
fastcgi_param SSL_CLIENT_CERT $ssl_client_raw_cert;
fastcgi_param SSL_CLIENT_I_DN $ssl_client_i_dn;
fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
fastcgi_param SSL_CLIENT_V_END $ssl_client_v_end;
fastcgi_param SSL_CLIENT_V_REMAIN $ssl_client_v_remain;
fastcgi_param SSL_CLIENT_V_START $ssl_client_v_start;
fastcgi_param SSL_CLIENT_VERIFY $ssl_client_verify; # “SUCCESS”, “FAILED:reason”, and “NONE”
fastcgi_param SSL_PROTOCOL $ssl_protocol;
fastcgi_param SSL_SERVER_S_DN $ssl_server_name;

这样,应用程序只需读取正确的

SSL_*
标头并根据内容进行管理。

接下来是使用反向代理(执行验证)并将结果转发到上游 http 服务器的场景。一、反向代理的相关部分:

server {
    listen 443 ssl http2;

...

    ssl_certificate /etc/XXX.pem;
    ssl_certificate_key /etc/XXX.key;
    ssl_client_certificate /etc/XXX/CA.pem;
    ssl_verify_client optional; # Or whatever

    ## PROXY backend
    location / {
        proxy_pass http://upstream:8080; 

        # Custom snippet to manage the proxy headers
        include snippets/proxy_ssl_client-upstream.conf;
    }

}

现在,

proxy_ssl_client-upstream.conf
文件:

# Snippet to be included in a reverse proxy server to catch the custom SSL_* headers
# (which will be seen as HTTP_SSL_* in the upstream) during the SSL verification process
# performed in the same proxy server, These headers should be transformed back
# to SSL_ for the web app, by using the corresponding
# $http_* variables generated by nginx. The web app should take care of
# SSL_* headers only.

# This is to prevent a warning about the bucket size
proxy_headers_hash_bucket_size 128;

# Here the standard SSL headers for a reverse SSL proxy
include snippets/proxy_ssl_standard-upstream.conf;


# And the set of headers, trying to mimic as much as possible the same headers
# that Apache generates via StdEnvVars and ExportCertData options in a SSLOptions directive

proxy_set_header SSL-CIPHER $ssl_cipher;
proxy_set_header SSL-CLIENT-CERT $ssl_client_escaped_cert;
proxy_set_header SSL-CLIENT-I-DN $ssl_client_i_dn;
proxy_set_header SSL-CLIENT-S-DN $ssl_client_s_dn;
proxy_set_header SSL-CLIENT-V-END $ssl_client_v_end;
proxy_set_header SSL-CLIENT-V-REMAIN $ssl_client_v_remain;
proxy_set_header SSL-CLIENT-V-START $ssl_client_v_start;
proxy_set_header SSL-CLIENT-VERIFY $ssl_client_verify; # “SUCCESS”, “FAILED:reason”, and “NONE”
proxy_set_header SSL-PROTOCOL $ssl_protocol;
proxy_set_header SSL-SERVER-S-DN $ssl_server_name;

并且自定义包括

proxy_ssl_standard-upstream.conf
(当不涉及客户端证书时,应该包括它而不是
proxy_ssl_client-upstream.conf
):

# forward standard headers to an upstream server

add_header Front-End-Https on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

最后是上游服务器的相关部分:

server {                                
        listen 8080;

...                                                     

    # PROD
    location ~ ^/index\.php(/|$) {
        fastcgi_pass php;
        # The standard snippet provided by nginx
        include snippets/fastcgi-php.conf;

        # A custom snippet to manage the headers forwarded by the reverse proxy
        include snippets/proxy_ssl_client-fastcgi.conf;
    }

包含的

ssl_proxy_client-fastcgi.conf

# Snippet to be included in an upstream server to catch the custom HTTP_SSL_* headers
# generated by another custom snippet during the SSL verification process
# performed by a reverse proxy server. This snippet transforms these generated
# HTTP_SSL_* headers as SSL_* to the web app via fastcgi, by using the corresponding
# $http_* variables generated by nginx. The web app should take care of
# SSL_* headers only.

fastcgi_param SSL_CIPHER $http_ssl_cipher;
fastcgi_param SSL_CLIENT_CERT $http_ssl_client_cert;
fastcgi_param SSL_CLIENT_I_DN $http_ssl_client_i_dn;
fastcgi_param SSL_CLIENT_S_DN $http_ssl_client_s_dn;
fastcgi_param SSL_CLIENT_V_END $http_ssl_client_v_end;
fastcgi_param SSL_CLIENT_V_REMAIN $http_ssl_client_v_remain;
fastcgi_param SSL_CLIENT_V_START $http_ssl_client_v_start;
fastcgi_param SSL_CLIENT_VERIFY $http_ssl_client_verify; # “SUCCESS”, “FAILED:reason”, and “NONE”
fastcgi_param SSL_PROTOCOL $http_ssl_protocol;
fastcgi_param SSL_SERVER_S_DN $http_ssl_server_s_dn;

# Clean up already used HTTP_* headers from proxy
fastcgi_pass_request_headers off;

我希望这可以帮助解决有关如何在 nginx 中管理 ssl 客户端证书的任何问题。


-1
投票

您可以使用第三方模块ngx_headers_more来完成此操作。构建包含此模块的 nginx 后,您可以在配置中执行以下操作:

location / {
    more_set_input_headers 'Foo: bar baz';
    ...
}

-1
投票

Nginx 现在有:

fastcgi_pass_header 'Cache-Control: no-cache, must-revalidate';

如果您要添加请求中尚未指定的标头,则可以在您的位置规则中使用它。默认情况下 fastcgi 使用:

fastcgi_pass_request_headers on;

这会将请求中的所有传入标头传递给 fastcgi。

© www.soinside.com 2019 - 2024. All rights reserved.