haproxy two-way ssl

Cài đặt CA cho HAProxy với Xác thực Two-Way SSL

Trong một số tình huống, việc có một Certificate Authority (CA) cá nhân hoá là cần thiết, đặc biệt khi bạn muốn tối ưu hóa việc xác thực SSL hai chiều trong HAProxy.

Tạo Khóa và Chứng chỉ CA

Bắt đầu hành trình thiết lập CA bằng việc tạo khóa:

openssl genrsa -out ca.key 4096

Bước tiếp theo liên quan đến việc tạo chứng chỉ. Đối với mục đích của chúng ta, chúng ta sẽ chọn một phiên bản tự ký:

openssl req -new -x509 -days 3650 -sha256 -key ca.key -out ca.crt -subj '/CN=root CA/O=Acme Corp'

Cấu hình CA của bạn

Sau khi đã có khóa và chứng chỉ, chúng ta sẽ tiến hành cấu hình CA. Tạo một tệp ca.conf và điền nội dung sau:

[ ca ]
default_ca   = acme_ca

[ crl_ext ]
authorityKeyIdentifier=keyid:always

[ acme_ca ]
DIR               = ./      # Default directory.
unique_subject    = no

certificate       = ${DIR}/ca.crt           
database          = ${DIR}/index.txt        
                                            
new_certs_dir     = ${DIR}/                 

private_key       = ${DIR}/ca.key           
serial            = ${DIR}/serial           

default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
copy_extensions   = copyall

default_days      = 730           
default_crl_days  = 730           

policy            = acme_policy    

[ acme_policy ]
C=      optional        # Country
ST=     optional        # State or province
L=      optional        # Locality
O=      supplied        # Organization
OU=     optional        # Organizational unit
CN=     supplied        # Common name

Một điểm an ninh quan trọng cần lưu ý: Sử dụng copy_extensions = copyall có thể tạo ra các vấn đề về an ninh, đặc biệt là khi bạn ký các Yêu cầu Ký Chứng chỉ (CSR) mà bạn không tự tạo. Phương pháp này chỉ được khuyến nghị khi bạn có quyền kiểm soát đầy đủ các CSR.

Tiếp tục bằng việc tạo tệp chỉ mục chứng chỉ:

touch index.txt

Sau đó, thiết lập cơ sở dữ liệu serial:

echo '01' > serial

Kết thúc cấu hình CA, chúng ta sẽ tạo Danh sách Thu hồi Chứng chỉ (CRL):

openssl ca -config ca.conf -gencrl -keyfile ca.key -cert ca.crt -out crl.pem

Ở thời điểm này, danh sách vẫn trống vì chưa có chứng chỉ nào bị thu hồi. Đảm bảo bạn sao chép các tệp ca.crtcrl.pem vào một vị trí mà HAProxy có thể truy cập sau này, ví dụ:

cp ca.crt /etc/haproxy/certs
cp crl.pem /etc/haproxy/certs

Tạo Khóa và Chứng chỉ cho HAProxy

Bắt đầu bằng việc tạo một khóa riêng:

openssl genrsa -out node.key 2048

Tiếp theo là tạo một CSR:

openssl req -new -key node.key -out node.csr -subj '/CN=node.example.com/O=Acme' -addext 'subjectAltName = DNS:proxy,DNS:proxy.example.com'

Trong CSR trên, chúng ta đã xác định rằng HAProxy sẽ hoạt động trên một máy chủ node.example.com (được chỉ định là CN), và nó cũng sẽ có một mục nhập DNS proxy.example.com.

Giờ đến lúc sử dụng CA của chúng ta để ký chứng chỉ này:

openssl ca -batch -config ca.conf -notext -in node.csr -out node.crt

Để thuận tiện hơn, đóng gói khóa và chứng chỉ vào một kho lưu trữ khóa PKCS12:

openssl pkcs12 -export -chain -CAfile ca.crt -in node.crt -inkey node.key -passout pass:mypassword > node.p12

Sau khi đã có khóa và chứng chỉ của HAProxy, hãy tạo một tệp PEM mà HAProxy có thể sử dụng:

openssl pkcs12 -in node.p12 -passin pass:mypassword -nodes -out haproxy.pem

Chuyển tệp PEM đã tạo sang một vị trí mà HAProxy có thể truy cập sau này:

cp haproxy.pem /etc/haproxy/certs

Đáng chú ý ở đây là chúng ta đã ký chứng chỉ HAProxy với CA của riêng mình, nhưng thực sự không bắt buộc phải sử dụng xác thực SSL hai chiều. Bạn hoàn toàn có thể sử dụng một chứng chỉ được ký bởi một CA được tin cậy trên toàn cầu. Tuy nhiên, trong trường hợp này, chúng ta chỉ sử dụng CA của chính mình.

Khởi chạy HAProxy

Tạo một tệp /etc/haproxy/haproxy.cfg và điền vào đó nội dung sau:

global
  log 127.0.0.1 local0 info
  spread-checks 5
  max-spread-checks 15000
  maxconn 50000
  tune.ssl.default-dh-param 2048
  ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:!aNULL:!MD5:!DSS
  ssl-default-bind-options no-sslv3 no-tlsv10 no-tls-tickets
  ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:!aNULL:!MD5:!DSS
  ssl-default-server-options no-sslv3 no-tlsv10 no-tls-tickets

defaults
  log               global
  retries                   3
  backlog               10000
  maxconn               10000
  timeout connect          3s
  timeout client          30s
  timeout server          30s
  timeout tunnel        3600s
  timeout http-keep-alive  1s
  timeout http-request    15s
  timeout queue           30s
  timeout tarpit          60s
  option            dontlognull
  option            http-server-close
  option            redispatch

frontend http_in
  bind *:80
  mode http
  redirect scheme https code 301

frontend https_in
  bind *:443 ssl crt /etc/certs/haproxy.pem ca-file /etc/certs/ca.crt verify required crl-file /etc/certs/crl.pem
  mode http
  use_backend webdav if { path -i -m beg /shared }
  use_backend prometheus if { path -i -m beg /prometheus }

backend prometheus
  mode http
  option forwardfor
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }
  reqirep  "^([^ :]*) /prometheus/?(.*)" "1 /2"
  server prometheus prometheus:9090

backend webdav
  mode http
  option forwardfor
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }
  server webdav webdav:80

Để tận dụng sức mạnh của HAProxy với Docker, thực thi lệnh sau:

docker run -d -p 80:80 -p 443:443 
    -v /etc/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg 
    -v /etc/haproxy/certs:/etc/certs 
    haproxy:2.0-alpine

Tạo Chứng chỉ Client

Bây giờ, với HAProxy đang hoạt động và tiết lộ dịch vụ WebDAV và Prometheus của chúng ta, hãy tạo một chứng chỉ client để có thể truy cập nó một cách an toàn.

Đầu tiên, tạo một khóa cho client:

openssl genrsa -des3 -passout pass:myclientpw -out client.key 2048

Tiếp theo, tạo một CSR:

openssl req -new -key client.key -passin pass:myclientpw -out client.csr -subj '/CN=My Client/O=Acme Corp'

Bây giờ, chúng ta sẽ ký CSR này để tạo ra một chứng chỉ:

openssl ca -batch -config ca.conf -notext -in client.csr -out client.crt

Tiếp theo, tạo một kho lưu trữ khóa PKCS12 để việc phân phối trở nên dễ dàng hơn:

openssl pkcs12 -export -chain -CAfile ca.crt -in client.crt -inkey client.key -passin pass:myclientpw -passout pass:myclientpw > client.p12

Bây giờ, bạn có thể nhập kho lưu trữ khóa này vào chuỗi chứng chỉ của trình duyệt và truy cập cả WebDAV và Prometheus.

Hãy liên hệ tôi nếu bạn cần bất kỳ sự trợ giúp nào.

Share this
Send this to a friend