Cho phép mã hóa với proxy ngược nginx


45

Giới thiệu

Tôi có một máy chủ dev (hiện đang chạy Ubuntu 14.04 LTS), hiện tại tôi đang sử dụng để lưu trữ các công cụ phát triển khác nhau trên các cổng khác nhau. Bởi vì các cổng có thể khó nhớ, tôi đã quyết định sử dụng cổng 80 cho tất cả các dịch vụ của mình và thực hiện chuyển tiếp cổng nội bộ, dựa trên tên máy chủ.

Thay vì viết domain.com:5432, tôi chỉ có thể truy cập nó thông qua sub.domain.com

Ví dụ: ứng dụng X đang sử dụng cổng 7547 và đang chạy trên sub.domain.com có ​​cấu hình nginx sau:

upstream sub {
    server 127.0.0.1:7547;
}

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    access_log /var/log/nginx/sub.log combined;
    location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:7547;
            proxy_set_header Authorization "";
    }
}

Câu hỏi

Với cấu trúc cấu hình hiện tại, mà tôi đã chọn, có thể sử dụng letencrypt và chạy các dịch vụ khác nhau trong https không?


3
Tôi đã viết một bài đăng trên blog về chủ đề này: tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no-dftimeime
Tom Busby

Câu trả lời:


81

Có, bạn có thể có các yêu cầu proxy nginx đến các máy chủ HTTP và sau đó chính nó sẽ trả lời các máy khách qua HTTPS. Khi làm điều này, bạn sẽ muốn chắc chắn rằng nginx <-> proxy kết nối không có khả năng bị đánh hơi bởi bất cứ ai là kẻ tấn công dự kiến ​​của bạn. Phương pháp đủ an toàn có thể bao gồm:

  • ủy quyền cho cùng một máy chủ (như bạn làm)
  • ủy quyền cho các máy chủ khác đằng sau tường lửa của bạn

Việc ủy ​​quyền cho một máy chủ khác trên Internet công cộng dường như không đủ an toàn.

Dưới đây là hướng dẫn để nhận chứng chỉ Encrypt bằng cách sử dụng cùng một máy chủ web mà bạn đang sử dụng làm proxy.

Yêu cầu chứng chỉ ban đầu của bạn từ Let Encrypt

Sửa đổi servermệnh đề của bạn để cho phép thư mục con .well-knownđược phục vụ từ một thư mục cục bộ, ví dụ:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    […]
    location /.well-known {
            alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}

http://sub.domain.com/.well-known là nơi các máy chủ Let Encrypt sẽ tìm kiếm câu trả lời cho những thách thức mà nó đưa ra.

Sau đó, bạn có thể sử dụng ứng dụng khách certbot để yêu cầu chứng chỉ từ Let Encrypt bằng cách sử dụng plugin webroot (với quyền root):

certbot certonly --webroot -w /var/www/sub.domain.com/ -d sub.domain.com -d www.sub.domain.com

Khóa, chứng chỉ và chuỗi chứng chỉ của bạn sẽ được cài đặt trong /etc/letsencrypt/live/sub.domain.com/

Định cấu hình nginx để sử dụng chứng chỉ của bạn

Đầu tiên tạo một mệnh đề máy chủ mới như thế này:

server {
    listen 443 ssl;

    # if you wish, you can use the below line for listen instead
    # which enables HTTP/2
    # requires nginx version >= 1.9.5
    # listen 443 ssl http2;

    server_name sub.domain.com www.sub.domain.com;

    ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem;

    # Turn on OCSP stapling as recommended at 
    # https://community.letsencrypt.org/t/integration-guide/13123 
    # requires nginx version >= 1.3.7
    ssl_stapling on;
    ssl_stapling_verify on;

    # Uncomment this line only after testing in browsers,
    # as it commits you to continuing to serve your site over HTTPS
    # in future
    # add_header Strict-Transport-Security "max-age=31536000";

    access_log /var/log/nginx/sub.log combined;

    # maintain the .well-known directory alias for renewals
    location /.well-known {
        alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here as in your port 80 configuration
        […]
    }
}

Tải lại nginx:

service nginx reload

Xác minh rằng HTTPS hiện hoạt động bằng cách truy cập https://sub.domain.comhttps://www.sub.domain.comtrong trình duyệt của bạn (và bất kỳ trình duyệt nào khác bạn muốn hỗ trợ cụ thể) và kiểm tra xem chúng có báo cáo lỗi chứng chỉ không.

Khuyến nghị: cũng xem xét raymii.org: Bảo mật SSL mạnh trên nginx và kiểm tra cấu hình của bạn tại SSL Labs .

(Khuyến nghị) Chuyển hướng yêu cầu HTTP sang HTTPS

Khi bạn đã xác nhận rằng trang web của bạn hoạt động với https://phiên bản URL, thay vì có một số người dùng phục vụ nội dung không an toàn vì họ đã truy cập http://sub.domain.com, hãy chuyển hướng họ đến phiên bản HTTPS của trang web.

Thay thế toàn bộ servermệnh đề cổng 80 của bạn bằng:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    rewrite     ^   https://$host$request_uri? permanent;
}

Bây giờ bạn cũng nên bỏ dòng này trong cấu hình cổng 443, để các trình duyệt nhớ thậm chí không thử phiên bản HTTP của trang web:

add_header Strict-Transport-Security "max-age=31536000";

Tự động gia hạn chứng chỉ của bạn

Bạn có thể sử dụng lệnh này (với quyền root) để gia hạn tất cả các chứng chỉ được biết đến certbot và tải lại nginx bằng chứng chỉ mới (sẽ có cùng đường dẫn với chứng chỉ hiện có của bạn):

certbot renew --renew-hook "service nginx reload"

certbot sẽ chỉ cố gắng gia hạn các chứng chỉ đã quá 60 ngày, vì vậy an toàn (và được khuyến nghị!) để chạy lệnh này rất thường xuyên và tự động nếu có thể. Ví dụ: bạn có thể đặt lệnh sau vào /etc/crontab:

# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16   * * *   root   certbot renew --quiet --renew-hook "service nginx reload"

Bạn có thể kiểm tra gia hạn bằng một bản chạy khô, sẽ liên hệ với các máy chủ dàn xếp của Encrypt để thực hiện một thử nghiệm thực sự về việc liên hệ với tên miền của bạn, nhưng sẽ không lưu trữ các chứng chỉ kết quả:

certbot --dry-run renew

Hoặc bạn có thể buộc gia hạn sớm với:

certbot renew --force-renew --renew-hook "service nginx reload"

Lưu ý: bạn có thể chạy khô bao nhiêu lần tùy thích, nhưng các lần gia hạn thực sự phải tuân theo giới hạn tốc độ Mã hóa của Let .


Soluton của bạn dường như không làm việc cho tôi. Tôi có cấu hình cơ bản giống nhau. Nó hoạt động cho goopen.tk, nhưng không phải www.goopen.tk
Alko

3
@Alko, hướng dẫn của câu trả lời là chính xác và bao gồm vấn đề này. Khi sử dụng certbothoặc bất kỳ công cụ nào khác, bạn không thể quên chỉ định tên miền của mình ở cả định dạng www và không www để hoạt động.
Paulo Coghi

Dưới location /.well-known, bạn cần phải rời .well-knownkhỏi trong đường dẫn. Sử dụng alias /var/www/sub.domain.com, không phảialias /var/www/sub.domain.com/.well-known
gldraphael

1
Bất cứ ai cũng có thể giải thích cho tôi lý do tại sao bạn muốn sử dụng "viết lại ^ https: // $ host $ request_uri? Permanent;" ở đây thay vì "trả về 301 https: // $ server_name $ request_uri;"
ZaxLofful

Tôi thấy rằng tôi cần trích dẫn xung quanh đường dẫn trong vị trí. location '/.well-known' {. Không chắc đây là phiên bản hay chỉ là thiết lập của tôi nhưng trong trường hợp người khác bị kẹt.
Frank V

2

Có, bạn có thể sử dụng nginxlàm điểm cuối của https và hợp tác với phụ trợ qua http. Ví dụ: cấu hình của tôi:

server {
        server_name host;
        listen 443 ssl;
...
 location /svn/ {
            auth_ldap off;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_pass http://localhost:1080/svn/;
            proxy_redirect http://localhost:1080/ https://host/;
        }
...
}

Nhưng như tôi biết, với việc mã hóa, bạn phải trỏ tất cả các tên miền phụ khi bạn nhận được chứng chỉ và nếu đây là một vấn đề, thì bạn chọn url https://host/servicethay vìhttps://service.host

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.