Ubuntu服务器上配置反向代理时,很多人只关注“能不能转发”,却忽略了代理层本身暴露的攻击面。代理服务器直接面向公网,一旦配置不当,轻则泄露内网结构,重则被用作跳板攻击后端服务。真正需要解决的问题集中在几个点:如何隐藏后端真实信息、如何控制访问来源、如何防止代理被滥用、以及如何让HTTPS终止在代理层而不影响后端性能。
先明确一个基本事实:反向代理的安全配置不是单一指令,而是一组策略的组合。Nginx作为Ubuntu上最常见的反向代理软件,默认配置并不适合直接暴露在生产环境。你需要从响应头、访问控制、超时限制、缓冲区策略、TLS参数、日志审计等维度逐项收紧。下面按实际部署顺序展开。
隐藏后端服务指纹默认情况下,Nginx会通过Server响应头暴露版本号,攻击者可以据此查找对应版本的已知漏洞。在nginx.conf的http块中加入server_tokens off,可以隐藏版本信息。但这还不够,后端应用如果直接返回自己的Server头,比如Apache或Tomcat,代理层必须覆盖它。在location块中使用proxy_hide_header Server,再通过add_header Server "nginx"设置一个无意义的通用值,能有效干扰自动化扫描工具。
另一个容易被忽略的细节是错误页面。Nginx默认的502、504错误页会包含nginx版本和模块信息,建议用自定义错误页替换。配置error_page 502 503 504 /custom_50x.html,并确保该文件只包含静态内容,不暴露任何技术栈线索。
限制代理请求的目标范围反向代理最常见的滥用方式是SSRF,攻击者尝试让代理服务器请求内网地址或云元数据服务。必须在proxy_pass中强制使用固定的upstream名称,而不是直接拼接用户输入。如果业务上必须动态指定目标,也要在server块中设置严格的白名单校验,例如只允许转发到特定内网网段,并拒绝包含localhost、169.254.169.254、127.0.0.1等敏感地址的请求。
对于使用变量拼接proxy_pass的场景,建议增加一层map指令做地址过滤。例如:
map $http_host $backend_allowed {
default 0;
~^api\.example\.com$ 1;
}
在location中判断该变量,不允许的值直接返回403。这能有效阻断通过修改Host头发起的代理滥用。
收紧请求头和请求体限制代理层必须限制客户端请求体大小,防止大体积恶意上传耗尽后端资源。使用client_max_body_size设置一个合理上限,例如10m。同时设置client_body_timeout和client_header_timeout,避免慢速连接长时间占用worker进程。对于反向代理场景,还应该显式设置proxy_read_timeout和proxy_send_timeout,避免后端响应缓慢导致连接堆积。
请求头过滤同样关键。默认Nginx会透传大多数客户端请求头,但有些头不应该被后端信任,比如X-Forwarded-For。如果后端应用依赖这个头做IP判断,攻击者可以伪造它绕过访问控制。正确做法是在代理层用proxy_set_header X-Real-IP $remote_addr覆盖,并用proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for重新生成,确保值只来自代理层计算,而不是直接透传客户端输入。
配置严格的访问控制如果反向代理只服务于特定业务,建议在server或location级别做IP白名单。使用allow和deny指令,只放行CDN回源地址或办公网出口。对于需要对外开放的接口,至少要对管理路径、健康检查路径做额外限制。例如/admin、/actuator、/server-status这类路径,必须拒绝公网访问或要求额外认证。
针对爬虫和自动化攻击,可以在代理层启用限速。limit_req_zone和limit_conn_zone分别控制请求频率和并发连接数。反向代理场景下,对单个IP设置每秒10个请求的限制通常足够正常用户使用,同时能显著降低暴力扫描和撞库行为的影响。配置时注意burst参数的设置,过小会误伤正常突发流量。
强化TLS与HTTPS终止反向代理承担HTTPS终止任务时,TLS配置直接决定传输层安全水平。Ubuntu上使用OpenSSL,建议只启用TLS1.2和TLS1.3,禁用所有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'; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d;
同时启用HSTS头,强制浏览器只通过HTTPS访问。add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always。注意该头只在HTTPS响应中生效,不要在HTTP端口返回。
证书管理方面,Ubuntu上推荐使用certbot自动续期。但自动续期后需要重载Nginx,建议用systemd timer配合nginx -s reload,避免证书过期导致服务中断。私钥文件权限必须设为600,属主为root,防止其他进程读取。
缓冲区与响应头安全策略Nginx作为代理时,默认会缓冲后端响应。对于大文件下载或流式接口,需要调整proxy_buffering、proxy_buffer_size和proxy_buffers参数。但关闭缓冲会带来风险,因为后端慢速响应会长时间占用代理连接。建议保持缓冲开启,只对特定大文件路径关闭。
响应头安全策略在代理层统一设置比在后端逐个配置更可靠。推荐添加以下头:
add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options SAMEORIGIN always; add_header Referrer-Policy strict-origin-when-cross-origin always; add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
注意add_header的继承规则:如果location中定义了任何add_header,会覆盖server级的全部add_header。因此要么统一在server级设置,要么在需要自定义的location中重复完整列表。
日志与实时监控安全配置的最后一环是可见性。反向代理日志必须记录足够的字段用于事后分析。建议使用自定义log_format,包含客户端真实IP、请求耗时、后端响应时间、请求头中的User-Agent和Referer、以及upstream地址。对于POST请求,不要记录请求体,避免敏感数据落入日志文件。
日志轮转使用Ubuntu自带的logrotate,保留至少30天。同时建议配置fail2ban监控Nginx错误日志,对频繁触发400、403、404或502的IP自动封禁。规则可以针对特定路径的扫描行为,例如对/wp-admin、/.env、/config.php的请求,一旦命中立即拉黑。
最后强调一点:反向代理的安全配置不是一次性工作。每次后端服务变更、每次Nginx升级、每次新增业务路径,都需要重新审视代理规则。建议将Nginx配置文件纳入版本控制,定期用nginx -t做语法校验,并用外部扫描工具模拟攻击路径验证防护效果。只有把代理层当作独立的安全边界来维护,才能真正发挥它在架构中的隔离作用。
