Nginx配置问题:如何禁止通过服务器IP直接访问站点?
问题分析
你的配置里导致IP访问跳转到主域名的核心原因有两个:
- 80端口的默认服务器被主域名跳转逻辑接管:当前80端口的
server块标记了default_server,且server_name是example.net www.example.net。当用IP访问80端口时,Nginx会命中这个默认服务器,执行最后的return 301 https://example.net$request_uri,直接跳转到主域名。 - 443端口无专属默认服务器:当用IP访问443端口时,Nginx会自动匹配第一个定义的443
server块(即app.example.net的配置),虽然里面有if ($host !~ ^(app.example.net)$ )返回444,但如果浏览器缓存了之前的跳转记录,或者测试时未清除缓存,可能导致看起来没生效;更关键的是,没有专门的443默认服务器兜底,逻辑不严谨。
另外,你现有配置里的if ($http_host != $server_name)和重复的$host匹配判断属于冗余逻辑,且Nginx的if指令存在优先级问题,容易引发意外行为,建议移除。
解决步骤
1. 生成自签SSL证书(用于443默认服务器)
因为Nginx的443端口必须配置SSL证书才能启动,所以先生成一个自签证书用于兜底的默认服务器:
mkdir -p /etc/nginx/ssl openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/default.key -out /etc/nginx/ssl/default.crt
执行过程中按提示填写信息即可,无需严格匹配域名。
2. 修改Nginx配置
替换原有配置为以下内容,核心是新增80和443端口的专属默认服务器,专门处理IP访问:
# 80端口默认服务器:处理IP访问,直接返回444关闭连接 server { listen 80 default_server; listen [::]:80 default_server; server_name _; return 444; } # 443端口默认服务器:处理IP访问,直接返回444关闭连接 server { listen 443 ssl default_server; listen [::]:443 ssl default_server; server_name _; ssl_certificate /etc/nginx/ssl/default.crt; ssl_certificate_key /etc/nginx/ssl/default.key; return 444; } # app server configuration server { root /var/www/html; server_name app.example.net; location / { proxy_pass http://external_server_ip:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_cache_bypass $http_upgrade; } if ($http_id = '') { return 401; } listen [::]:443 ssl http2; # managed by Certbot listen 443 ssl http2; # managed by Certbot ssl_certificate /etc/letsencrypt/live/app.example.net/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/app.example.net/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } map $sent_http_content_type $expires { default off; ~text/css 30d; ~application/javascript 30d; ~image/ 30d; } # Default server configuration server { root /var/www/html; server_name example.net www.example.net; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_cache_bypass $http_upgrade; limit_except GET HEAD POST { deny all; } } ## Block download agents ## if ($http_user_agent ~* LWP::Simple|BBBike|wget|zgrab|WebSucker01h4x.com|360Spider|404checker|404enemy|80legs|ADmantX|AIBOT|ALittle\ Client|ASPSeek|Go-Ahead-Got-It|GoZilla|Gotit|GrabNet|Grabber|Grafula|Niki-bot|Nikto|NimbleCrawler|Nimbostratus|Ninja|Nmap|Xaldon_WebSpider|Xenu|YoudaoBot|Zade|Zauba|Zermelo|Zeus|Zitebot|ZmEu|seocompany.store|seoscanners|seostar|serpstatbot|sexsearcher|sitechecker.pro|siteripz|sogouspider|sp_auditbot|spyfu|sysscan|tAkeOut|trendiction.com|trendiction.de|ubermetrics-technologies.com|voyagerx.com|webgains-bot|webmeup-crawler|webpros.com|webprosbot|x09Mozilla|x22Mozilla) { return 403; } ## Deny certain Referers ### if ( $http_referer ~* (seo|referrer|redirect|babes|click|girl|jewelry|love|organic|poker|porn|sex|teen|video|webcam) ) { return 403; } # deny access to .htaccess files location ~ /\.ht { deny all; } # Deny access to hidden files (beginning with a period) location ~ /\. { deny all; } expires $expires; listen [::]:443 ssl http2; # managed by Certbot listen 443 ssl http2; # managed by Certbot ssl_certificate /etc/letsencrypt/live/example.net/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/example.net/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } # 80端口主域名跳转:仅处理example.net和www.example.net的http转https server { if ($host = www.example.net) { return 301 https://example.net$request_uri; } if ($host = example.net) { return 301 https://example.net$request_uri; } listen 80; listen [::]:80; server_name example.net www.example.net; return 301 https://example.net$request_uri; }
3. 验证并重启Nginx
nginx -t systemctl restart nginx
关键说明
- 新增的两个默认服务器块会优先处理所有IP访问(无论80还是443端口),直接返回444关闭连接,不会触发任何跳转。
- 原有的主域名和子域名配置仅处理对应域名的请求,逻辑更清晰。
- 移除了冗余的
$host匹配判断,避免Nginxif指令的优先级问题。
内容的提问来源于stack exchange,提问作者Oleksii Sinkov
相关产品推荐
相关产品推荐

