Chuyển trang web http Apache thành trang https an toàn thông qua proxy ngược Nginx
Tôi phải hỗ trợ một trang WordPress cũ chạy trên máy chủ web Apache. Để giúp mọi thứ an toàn hơn, máy chủ Apache này nằm trong vùng chứa Docker và nó có thể truy cập được với mọi người thông qua cấu hình proxy ngược Nginx. Trang web này hiện được phục vụ qua http và tôi muốn chuyển nó sang https.
Tôi nghĩ tôi có hai lựa chọn:
Chứng chỉ SSL được cài đặt cho trang Nginx và nó được cài đặt cho trang
proxy_passhttp thuần túy trên vùng chứa Apache:server { listen 443 ssl; server_name www.example.com; ssl_certificate /etc/nginx/ssl/letsencrypt/live/www.example.com/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/letsencrypt/live/www.example.com/privkey.pem; access_log /var/log/nginx/example.com.access.log; location / { proxy_pass http://Apache2-PHP5.6:80; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }Trong trường hợp này từ quan điểm của máy chủ Apache, nó vẫn đang phục vụ trang web qua http
Điều này tốn nhiều công sức hơn: chứng chỉ SSL được cài đặt trên cả máy chủ Nginx cổng và trang web Apache được ủy quyền. Sau đó, nó sẽ là cần thiết để thay đổi
httpđểhttpstrongproxy_passgiá trị cấu hình.
Tôi ước tất cả đều ổn với kịch bản đầu tiên. Nhưng thực tế là Apache cảm thấy nó đang phục vụ nội dung qua http dẫn đến một số vấn đề: có một số chuyển hướng URL ẩn mà tôi thực sự không muốn định cấu hình lại / gỡ lỗi. Và những chuyển hướng URL đó thực hiện một cái gì đó như thế này: nếu URL được yêu cầu http://www.example.com, nó được viết lại (trạng thái http 301) như http://www.example.com/main. Trình duyệt nhận được chuyển hướng này và do đó, mặc dù yêu cầu đầu tiên là https, nhưng bây giờ URL được chuyển hướng là http. Ngoài ra, các trang web html chứa hrefs đường dẫn đầy đủ phục vụ đến các tài nguyên riêng của nó (tệp JavaScript và CSS) bao gồm cả tham chiếu giao thức. Tại thời điểm này, không rõ liệu các hrefs đó có áp dụng giao thức từ cách yêu cầu được thực hiện hay nó được mã hóa cứng. Dù sao, tiếc là điều này không hoạt động nếu không có một số nghiên cứu nghiêm túc.
Vì vậy, tôi còn lại với tùy chọn 2. Tôi đã thử, nó hoạt động, tôi có thể thiết lập cùng một chứng chỉ SSL trên cả Nginx và Apache được chứa trong vùng chứa. Nhưng tôi muốn biết liệu đây có thực sự là cách nó nên được để chạy hay không. Bởi vì mặc dù máy chủ Apache bây giờ biết rằng nội dung đang được phân phối qua https, nhưng giờ đây vẫn có SSL kép xảy ra cho mọi yêu cầu. Nó cảm thấy không ổn.
Trả lời
Bạn sẽ có thể cho Apache biết rằng yêu cầu đến đang được ủy quyền từ một yêu cầu HTTPS bằng proxy_set_header X-Forwarded-Proto "https";khai báo trong lần thiết lập đầu tiên
Bạn có thể giải quyết vấn đề trong tùy chọn số 1 của mình (như bạn đã nói, là một cách tiếp cận tốt hơn nhiều) bằng cách đặt HTTP_X_FORWARDED_PROTO trong cấu hình nginx của bạn với
proxy_set_header X-Forwarded-Proto $scheme;
và định cấu hình WordPress để nhận ra nó bằng cách thêm dòng này vào wp-config.php
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on';
}
Xem thêm bài viết hỗ trợ Wordpress để biết một biến thể của giải pháp này.
Thông thường, tôi muốn thực hiện tất cả các công việc nặng nhọc trên proxy ngược và giữ cho trang web phụ trợ được hiển thị nguyên bản nhất có thể.
Vấn đề của bạn dường như về bản chất là phần phụ trợ (WordPress) tạo và sử dụng (tuyệt đối) URI khác với những gì bạn muốn khách truy cập sử dụng.
Bạn có thể khắc phục điều đó bằng cách viết lại nội dung (HTML) mà WordPress tạo ra trong nginx với ngx_http_sub_module . Điều đó cũng sẽ cho phép bạn viết lại URL tuyệt đối bằng một cái gì đó tương tự như:
location / {
sub_filter 'http://example.com/' 'https://www.example.com/' ;
sub_filter 'http://www.example.com/' 'https://www.example.com/' ;
sub_filter_once off;
proxy_pass http://Apache2-PHP5.6:80;
proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}