Debian上具有TLS/SSL的Apache2(LAMP)的Nginx反向代理

时间:2020-03-21 11:47:36  来源:igfitidea点击:

安装并配置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