พร็อกซี Nginx สำหรับแบ็คเอนด์ที่มีการตรวจสอบความถูกต้องใบรับรองไคลเอ็นต์ SSL


14

ฉันมีสองเซิร์ฟเวอร์ทั้งคู่มี nginx เซิร์ฟเวอร์ A กำลังรับฟัง 443 และได้รับการกำหนดค่าให้ตรวจสอบสิทธิ์ด้วยใบรับรอง SSL ของไคลเอ็นต์

เซิร์ฟเวอร์ B มีกระบวนการภายในที่ต้องสื่อสารกับเซิร์ฟเวอร์ A ถึง nginx

ฉันต้องการกำหนดค่า Nginx บนเซิร์ฟเวอร์ B ที่จะรับฟัง 8080 (ไม่มีการเข้ารหัสเนื่องจากเป็นการสื่อสารในท้องถิ่นทั้งหมด) และ proxy_pass เป็น ServerA: 443

คำถามคือฉันจะฉีดใบรับรองลูกค้าได้อย่างไร ฉันไม่พบฟังก์ชัน proxy_xxxx ใด ๆ ที่จะทำเช่นนั้น

ฉันรู้วิธีทำให้เทียบเท่ากับ socat แต่ความต้องการของฉันคือใช้ nginx


2
การดูคำสั่งในโมดูลพร็อกซีของ nginx ดูเหมือนว่าไม่สามารถสร้างเซิร์ฟเวอร์ nginx ให้ใช้ใบรับรองเพื่อตรวจสอบสิทธิ์: nginx.org/en/docs/http/ngx_http_proxy_module.html Apache จะสนับสนุนคุณสมบัตินั้น
NuTTyX

นั่นคือสิ่งที่ฉันกลัว ... ความคิดใด ๆ หากมีโมดูลที่กำหนดเองหรือสิ่งที่สามารถทำให้งานนี้ได้หรือไม่ คุณสมบัติดังกล่าวต้องมีอยู่จริง!
Bastien974

ฉันพบยูทิลิตี้ในการโยกย้ายไฟล์กำหนดค่าจาก 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

คำตอบ:


21

มันเพียงพอที่จะให้รายละเอียดใบรับรองลูกค้าผ่านหรือไม่

คุณสามารถเพิ่ม

proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;

ถึง config ของคุณจากนั้นข้อมูลใบรับรองจะมีให้สำหรับเซิร์ฟเวอร์ B ผ่านทางส่วนหัว X-SSL-Cert


1
ดังที่ปรากฏที่นี่โปรดระวังว่าแบ็กเอนด์ของคุณสามารถแทนที่\tด้วย\nจากส่วนหัวนี้เมื่ออ่าน
lucasvc

3
ตามเอกสาร Nginx ของที่$ssl_client_certตัวแปรจะเลิก; $ssl_client_escaped_certตัวแปรควรจะนำมาใช้แทน
dubek

1
@dubek good catch ฉันจะอัปเดตคำตอบโดยตรงในกรณีเช่นนี้
Chris Stryczynski

ฉันได้ลองใช้วิธีแก้ไขปัญหานี้แล้ว แต่ดูเหมือนว่าจะผ่านการรับรองเท่านั้นหากการตรวจสอบความถูกต้องของใบรับรองตั้งไว้ที่ ON ฉันไม่ต้องการเปิดใช้งานมีวิธีทำให้ทำงานโดยไม่ตั้งค่าการตรวจสอบหรือไม่
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 จะส่งต่อไปยัง A ที่มอบให้แก่ B. ทั้งคู่อาจทำงานได้ขึ้นกับสิ่งที่คุณต้องการ
Nicolas Malbran

สวัสดีนิโคลัส ฉันพยายามจะพูดว่า: หากเซิร์ฟเวอร์ B ไม่ได้ใช้การเข้ารหัส (บนพอร์ต 8080) จะไม่ใช้สิ่งใด ๆ เช่น HTTPS / SSL หรือที่คุณเรียกว่า ใบรับรองไคลเอ็นต์เป็นส่วนหนึ่งของ SSL ดังนั้นเซิร์ฟเวอร์ B. B จึงไม่สามารถส่งหรือรับใบรับรองไคลเอ็นต์ใด ๆ ได้
Kenyakorn Ketsombut

1
ฉันได้รับ nginx: [ฉุกเฉิน] ไม่มี "proxy_ssl_certificate_key" ถูกกำหนดไว้สำหรับใบรับรอง "certs / Roro_Client.pem" 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 อาจมีความหมายว่าเป็นเพียงคำใบ้เท่านั้นและไม่ควรใช้เป็นไฟล์กำหนดค่าดังกล่าวหรือขึ้นกับรุ่นอื่น

ฉันกำลังทดสอบกับเซิร์ฟเวอร์แบ็กเอนด์ที่ใช้ apache2 A ที่เปิดใช้ SSL และใบรับรองไคลเอ็นต์ที่ลงชื่อด้วยตนเอง Apache config SSLOptions ถูกตั้งค่าเป็น:

SSLOptions +ExportCertData +FakeBasicAuth + StdEnvVars

สิ่งนี้ทำให้การดีบักสถานการณ์ง่ายขึ้นเนื่องจากสคริปต์ phpinfo () ที่ด้านหลังจะแสดงข้อมูลเซิร์ฟเวอร์และฝั่งไคลเอ็นต์

เพื่อตรวจสอบสิ่งนี้ฉันใช้:

https: // แบ็กเอนด์ / ทดสอบ / phpinfo

เมื่อติดตั้งใบรับรอง SSL ในเบราว์เซอร์และฉันได้รับส่วนต่างๆเช่น: SSL_SERVER_S_DN_CN สำหรับใบรับรองเซิร์ฟเวอร์และ SSL_CLIENT_S_DN_CN สำหรับใบรับรองไคลเอ็นต์

เป็นการเริ่มต้นครั้งแรกที่ฉันใช้ (กรอกข้อมูลลงในวงเล็บ) เพื่อกำหนดค่า nginx บนเซิร์ฟเวอร์ส่วนหน้า B:

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;
  }
}

uncomenting ส่วนใบรับรองเฉพาะไคลเอ็นต์ SSL เพียงเพื่อตรวจสอบว่า reverse proxy ทำงานได้หรือไม่

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: // ส่วนหน้า: 8080 / test / phpinfo.php ใช้งานได้

SSL_SERVER_S_DN_CN สำหรับใบรับรองเซิร์ฟเวอร์แสดงขึ้นและ SSL_CLIENT_S_DN_CN สำหรับใบรับรองไคลเอ็นต์ยังไม่ปรากฏ (ยัง)

หลังจาก uncommenting:

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: // ส่วนหน้า: 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.