Назад | Перейти на главную страницу

Что не так с моей конфигурацией обратного прокси nginx с одним сервером (и более поздними версиями)

Я пытаюсь настроить обратный прокси-сервер nginx. У меня настроено два веб-сервера, один с nginx, а другой с apache2. В настоящее время я не могу заставить его работать только с сервером nginx, так что это все, что я пытаюсь сделать прямо сейчас, но я добавил, что в конечном итоге я пытаюсь использовать два, на случай, если это повлияет на настройку.

У меня четыре машины в этой установке.


1. Клиентская машина

192.168.0.5

Ubuntu 14.04 для настольных ПК


2. Обратный прокси-сервер

192.168.0.10

nginx 1.4.6

Сервер Ubuntu 14.04


3. Сервер 1

192.168.0.15

server1.mydomain.com

nginx 1.4.6

Сервер Ubuntu 14.04


4. Сервер 2

192.168.0.20

server2.mydomain.com

apache2

Сервер Ubuntu 14.04


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

/ etc / hosts На клиенте 192.168.0.5 127.0.0.1 localhost 192.168.0.10 server1.mydomain.com 192.168.0.10 server2.mydomain.com

У меня есть ssl-сертификаты для server1 и server2, которые я поставил на обратный прокси-сервер (192.168.0.10). Мы назовем их server1.crt, server1.key и server2.crt, server2.key.

Я считаю, что у меня должна быть такая настройка, чтобы сертификаты работали следующим образом:

client(192.168.0.5) ---https---> reverseProxy(192.168.0.10 holds ssl certs) ---http---> server1 or server2 

У меня сейчас оба сервера работают с http, и мне просто нужно исправить настройки обратного прокси-сервера nginx на 192.168.0.10.

Вот кое-что, что я пробовал, но перенаправление неправильно. Еще раз, я бы хотел https-соединение с обратным прокси-сервером, а затем http-соединение между обратным прокси и серверами.

/etc/nginx/nginx.conf

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # nginx-naxsi config
    ##
    # Uncomment it if you installed nginx-naxsi
    ##

    #include /etc/nginx/naxsi_core.rules;

    ##
    # nginx-passenger config
    ##
    # Uncomment it if you installed nginx-passenger
    ##

    #passenger_root /usr;
    #passenger_ruby /usr/bin/ruby;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

/ и т.д. / nginx / сайты-доступные / по умолчанию

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name localhost;

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            try_files $uri $uri/ =404;
            # Uncomment to enable naxsi on this location
            # include /etc/nginx/naxsi.rules
    }

server {
    listen 443;
    server_name server1.mydomain.com;

    ssl on;
    ssl_certificate /usr/local/nginx/conf/server1.crt;
    ssl_certificate_key /usr/local/nginx/conf/server1.key;
    ssl_session_cache shared:SSL:10m;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;

    location / {
            proxy_pass http://192.168.0.15:80;
            proxy_set_header Host server1;

            proxy_redirect http:// https://;
    }
}

Я предполагаю, что у меня что-то не так /etc/nginx/sites-available/default файл, но я прочитал несколько руководств, и это кажется довольно близким. Эта установка, очевидно, пытается только с server1 и игнорирует server2, но я предполагал, что если бы я мог получить одну работу, я мог бы добавить столько других, сколько хотел. Я нашел похожие вопросы, например этот one, но мне все еще не удалось заставить эту конфигурацию работать с одним сервером.

Что сейчас происходит

В настоящее время, когда я перехожу на server1.mydomain.com, я получаю стандартный "Добро пожаловать в Nginx!" страница с обратного прокси-сервера (192.168.0.10). Пересылки нет.

Я уже близко? заранее спасибо


РЕДАКТИРОВАТЬ1

Попробовав решение, опубликованное Capile, я столкнулся с другой проблемой (которую, возможно, ожидал кто-то с большим знанием Интернета, чем я).

Когда я изменил свой /etc/nginx/sites-available/default файл к этому:

/ и т.д. / nginx / сайты-доступные / по умолчанию (На обратном прокси)

server {

        listen 80 default_server;
        listen 443 ssl default_server;
        server_name server1.mydomain.com;

        ssl on;
        ssl_certificate /usr/local/nginx/conf/server1.com.crt;
        ssl_certificate_key /usr/local/nginx/conf/server1.com.key;
        ssl_session_cache shared:SSL:10m;

        ssl_session_timeout 5m;

        ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
        ssl_prefer_server_ciphers on;

        location / {
                proxy_pass http://192.168.0.15:80;
                proxy_set_header Host server1;

                proxy_redirect http:// https://;
        }
}

С этой конфигурацией я получаю

ошибка 400, неверный запрос

На порт HTTPS был отправлен простой HTTP-запрос.

Я подумал, может мне стоит попробовать https://server1.mydomain.com, но это просто крутится.

Кроме того, я не против использовать один и тот же сертификат ssl для обоих серверов. Не думаю, что это будет проблемой.


РЕДАКТИРОВАТЬ2

Прежде всего, спасибо за помощь.

Я удалил ssl on; линию, как рекомендовано Кэпиле, и изменил proxy_redirect http:// https://; линия к proxy_redirect http:// $scheme://; как рекомендовано Ричардом Смитом.

Это исправило неправильный запрос HTTP-трафика. Итак, если я пойду в http://server1.mydomain.com Меня успешно перенаправили на сайт (ура!)

Если я попытаюсь пойти в https://server1.mydomain.com Меня тоже перенаправили, и это здорово, но я получаю Невозможно подключиться ошибка. Это имеет смысл, если обратный прокси-сервер перенаправляет трафик http на http, а трафик https на https, поскольку для внутреннего сервера нет конфигурации https.

Моя цель - если я пойду http://server1.domain.com что он подключается к обратному прокси с помощью https, а затем перенаправляется на внутренний сервер с помощью http. Похоже, этого не происходит ... похоже, он просто пересылает его, даже не используя https.

С другой стороны, если я пойду в https://server1.domain.com он должен подключиться к обратному прокси с помощью https, а затем перенаправить на внутренний сервер с помощью http.

Поэтому мне никогда не нужно http-соединение от клиента к обратному прокси-серверу.

Однако локоны выглядят так, как ожидалось. Когда я скручиваю сайт http или https, я получаю следующее:

curl -i https://server1.mydomain.com или curl -i http://server1.mydomain.com

HTTP/1.1 302 Found
Server: nginx/1.4.6 (Ubuntu)
Date: Thu, 21 Jan 2016 16:34:29 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 92
Connection: keep-alive
Cache-Control: no-cache
Location: http://test1/users/sign_in
Set-Cookie: session=336e109ad711; path=/; expires=Thu, 28 Jan 2016 16:34:36 -0000; HttpOnly
Status: 302 Found
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: ad65f-f6ds204-9fs8d-bdsdfa43-df5583266sdf87
X-Runtime: 0.005358
X-Xss-Protection: 1; mode=block

<html><body>You are being <a href="http://test1/users/sign_in">redirected</a>.</body></html>

Итак, перенаправление определенно происходит для любого типа соединения, но я не ДУМАЮ, что сертификаты SSL для https-соединения между клиентом и обратным прокси-сервером когда-либо используются.

С новой конфигурацией (EDIT1) любой доступ к машине №2 с использованием http (в отличие от https) будет проксироваться. Что устраняет исходное "Добро пожаловать в nginx!" побочный эффект, который (вероятно) был вызван перенаправлением на схему http.

Двигаясь дальше, я думаю, что корень проблемы - это машина № 3 (настоящий сервер 1), генерирующая перенаправление, которое не отображается правильно к тому времени, когда оно возвращается к клиенту.

Вы можете проверить журналы доступа на машинах №2 и №3, чтобы полностью понять взаимодействие. Возможно, вам придется отрегулировать формат журнала чтобы понять, какая схема используется (http или https) для каждого взаимодействия.

Вы можете временно отключить proxy_redirect так что вы можете использовать инструменты разработчика на клиенте, чтобы точно понять, какие URL-адреса отправляет машина №3 в своих ответах http 3xx.

Ваш proxy_redirect директива неверна для конфигурации EDIT1, поскольку вы сейчас проксируете обе схемы, поэтому это может быть более подходящим:

proxy_redirect http:// $scheme://

Сказав это, более конкретный proxy_redirect может быть уместным. Так как документация состояний, вы можете использовать несколько proxy_redirect rules. I am not an expert onproxy_redirect`, но вы можете получить что-то вроде этого:

proxy_pass http://192.168.0.15;
proxy_set_header Host server1;
proxy_redirect http://192.168.0.15 $scheme://
proxy_redirect http://server1 $scheme://

вы близки, но обратный прокси-сервер для http не настроен, только для https (в приведенной выше настройке), поэтому он должен отображать содержимое по умолчанию из корня документа. На первом сервере также отсутствует концовка }.

Вы можете настроить и http, и https в одном блоке, просто используйте ssl ключевое слово в директиве прослушивания (под ssl-портом, поэтому нет необходимости устанавливать ssl on директива):

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    ...
    ssl_certificate /usr/local/nginx/conf/server1.crt;
    ssl_certificate_key /usr/local/nginx/conf/server1.key;
    ssl_session_cache shared:SSL:10m;
...

Я должен предупредить, что использование двух разных SSL-сертификатов в пределах одного IP-адреса несколько ограничено и сложно - это потому, что для этого потребуется повторное согласование HTTP (поскольку запрос должен быть зашифрован сертификатом перед запросом правильного хоста), поэтому вы, вероятно, необходимо разделить сертификат server блок. Для этого используйте более конкретный, по IP listen:

server {
    listen 192.168.0.10:443 ssl; # for server1.mydomain.com
...

server {
    listen 192.168.0.11:443 ssl; # for server2.mydomain.com
...

Я также рекомендую вам использовать Генератор конфигурации Mozilla SSL для лучших практик безопасности SSL.

РЕДАКТИРОВАТЬ1

Чтобы избежать ошибки 400, просто удалите директиву ssl on; и перезагрузить. Это заставляло http-трафик требовать SSL - вы уже указали, что использовать ssl в строке: listen 443ssldefault_server; (это означает включение ssl на этом порту).

С остальной конфигурацией все в порядке, но в зависимости от ответа вашего сервера вам может потребоваться изменить настройки прокси.

Сначала проверьте, является ли вращение на стороне клиента или на стороне сервера: откройте его с помощью cURL или включите инструменты веб-разработчика в своем браузере и проверьте сеть: если ваш браузер перенаправляется, вам, вероятно, нужно настроить proxy_redirect или даже сделайте некоторые замены строк в ответе вашего сервера.

Проверьте это с помощью cURL:

curl -i http://server1.mydomain.com

Если вы видите Location: Заголовок вашего ответа, вам нужно будет точно настроить параметры прокси (это будет зависеть от ответа). Например, вы можете получить к нему доступ как https, тогда ваш прокси-сервер пересылает его как http, а приложение вашего внутреннего сервера перенаправляет на https (но когда ответ проходит через прокси, он возвращается на http в браузер). Есть несколько способов исправить это, используя proxy_set_header или даже настроить свой внутренний сервер.

Например, вы можете использовать:

proxy_set_header X-Forwarded-Proto $scheme;

Но либо ваш внутренний http-сервер, либо ваше приложение должны это правильно понимать.


В качестве альтернативы, если нет перенаправления, но также нет ответа (или нет ответа шлюза после тайм-аута запроса - 30 секунд), проверьте, правильно ли ваш внутренний сервер отвечает на прокси-сервер.

 

Также обратите внимание, что вам не нужен http-сервер на вашем бэкэнде, вы можете использовать, например, напрямую сервер FastCGI - иногда это имеет меньше недостатков.


РЕДАКТИРОВАТЬ2

Основываясь на ответе cURL, я вижу, что конфигурация работает должным образом - ответ внутреннего сервера просит вас войти в систему. Если бы сертификаты SSL не работали, вы не смогли бы curl -i https://server1.mydomain.com.

Трафик между интерфейсом (прокси) и сервером осуществляется только через http (см. proxy_pass директива), что также обычно ожидается (другое шифрование может добавить ненужные накладные расходы).

Теперь, если вы хотите использовать только https, у вас есть два варианта: либо настроить это в своем бэкэнде (чтобы он перенаправлял вас на https: // test1 / users / sign_in) или используйте другую настройку для nginx, где вы удаляете сервер http: 80 и заставляете его перенаправлять все на https: 443. Что-то вроде этого (обязательно удалите listen 80 из следующего серверного блока):

server {
    listen 80 default;
    server_name  _;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
...