Debian上具有TLS/SSL的Apache2(LAMP)的Nginx反向代理
安装并配置Nginx以通过TLS连接充当Apache的反向代理。
涵盖了Nginx,Apache和PHP配置。
通常,Nginx反向代理位于Apache端,它将缓存来自Web服务器的所有静态答案,并从其缓存中回复客户端。
Nginx用于Apache的好处,以减少其负载。
准备工作
Nginx和Apache将配置为仅支持TLSv1,TLSv1.1和TLSv1.2.
SSLv2和SSLv3将被禁用。
将启用以下SSL密码:
ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-SHA384 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA ECDHE-ECDSA-AES256-SHA ECDH-RSA-AES256-GCM-SHA384 ECDH-ECDSA-AES256-GCM-SHA384 ECDH-RSA-AES256-SHA384 ECDH-ECDSA-AES256-SHA384 ECDH-RSA-AES256-SHA ECDH-ECDSA-AES256-SHA DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA256 DHE-RSA-AES256-SHA ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES128-SHA ECDHE-ECDSA-AES128-SHA DHE-RSA-CAMELLIA256-SHA DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES128-SHA256 DHE-RSA-AES128-SHA DHE-RSA-SEED-SHA DHE-RSA-CAMELLIA128-SHA
Apache将配置为在端口8080上侦听HTTP,在端口8081上侦听HTTPS。
Nginx将使用默认的HTTP和HTTPS端口。
由于Mediawiki和WordPress,已安装完整的LAMP堆栈。
请注意,Mediawiki和WordPress的安装不在本文讨论范围之内。
如果不需要,可以随意删除MySQL和PHP。
假定:
- 默认位于'/var/www /'下。
- Mediawiki安装在'/var/www/wiki /'下。
- WordPress安装在'/var/www/wordpress /'下。
同样,在我们的例子中,'/var/www'被安装在带有noexec,nodev和nosuid的单独的加密分区上:
$mount -l | grep www /dev/mapper/data on /var/www type ext4 (rw,nosuid,nodev,noexec,relatime,user_xattr,barrier=1,data=ordered) [data]
- noexec:不要在该分区上设置任何二进制文件的执行(防止二进制文件的执行,但允许脚本执行)。
- nodev:不允许在此分区上使用字符或者特殊设备。
- nosuid:请勿在此分区上设置SUID/SGID访问(防止setuid位)。
安装
Apache2 + OpenSSL
# apt-get install --no-install-recommends apache2 openssl
MySQL + PHP5(可选)
# apt-get install --no-install-recommends mysql-server php5 libmysqld-dev \ libmysqlclient-dev php5-common php-pear php5-cli php5-curl php5-fpm php5-gd \ php5-mysql php-apc libapache2-mod-php5
Nginx的
仅在完成Apache2的配置后才安装Nginx,否则最终将有两个Web服务器争夺端口80。
# apt-get install nginx
使用HTTPS配置Apache
禁用默认。
我们将使用“ httpd.conf”定义虚拟主机。
# a2dissite default
生成并安装自签名SSL证书
我们希望通过安全的TLS/SSL连接推送所有内容。
# mkdir /etc/ssl/webserver && cd /etc/ssl/webserver
生成自签名证书:
# openssl req -x509 -days 1825 -sha256 -nodes -newkey rsa:2048 \ -keyout ./server.key -out ./server.crt
使私钥只能由root用户读取:
# chmod 0600 ./server.key
启用Apache重写和SSL模块
# a2enmod rewrite ssl
/etc/apache2/conf.d/security的配置
服务器的签名已启用,因此我们可以分辨出有哪些链接的服务器实际上产生了返回的错误消息。
ServerTokens设置为prod,以防止在线显示Apache的版本。
ServerSignature on ServerTokens prod TraceEnable off Header unset ETag FileETag None #Header always append X-Frame-Options SAMEORIGIN #Header set X-Content-Type-Options nosniff #Header set X-XSS-Protection "1; mode=block" Header edit Set-Cookie ^(.*)$;HttpOnly;Secure #Header set Content-Security-Policy "default-src 'self';"
上面的配置要求启用标头模块:
# a2enmod headers
/etc/apache2/ports.conf的配置
在端口8080上侦听HTTP请求,在端口8081上侦听HTTPS请求。
NameVirtualHost *:8080 Listen 8080 <IfModule mod_ssl.c> Listen 8081 </IfModule> <IfModule mod_gnutls.c> Listen 8081 </IfModule>
/etc/apache2/httpd.conf的配置
确保https.conf包含在'/etc/apache2/apache2.conf'中。
ServerName example.com
<VirtualHost *:8080>
ServerAdmin Hyman@theitroad
#rewrite HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:8081>
ServerAdmin Hyman@theitroad
SSLEngine on
SSLCertificateFile /etc/ssl/webserver/server.crt
SSLCertificateKeyFile /etc/ssl/webserver/server.key
#ALL is a shortcut for "+SSLv2 +SSLv3 +TLSv1 +TLSv1.1 +TLSv1.2"
#when using OpenSSL 1.0.1 and later
SSLProtocol ALL -SSLv2 -SSLv3
SSLVerifyClient none
SSLVerifyDepth 1
SSLHonorCipherOrder On
#SSLLabs.com suggestion
SSLCipherSuite EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:ECDH+AES256:DH+AES256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:EDH+aRSA:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
DocumentRoot /var/www
<Directory
Options FollowSymLinks -Indexes
AllowOverride All
Order Allow,Deny
Allow from all
SSLRequireSSL
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
检查Apache配置文件中的语法错误
# apachectl configtest Syntax OK
显示虚拟主机配置
# apachectl -t -D DUMP_VHOSTS VirtualHost configuration: wildcard NameVirtualHosts and _default_ servers: *:8081 example.com (/etc/apache2/httpd.conf:14) *:8080 is a NameVirtualHost default server example.com (/etc/apache2/httpd.conf:3) port 8080 namevhost example.com (/etc/apache2/httpd.conf:3) Syntax OK
重新启动Apache
# service apache2 restart
配置PHP(可选)
为临时HTTP上传文件以及php会话创建非世界可写目录:
# mkdir -p -m 0750 /var/www/php_dir/temp # mkdir -p -m 0750 /var/www/php_dir/session # chown -R www-data:www-data /var/www/php_dir
如果我们使用的是PHPMyAdmin,则出现以下错误:
Cannot start session without errors, please check errors given in your PHP and/or webserver log file and configure your PHP installation properly.
我们可能需要这样的东西:
# chmod 1777 /var/www/php_dir/session
打开“ /etc/php5/apache2/php.ini”并适当修改以下设置(仅用作指导):
[PHP] engine = On disable_functions = exec,system,shell_exec,passthru open_basedir = Off expose_php = Off max_execution_time = 600 max_input_time = 600 memory_limit = 256M display_errors = Off display_startup_errors = Off track_errors = Off html_errors = Off error_log = "/var/log/php-errors.log" register_globals = Off post_max_size = 32M magic_quotes_gpc = Off file_uploads = On upload_tmp_dir = "/var/www/php_dir/temp" upload_max_filesize = 16M max_file_uploads = 5 allow_url_fopen = Off allow_url_include = Off [Date] date.timezone = "Europe/London" [Session] session.save_path = "/var/www/php_dir/session"
将Nginx配置为反向代理
“ /etc/nginx/nginx.conf”文件的配置如下所示。
如我们所见,我们的双核Debian服务器配置为一次提供约1024个连接(2个工作进程* 512个连接)。
user www-data;
worker_processes 2;
pid /var/run/nginx.pid;
events {
worker_connections 512;
}
http {
#BASIC SETTINGS
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 30;
types_hash_max_size 2048;
server_tokens off;
#LOGGING SETTINGS
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
#GZIP SETTINGS
gzip on;
gzip_buffers 16 8k;
gzip_comp_level 2;
gzip_min_length 1024;
gzip_http_version 1.1;
gzip_proxied any;
gzip_types application/x-javascript text/css text/plain text/javascript;
#VIRTUALHOST SETTINGS
server {
listen 80;
server_name example.com www.example.com;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location ~ \.php${
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;
proxy_pass http://localhost:8080;
}
#this is mainly for Mediawiki
#as Mediawiki URLs look like: http://example.com/wiki/index.php/blablabla
#we have to be sure that all these URLs get redirected to Apache
#thanks to: http://forum.nginx.org/read.php?2,215093,215095#msg-215095
location /wiki/index.php {
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;
proxy_pass http://localhost:8080;
}
#Nginx should serve all files except the php ones
location/{
root /var/www;
index index.html index.php;
}
location ~ /\.ht {
deny all;
}
}
server {
listen 443 ssl;
server_name example.com www.example.com;
access_log /var/log/nginx/ssl_access.log;
error_log /var/log/nginx/ssl_error.log;
ssl on;
ssl_certificate
/etc/ssl/webserver/server.crt;
ssl_certificate_key /etc/ssl/webserver/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
#add_header Strict-Transport-Security max-age=15552000;
#add_header Content-Security-Policy "default-src 'self';
#add_header Public-Key-Pins 'pin-sha256="";max-age=300''
#SSLLabs.com suggestion
ssl_ciphers EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:ECDH+AES256:DH+AES256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:EDH+aRSA:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
ssl_prefer_server_ciphers on;
location ~ \.php${
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;
proxy_pass https://localhost:8081;
}
location /wiki/index.php {
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;
proxy_pass https://localhost:8081;
}
#Nginx should serve all files except the php ones
location/{
root /var/www;
index index.html index.php;
}
location ~ /\.ht {
deny all;
}
}
}
重新启动Nginx
# service nginx restart
配置iptables
# iptables -A INPUT -p tcp -m multiport --dport 80,443 -j ACCEPT
在SSLLabs上测试SSL服务器
免费的在线测试服务:https://www.ssllabs.com/ssltest

