我有一台服务器在代理设置中同时运行Nginx和Apache,Nginx为静态内容和Apache提供了非常好的dynamic内容。
这个设置目前正在托pipe同一个网站的两个版本,可以称之为production.com和staging.com。
我刚刚完成了使用SSL的production.com网站的设置,但也发现,如果我使用SSL浏览到staging.com,则会获得production.com网站根目录的内容,这显然是错误的。
我被告知使用SSL和非SSL的默认处理程序,这将消除这种行为,但这是我有麻烦的地方。
现在我有这个configuration包含在nginx.conf
default_80.conf
server { listen 80; server_name ""; return 444; }
default_443.conf
server { listen 443 default_server ssl; server_name ""; return 444; }
staging.com.conf
server { listen 80; server_name staging.com; access_log /var/log/nginx/staging.com.log; # static content folders location ^~ /(images|css|js) { root /var/www/staging.com/current; access_log /var/log/nginx/staging.com.static.log; } # static content files location ~* \.(js|css|rdf|xml|ico|txt|jpg|gif|png|jpeg)$ { root /var/www/staging.com/current; access_log /var/log/nginx/staging.com.static.log; } # proxy the rest to apache location / { proxy_pass http://127.0.0.1:8080/; proxy_redirect 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; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; } }
production.com.conf
server { listen 80; server_name production.com; rewrite ^ https://$server_name$request_uri? permanent; } server { listen 443 ssl; server_name production.com; access_log /var/log/nginx/production.com.log; ssl_certificate /etc/httpd/conf.d/SSL/ev.crt; ssl_certificate_key /etc/httpd/conf.d/SSL/server.key; keepalive_timeout 60; # static content folders location ^~ /(images|css|js) { root /var/www/production.com/current; access_log /var/log/nginx/production.com.static.log; } # static content files location ~* \.(js|css|rdf|xml|ico|txt|jpg|gif|png|jpeg)$ { root /var/www/production.com/current; access_log /var/log/nginx/production.com.static.log; } # proxy the rest to apache location / { # proxy settings proxy_pass http://127.0.0.1:8080/; proxy_redirect 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; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; } }
这个设置杀死了对这两个站点中任何一个站点的所有types的SSL访问,如果我从default_443.conf中删除了“default_server”指令,它可以用于这两个站点。
所以问题在于,如何closuresstaging.com的SSL访问( https://staging.com返回444)并在production.com上启用它?
最好的问候拉尔斯
首先,确认您的Nginx版本支持SNI,以防您使用其中一个奇怪的发行版(您应该看到顶部启用了TLS SNI支持):
nginx -V
我已经发布了下面的设置,这里是我的框中的结果(/var/www/production/index.html包含PRODUCTION和/var/www/staging/index.html,STAGING)
http://192.168.56.101连接重置(444)
https://192.168.56.101连接重置(444)
http://staging.example.com展示
https://staging.example.comredirect到http
http://production.example.comredirect到https
https://production.example.com生产
作为参考,我使用debian库(0.7.67)中的nginx的稳定版本,但是我有一个非常类似于1.0的设置,其function几乎完全相同。 如果你不能工作,请让我们知道你的确切版本。
在你的情况下,你可能会想要将两个默认值都改为default_server。 你也可能想重写永久的,如果你的nginx版本允许的话,可以把它改成返回301。
在/ etc / nginx的/启用的站点- /默认
server { listen 80 default; return 444; } server { listen 443 default; ssl on; ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; return 444; }
在/ etc / nginx的/启用的站点- /生产
server { listen 80; ## listen for ipv4 server_name production.example.com; rewrite ^ https://production.example.com$request_uri?; } server { listen 443; server_name production.example.com; ssl on; ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; keepalive_timeout 60; location / { proxy_pass http://127.0.0.1:81; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
在/ etc / nginx的/启用的站点- /分期
server { listen 80; server_name staging.example.com; keepalive_timeout 60; location / { proxy_pass http://127.0.0.1:81; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } server { listen 443; ## listen for ipv4 server_name staging.example.com; ssl on; ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; keepalive_timeout 60; rewrite ^(.*) http://staging.example.com$1; }
在/ etc / apache2的/启用的站点- /生产
<VirtualHost *:81> ServerAdmin webmaster@localhost ServerAlias production.example.com DocumentRoot /var/www/production <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/production> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
在/ etc / apache2的/启用的站点- /分期
<VirtualHost *:81> ServerAdmin webmaster@localhost ServerAlias staging.example.com DocumentRoot /var/www/staging <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/staging> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
/etc/apache2/ports.conf
NameVirtualHost *:81 Listen 81
我(在IRC的3molo的帮助下)通过在staging.com中添加ssl的服务器块来重写HTTP来解决这个问题,这在我看来是一个经过批准的解决scheme。
server { listen 443 ssl; server_name staging.com; ssl_certificate /etc/httpd/conf.d/SSL/ev.crt; ssl_certificate_key /etc/httpd/conf.d/SSL/server.key; keepalive_timeout 60; rewrite ^ http://$server_name$request_uri? permanent; }
但问题仍然存在,为什么Nginx在$ http_host和server_name不匹配时提供内容? 如果有人能够回答这个问题,我很乐意听到。
如果staging.com和production.com指向相同的IP地址,则由客户端发送主机标头之前协商的SSL而超出了您的控制范围。
如果可能,请为每个站点使用一个IP,如果没有,则可以在production.com的服务器上下文中“如果$ host = staging.com ..”。