У меня странная проблема с поддоменами nginx. Во-первых, моя конфигурация:
server {
listen 443 ssl;
server_name secure.example.com;
ssl_certificate example.crt;
ssl_certificate_key example.key;
keepalive_timeout 70;
location / {
fastcgi_pass 127.0.0.1:8000;
...
}
}
server {
listen 80;
server_name example.com www.example.com;
location / {
fastcgi_pass 127.0.0.1:8000;
...
}
}
Идея в том, что у меня есть защищенный домен, secure.example.com
и нормальный домен, example.com
. На практике я могу перейти на https://example.com
и http://secure.example.com
. Я обошел вторую проблему с промежуточным сервером:
server {
listen 80;
server_name secure.example.com;
rewrite ^(.*) https://secure.example.com$1 permanent;
}
Но это не оптимальное решение, и мне пришлось бы создать еще один, чтобы перенаправить https с tld на поддомен. Я чувствую, что, должно быть, делаю что-то не так, если мне нужно несколько таких серверов. Почему https://example.com
работают, когда там нет слушающего сервера на 443? Разве он не должен просто не подключиться? Я немного запутался.
Почему
https://example.com
работают, когда там нет слушающего сервера на 443? Разве он не должен просто не подключиться?
В server_name
(или, точнее, заголовок HTTP / 1.1 Host) оценивается после установления соединения по 80 / tcp (HTTP) или 443 / tcp (HTTPS). Это означает, что если secure.example.com
и example.com
имеют одну и ту же запись ресурса A (они указывают на один и тот же IP-адрес), невозможно определить, какой виртуальный хост хочет видеть клиент до того, как соединение будет установлено и заголовок HTTP / 1.1 Host не был отправлен.
Еще точнее TCP / IP работает с IP-адресами (часть IP) и портами (часть TCP). Поэтому, если вы привязываете процесс (например, nginx) к определенному IP-адресу и порту, он всегда будет отвечать на этом сокете, а TCP / IP ничего не знает о HTTP / 1.1 и его заголовке Host.
Если вы хотите оптимизировать конфигурацию nginx, вы можете написать следующее:
server {
listen 443 ssl;
listen 80;
server_name secure.example.com;
ssl_certificate example.crt;
ssl_certificate_key example.key;
keepalive_timeout 70;
if ($scheme = http) {
rewrite ^(.+)$ https://example.com$1 redirect;
}
location / {
fastcgi_pass 127.0.0.1:8000;
# ...
}
}
server {
listen 80;
server_name example.com www.example.com;
location / {
fastcgi_pass 127.0.0.1:8000;
# ...
}
}
Взгляните на Nginx документация server_name. Он говорит, что если в вашем списке виртуальных хостов нет совпадений, nginx будет использовать первый сервер {} блок с соответствием Слушать директива.
Если вы хотите заставить пользователей использовать secure.example.com принимать с https, у вас может быть тот же способ обхода, который вы использовали для противоположного случая.