第5章:安全与性能
5.1 基础安全配置
5.1.1 隐藏Nginx版本信息
默认情况下,Nginx会在响应头中显示版本信息,这可能会泄露服务器的版本号,增加安全风险。
配置示例:
http {
# 隐藏Nginx版本信息
server_tokens off;
# ... 其他配置 ...
}验证配置:
curl -I http://localhost预期输出(不包含版本号):
Server: nginx而不是(包含版本号):
Server: nginx/1.18.05.1.2 限制HTTP方法
限制允许的HTTP方法可以防止某些类型的攻击,如PUT、DELETE等可能用于上传恶意文件的方法。
配置示例:
server {
# ... 其他配置 ...
location / {
# 只允许GET、POST和HEAD方法
limit_except GET POST HEAD {
deny all;
}
# ... 其他配置 ...
}
}或使用if指令:
server {
# ... 其他配置 ...
if ($request_method !~ ^(GET|POST|HEAD)$) {
return 405;
}
# ... 其他配置 ...
}验证配置:
# 测试GET方法(应该成功)
curl -I http://localhost
# 测试PUT方法(应该失败)
curl -I -X PUT http://localhost5.1.3 防止常见攻击
5.1.3.1 防止点击劫持(X-Frame-Options)
点击劫持是一种通过iframe嵌入恶意网站,诱使用户点击看似合法的按钮来执行恶意操作的攻击方式。
配置示例:
server {
# ... 其他配置 ...
# 防止点击劫持
add_header X-Frame-Options SAMEORIGIN;
# ... 其他配置 ...
}X-Frame-Options值说明:
DENY:不允许任何网站嵌入当前页面SAMEORIGIN:只允许来自同一域名的网站嵌入当前页面ALLOW-FROM https://example.com:只允许来自特定域名的网站嵌入当前页面
5.1.3.2 防止跨站脚本攻击(X-XSS-Protection)
跨站脚本攻击(XSS)是一种通过注入恶意脚本代码来窃取用户数据的攻击方式。
配置示例:
server {
# ... 其他配置 ...
# 防止XSS攻击
add_header X-XSS-Protection "1; mode=block";
# ... 其他配置 ...
}5.1.3.3 防止MIME类型嗅探(X-Content-Type-Options)
MIME类型嗅探是浏览器尝试通过分析文件内容来确定文件类型的行为,这可能会导致安全问题。
配置示例:
server {
# ... 其他配置 ...
# 防止MIME类型嗅探
add_header X-Content-Type-Options nosniff;
# ... 其他配置 ...
}5.1.3.4 启用严格传输安全(HSTS)
HTTP Strict Transport Security(HSTS)告诉浏览器始终使用HTTPS连接访问网站,防止中间人攻击。
配置示例:
server {
# ... 其他配置 ...
# 启用HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# ... 其他配置 ...
}指令说明:
max-age=31536000:HSTS策略有效期为1年includeSubDomains:HSTS策略适用于所有子域名always:始终添加此头,即使在错误响应中
5.2 SSL/TLS配置
5.2.1 自签名证书生成
在开发和测试环境中,可以使用自签名证书来启用HTTPS。
生成步骤:
生成私钥:
sudo openssl genrsa -out /etc/nginx/ssl/nginx.key 2048生成证书签名请求(CSR):
sudo openssl req -new -key /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.csr按照提示输入证书信息,如国家、组织、域名等。
生成自签名证书:
sudo openssl x509 -req -days 365 -in /etc/nginx/ssl/nginx.csr -signkey /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt验证证书:
sudo openssl x509 -in /etc/nginx/ssl/nginx.crt -text -noout
5.2.2 Let's Encrypt免费证书
在生产环境中,建议使用Let's Encrypt提供的免费、受信任的SSL证书。
安装Certbot:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
# CentOS/RHEL
sudo yum install -y epel-release
sudo yum install -y certbot python3-certbot-nginx获取证书:
sudo certbot --nginx -d example.com -d www.example.com按照提示完成证书获取过程,Certbot会自动更新Nginx配置。
自动续订证书:
Let's Encrypt证书的有效期为90天,建议设置自动续订:
# 添加到crontab
sudo crontab -e添加以下内容:
0 3 * * * certbot renew --quiet这会在每天凌晨3点检查证书是否需要续订。
5.2.3 HTTPS强制跳转
将所有HTTP请求重定向到HTTPS可以确保网站始终使用加密连接。
配置示例:
# HTTP服务器,用于重定向到HTTPS
server {
listen 80;
server_name example.com www.example.com;
# 301永久重定向到HTTPS
return 301 https://$server_name$request_uri;
}
# HTTPS服务器
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL证书配置
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
# ... 其他SSL配置 ...
# ... 其他服务器配置 ...
}5.2.4 性能优化(会话恢复、OCSP装订)
5.2.4.1 SSL会话缓存
启用SSL会话缓存可以减少SSL握手的时间,提高HTTPS连接的性能。
配置示例:
http {
# SSL会话缓存配置
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# ... 其他配置 ...
}5.2.4.2 OCSP装订
OCSP装订(OCSP Stapling)允许服务器在TLS握手时提供证书的在线证书状态协议(OCSP)响应,减少客户端验证证书的时间。
配置示例:
http {
# OCSP装订配置
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# ... 其他配置 ...
}验证OCSP装订:
openssl s_client -connect localhost:443 -status < /dev/null | grep -A 10 "OCSP response"5.3 限速与访问控制
5.3.1 连接数限制
限制每个IP的连接数可以防止DoS攻击,避免服务器资源被单个IP耗尽。
配置示例:
http {
# 定义连接数限制区域
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
# ... 其他配置 ...
server {
# ... 其他配置 ...
location / {
# 限制每个IP的并发连接数为5
limit_conn conn_limit_per_ip 5;
# ... 其他配置 ...
}
}
}5.3.2 请求速率限制
限制每个IP的请求速率可以防止暴力破解和DoS攻击。
配置示例:
http {
# 定义请求速率限制区域
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
# ... 其他配置 ...
server {
# ... 其他配置 ...
location / {
# 限制每个IP的请求速率为10次/秒,允许突发10次请求
limit_req zone=req_limit_per_ip burst=10 nodelay;
# ... 其他配置 ...
}
}
}指令说明:
rate=10r/s:限制速率为10次请求/秒burst=10:允许突发10次请求nodelay:不延迟突发请求
验证配置:
# 使用ab工具测试请求速率限制
ab -n 20 -c 5 http://localhost/预期输出:
- 部分请求会返回429 Too Many Requests状态码
5.3.3 基于IP/地理位置的访问控制
5.3.3.1 基于IP的访问控制
允许或拒绝特定IP地址或IP段访问网站可以限制访问来源,提高安全性。
配置示例:
server {
# ... 其他配置 ...
# 允许特定IP访问,拒绝其他所有IP
location /admin {
allow 192.168.1.100;
allow 10.0.0.0/24;
deny all;
# ... 其他配置 ...
}
# ... 其他配置 ...
}或使用deny指令:
server {
# ... 其他配置 ...
# 拒绝特定IP访问,允许其他所有IP
location / {
deny 192.168.1.200;
allow all;
# ... 其他配置 ...
}
# ... 其他配置 ...
}5.3.3.2 基于地理位置的访问控制
使用ngx_http_geoip_module模块可以基于IP的地理位置进行访问控制,需要安装GeoIP数据库。
配置示例:
http {
# 加载GeoIP数据库
geoip_country /usr/share/GeoIP/GeoIP.dat;
# 定义允许访问的国家
map $geoip_country_code $allowed_country {
default no;
CN yes;
US yes;
}
# ... 其他配置 ...
server {
# ... 其他配置 ...
# 只允许来自中国和美国的访问
if ($allowed_country = no) {
return 403;
}
# ... 其他配置 ...
}
}安装GeoIP数据库:
# Ubuntu/Debian
sudo apt-get install -y geoip-database
# CentOS/RHEL
sudo yum install -y geoip5.4 实战项目:配置安全的Nginx服务器
在这个实战项目中,我们将配置一个安全的Nginx服务器,包含以下功能:
- 隐藏Nginx版本信息
- 限制HTTP方法
- 防止常见攻击
- 配置HTTPS(使用自签名证书)
- 实现HTTPS强制跳转
- 配置SSL会话缓存和OCSP装订
- 限制连接数和请求速率
- 基于IP的访问控制
5.4.1 项目准备
1. 创建SSL证书目录:
sudo mkdir -p /etc/nginx/ssl2. 生成自签名证书:
sudo openssl genrsa -out /etc/nginx/ssl/nginx.key 2048
sudo openssl req -new -key /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.csr -subj "/CN=localhost/O=Test Org/C=CN"
sudo openssl x509 -req -days 365 -in /etc/nginx/ssl/nginx.csr -signkey /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt5.4.2 配置Nginx
1. 创建Nginx配置文件:
sudo nano /etc/nginx/conf.d/secure-nginx.conf2. 添加以下配置:
http {
# 隐藏Nginx版本信息
server_tokens off;
# SSL会话缓存配置
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# OCSP装订配置
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# 连接数限制区域
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
# 请求速率限制区域
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
# HTTP服务器,用于重定向到HTTPS
server {
listen 80;
server_name localhost;
# 301永久重定向到HTTPS
return 301 https://$server_name$request_uri;
}
# HTTPS服务器
server {
listen 443 ssl http2;
server_name localhost;
# SSL证书配置
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
# 现代SSL配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# 安全头配置
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 只允许GET、POST和HEAD方法
if ($request_method !~ ^(GET|POST|HEAD)$) {
return 405;
}
location / {
root /var/www/html;
index index.html;
# 限制连接数和请求速率
limit_conn conn_limit_per_ip 5;
limit_req zone=req_limit_per_ip burst=10 nodelay;
}
# 管理界面,只允许特定IP访问
location /admin {
root /var/www/html;
index admin.html;
# 只允许本地访问
allow 127.0.0.1;
deny all;
}
}
}5.4.3 验证配置
1. 测试配置语法:
sudo nginx -t2. 重载Nginx配置:
sudo systemctl reload nginx3. 验证HTTPS访问:
# 测试HTTP到HTTPS的重定向
curl -I http://localhost
# 测试HTTPS访问
curl -k -I https://localhost4. 验证安全头:
curl -k -I https://localhost | grep -E "X-Frame-Options|X-XSS-Protection|X-Content-Type-Options|Strict-Transport-Security"5. 验证版本信息隐藏:
curl -k -I https://localhost | grep "Server"6. 测试访问控制:
# 测试管理界面访问(应该成功,因为是本地访问)
curl -k https://localhost/admin
# 使用其他IP测试管理界面访问(应该失败)
curl -k -H "X-Forwarded-For: 192.168.1.100" https://localhost/admin5.4.4 常见问题与解决方案
问题1:SSL证书验证失败
解决方案:
确保证书文件路径正确
确保证书和私钥匹配:
openssl x509 -noout -modulus -in /etc/nginx/ssl/nginx.crt | openssl md5 openssl rsa -noout -modulus -in /etc/nginx/ssl/nginx.key | openssl md5两个命令的输出应该相同
对于自签名证书,使用
curl -k或在浏览器中添加例外
问题2:访问控制不生效
解决方案:
- 检查allow/deny指令的顺序,先allow后deny
- 检查IP地址是否正确
- 如果使用了代理,确保获取真实客户端IP:
set_real_ip_from 192.168.1.0/24; real_ip_header X-Forwarded-For;
问题3:限速不生效
解决方案:
- 确保已正确定义limit_conn_zone或limit_req_zone
- 确保limit_conn或limit_req指令在正确的位置
- 检查是否超过了限制的阈值
章节总结
在本章中,我们学习了:
基础安全配置:
- 隐藏Nginx版本信息
- 限制HTTP方法
- 防止常见攻击(点击劫持、XSS、MIME类型嗅探)
- 启用严格传输安全
SSL/TLS配置:
- 生成自签名证书
- 获取Let's Encrypt免费证书
- 实现HTTPS强制跳转
- 优化SSL性能(会话缓存、OCSP装订)
限速与访问控制:
- 限制连接数
- 限制请求速率
- 基于IP的访问控制
- 基于地理位置的访问控制
实战项目:
- 配置安全的Nginx服务器
- 验证安全配置
- 解决常见问题
实践练习
- 隐藏Nginx版本信息
- 配置HTTPS,使用自签名证书
- 实现HTTP到HTTPS的强制跳转
- 配置请求速率限制,限制每个IP每秒10次请求
- 配置基于IP的访问控制,只允许特定IP访问管理界面
- 添加安全头,防止常见攻击
延伸阅读
下一章:第6章:动态内容处理