SSLクライアント証明書認証でバックエンドするNginxプロキシ


13

私には2台のサーバーがあり、どちらにもnginxがあります。サーバーAは443をリッスンしており、クライアントSSL証明書で認証するように構成されています。

サーバーBには、nginxを介してサーバーAと通信する必要がある内部プロセスがあります。

8080(すべてローカル通信なので暗号化なし)をリッスンし、ServerA:443にproxy_passするサーバーBでNginxを構成したいと思います。

問題は、クライアント証明書をどのように注入するかです。私は、それを行うproxy_xxxx関数を見つけられませんでした。

私はsocatでそれと同等のものを作る方法を知っていますが、私の要件はnginxを使用することです。


2
nginxのプロキシモジュールのディレクティブを見ると、nginxサーバーで証明書を使用して認証することはできないようです。nginx.org / en / docs / http / ngx_http_proxy_module.html Apacheはこの機能をサポートしています。
NuTTyX 2014

それは私が恐れていたものです...カスタムモジュールまたはこれを機能させることができる何かがあるかどうかのアイデア?そのような機能が存在している必要があります!
Bastien974 14

設定ファイルをapacheからnginx(github.com/nhnc-nginx/apache2nginx)に移行するユーティリティを見つけたので、それをダウンロードし、ダミーのapache.confを作成してツールに渡しましたが、この結果が得られました:### Section 2: Unconverted directives ### # Flag Description # [S] Unsupported directives. # In conf file: dummy.conf # Line 32: SSLProxyMachineCertificateFile /path/to/cert (mod_ssl.c) # [S] SSLProxyMachineCertificateFile: No relevant directive in Nginx.
NuTTyX 2014

回答:


20

クライアント証明書の詳細を渡すだけで十分ですか?

あなたは付け加えられます

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

構成に追加すると、サーバーBはX-SSL-Certヘッダーを介して証明書情報を利用できます。


1
comentedとしてここにあなたのバックエンドが交換することができれば、知っておく\t\nreadedたら、このヘッダから。
lucasvc 2016年

3
nginxのドキュメントによると、$ssl_client_cert変数は非推奨です。$ssl_client_escaped_cert代わりに変数を使用する必要があります。
dubek

1
@dubek良いキャッチ、私はこのような場合に答えを直接更新します。
Chris Stryczynski

私はこのソリューションを試してみましたが、証明書の検証がオンに設定されている場合にのみ証明書を通過させるようです。オンにしたくないのですが、検証をオンにせずに機能させる方法はありますか?
juhako

5

どうやら、これはあなたが探しているものです:http : //nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_certificateバージョン1.7.8以降で利用可能です。

location / {
    ...
    proxy_pass     the_other_nginx;
    proxy_ssl_certificate  the_certificate.pem;
    ...
}

1
これは間違っています。これにより、バックエンドへのリクエストに使用されるクライアント証明書がプロキシに割り当てられます。しかし、尋ねたところ、この通信はローカルでのみ暗号化されないため、クライアント証明書のチェックは行われません。jwilkinsの答えはうまくいきます。
Kenyakorn Ketsombut

@KenyakornKetsombut私はあなたが質問を誤解していると思います。サーバーBは暗号化されていません(8080でリッスン)が、サーバーAと通信する必要があります(暗号化で443でリッスンします)。したがって、Bは認証のためにクライアント証明書をAに送信する必要があります。これを行うには、proxy_ssl_certificateを使用できます。jwilkinsが答えると、Bに渡された証明書がAに転送されます。どちらも必要に応じて機能します。
Nicolas Malbran

こんにちはニコラス。サーバーBが暗号化を使用していない場合(ポート8080)、HTTPS / SSLなどを使用していません。クライアント証明書はSSLの一部であるため、この部分はサーバーBでは実行できません。Bはクライアント証明書を送受信できません。
Kenyakorn Ketsombut 2015

1
nginxを取得:[emerg]証明書 "certs / Roro_Client.pem"に "proxy_ssl_certificate_key"が定義されていませんnginx:設定ファイル/etc/nginx/nginx.confを1.8.0で試したところ、失敗しました
Wolfgang Fahl

4

問題は主にバージョンに依存するようです。Ubuntu 14.04 LTSでは、デフォルトのnginxは古い1.4です。まず、PPAベースのバージョンをインストールする必要があります

https://leftshift.io/upgrading-nginx-to-the-latest-version-on-ubuntu-servers

これを行う方法を示します:

sudo add-apt-repository ppa:nginx/stable
sudo aptitude safe-upgrade

あなたは次のようになるはずです:

nginx -v
nginx version: nginx/1.8.0

xatr0zの答え@から設定https://serverfault.com/a/636455/162693を指す http://www.senginx.org/en/index.php/Proxy_HTTPS_Client_Certificateは 仕事をしません。

機能しない提案

backend {
    server some-ip:443;
}

server {
    listen 80;


    location / {
        proxy_ssl_certificate        certs/client.crt;
        proxy_ssl_certificate_key    certs/client.key;


        proxy_pass https://backend;
    }
}

1.8.0では、そのままでは機能しません。これはおそらくヒントとしてのみ意図されており、そのような設定ファイルとして使用したり、別のバージョンに依存することはありません。

SSLと自己署名クライアント証明書を有効にしたapache2ベースのバックエンドサーバーAでテストしています。Apache config SSLOptionsは次のように設定されています。

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

これにより、バックエンド側のphpinfo()スクリプトがサーバー側とクライアント側の情報を表示するため、状況のデバッグが容易になります。

これを確認するには、私が使用しました:

https:// backend / test / phpinfo

ブラウザにSSL証明書をインストールすると、サーバー証明書のSSL_SERVER_S_DN_CNとクライアント証明書のSSL_CLIENT_S_DN_CNのようなセクションが表示されます。

最初のスタートとして、フロントエンドサーバーBでnginxを構成するために使用しました(括弧内の部分を埋めます)。

server {
  listen 8080;
  server_name <frontend>;

  location / {
    proxy_buffering off;
    proxy_pass https://<backend>;
    #proxy_ssl_certificate      certs/<SSL Client Certificate>.crt;
    #proxy_ssl_certificate_key  certs/<SSL Client Certificate>.key;
  }
}

SSLクライアント証明書固有の部分のコメントを外して、リバースプロキシ自体が機能することを確認します。

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
service nginx restart
nginx stop/waiting
nginx start/running, process 8931

これでhttp:// frontend:8080 / test / phpinfo.phpが機能します

サーバー証明書のSSL_SERVER_S_DN_CNが表示され、クライアント証明書のSSL_CLIENT_S_DN_CN は(まだ)表示されない

コメントを外した後:

server {
  listen 8080;
  server_name <frontend>;

  location / {
    proxy_buffering off;
    proxy_pass https://<backend>;
    proxy_ssl_certificate      certs/<SSL Client Certificate>.crt;
    proxy_ssl_certificate_key  certs/<SSL Client Certificate>.key;
  }
}

およびチェック/再起動

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
service nginx restart
nginx stop/waiting
nginx start/running, process 8931

http:// frontend:8080 / test / phpinfo.phpが機能し、

サーバー証明書のSSL_SERVER_S_DN_CNが表示され、クライアント証明書のSSL_CLIENT_S_DN_CN が表示されます

これで、要求どおりに機能するようになりました。

バグhttps://trac.nginx.org/nginx/ticket/872#ticketに注意してください


再交渉中の問題ruby-forum.com/topic/6875137に注意して、ショーを台無しにするかもしれません
Wolfgang Fahl

1

nginxとSSLクライアント証明書に関するすばらしい記事があります。例としてPHPとFastCGIを使用していますが、これをリバースプロキシの設定に適応させることができると思います。

server {
    listen        443;
    ssl on;
    server_name example.com;

    ssl_certificate      /etc/nginx/certs/server.crt;
    ssl_certificate_key  /etc/nginx/certs/server.key;
    ssl_client_certificate /etc/nginx/certs/ca.crt;
    ssl_verify_client optional;

    location / {
        root           /var/www/example.com/html;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME /var/www/example.com/lib/Request.class.php;
        fastcgi_param  VERIFIED $ssl_client_verify;
        fastcgi_param  DN $ssl_client_s_dn;
        include        fastcgi_params;
    }
}

ソースhttp://nategood.com/client-side-certificate-authentication-in-ngi


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.