Позволяет зашифровать с помощью обратного прокси nginx

45

Введение

У меня есть сервер разработки (в настоящее время работает Ubuntu 14.04 LTS), который я уже некоторое время использую для размещения различных инструментов разработки на разных портах. Поскольку порты могут быть трудно запомнить, я решил использовать порт 80 для всех моих служб и выполнять переадресацию портов внутренне, основываясь на имени хоста.

Вместо того, чтобы писать domain.com:5432, я могу просто получить к нему доступ через sub.domain.com

Например, приложение X, которое использует порт 7547 и работает на sub.domain.com, имеет следующую конфигурацию nginx:

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

Вопрос

Учитывая текущую структуру конфигурации, которую я выбрал, возможно ли использовать letsencrypt и запускать различные службы под https?

0x450
источник
3
Я написал сообщение в блоге на эту тему: tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no-downtime
Том Басби,

Ответы:

81

Да, вы можете получать запросы прокси-сервера nginx к HTTP-серверам, а затем сами отвечать клиентам по HTTPS. При этом вы должны быть уверены, что соединение прокси-сервера nginx <-> вряд ли будет прослушано кем-либо из ваших предполагаемых атакующих. Достаточно безопасные подходы могут включать:

  • проксирование к тому же хосту (как и вы)
  • проксирование на другие хосты за вашим брандмауэром

Проксирование другого хоста в общедоступном Интернете вряд ли будет достаточно безопасным.

Ниже приведены инструкции по получению сертификата Let's Encrypt с использованием того же веб-сервера, который вы используете в качестве прокси.

Запрос вашего начального сертификата от Let's Encrypt

Измените ваше serverпредложение, чтобы разрешить обслуживание подкаталога .well-knownиз локального каталога, например:

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 Именно здесь серверы Let's Encrypt будут искать ответы на возникающие проблемы.

Затем вы можете использовать клиент certbot для запроса сертификата в Let's Encrypt с помощью плагина webroot (как root):

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

Ваш ключ, сертификат и цепочка сертификатов теперь будут установлены в /etc/letsencrypt/live/sub.domain.com/

Настройка nginx для использования вашего сертификата

Сначала создайте новое предложение сервера следующим образом:

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
        […]
    }
}

Перезагрузить nginx:

service nginx reload

Убедитесь, что HTTPS теперь работает, посетив https://sub.domain.comи https://www.sub.domain.comв своем браузере (и любых других браузерах, которые вы специально хотите поддерживать) и убедитесь, что они не сообщают об ошибках сертификата.

Рекомендуем также ознакомиться с raymii.org: Надежная защита SSL на nginx и протестировать свою конфигурацию в лабораториях SSL .

(Рекомендуется) Перенаправить HTTP-запросы на HTTPS

После того как вы подтвердите, что ваш сайт работает с https://версией URL-адреса, а не для того, чтобы некоторые пользователи обслуживали небезопасный контент из-за http://sub.domain.comперехода, перенаправьте их на HTTPS-версию сайта.

Замените весь serverпункт 80 порта следующим :

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

Вы также должны теперь раскомментировать эту строку в конфигурации порта 443, чтобы браузеры даже не пробовали использовать HTTP-версию сайта:

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

Автоматически обновлять ваш сертификат

Вы можете использовать эту команду (как root), чтобы обновить все сертификаты, известные certbot, и перезагрузить nginx, используя новый сертификат (который будет иметь тот же путь, что и ваш существующий сертификат):

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

certbot будет пытаться обновить только сертификаты, срок действия которых превышает 60 дней, поэтому безопасно (и рекомендуется!) запускать эту команду очень регулярно и автоматически, если это возможно. Например, вы можете ввести следующую команду /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"

Вы можете протестировать обновления с помощью пробного запуска, который свяжется с промежуточными серверами Let's Encrypt, чтобы провести реальный тест связи с вашим доменом, но не сохранит полученные сертификаты:

certbot --dry-run renew

Или вы можете форсировать раннее обновление с помощью:

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

Примечание: вы можете пробовать неограниченное количество раз, но для реальных обновлений действуют ограничения скорости Let's Encrypt .

замешательство
источник
Ваш солутон, похоже, не работает для меня. У меня в основном такая же конфигурация. Это работает для goopen.tk, но не для www.goopen.tk
Alko
3
@Alko, инструкции ответа верны и охватывают эту проблему. При использовании certbotили любого другого инструмента, вы не можете забыть указать свой домен в формате www и не www для работы.
Пауло Коги - Восстановить Монику
Под location /.well-known, вам нужно выйти .well-knownв путь. Используйте alias /var/www/sub.domain.com, неalias /var/www/sub.domain.com/.well-known
Gldraphael
1
Может кто-нибудь объяснить мне, почему вы хотели бы использовать "переписать ^ https: // $ host $ request_uri? Постоянный;" здесь вместо "вернуть 301 https: // $ имя_сервера $ request_uri;"
ZaxLofful
Я обнаружил, что мне нужны цитаты вокруг пути в локации. location '/.well-known' {, Не уверен, что это версия или просто мои настройки, но на случай, если кто-то еще застрянет.
Фрэнк V
2

Да, вы можете использовать в nginxкачестве конечной точки https и сотрудничать с бэкэндами через http. Например мой конфиг:

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

Но, как я знаю, с помощью функции «Зашифровать» вы должны указывать все субдомены при получении сертификата, и если это проблема, тогда вы выбираете URL https://host/serviceвместоhttps://service.host

FGHJ
источник