当一台服务器上部署了网站之后,任何人只要知道你的服务器IP地址,在浏览器里直接输入这个IP,往往就能打开你的站点。这种IP直接访问看起来没什么危害,实际上隐患不少:源站IP一旦暴露,攻击者可以绕过CDN直接攻击源站;别人还能把陌生域名解析到你的IP上,蹭你的服务器资源甚至让你的站点因为违规域名被牵连。本文就来完整讲一下如何通过配置Web服务器,实现只允许域名访问、禁止IP直接访问。

为什么必须禁止IP直接访问
首先要理解HTTP请求里Host头的概念。浏览器访问网站时,无论你输入的是域名还是IP,请求到达服务器后,Web服务器都会拿到一个Host字段。当使用域名访问时,Host是域名本身;使用IP访问时,Host就是那个IP字符串。Web服务器正是根据这个Host来决定把请求交给哪个虚拟主机处理。
如果服务器上没有任何虚拟主机的域名与请求的Host匹配,请求会落到默认站点上。Nginx中默认会把第一个server块作为默认站点,这意味着只要有人随便解析一个域名或者直接用IP访问,你的主站内容就可能被返回给对方。这就是所谓的恶意解析:别人把他的域名A记录指向你的IP,搜索引擎收录了他的域名,你的服务器却在免费给他提供服务。
禁止IP直接访问的核心思路就是:拦截那些Host不是我们域名(也不是我们的IP)的请求,直接返回错误或跳转。这样无论是裸IP访问还是陌生域名解析,都拿不到任何网站内容。
Nginx下的完整配置方法
Nginx是最常见的场景,配置也最简单。做法是新增一个server块,监听80端口,把server_name设为下划线_或者直接写IP,并用default_server标记为默认站点,然后返回444状态码。444是Nginx特有的非标准状态码,含义是不返回任何响应直接断开连接,比返回403更节省资源。
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
# 443端口需要一个证书,哪怕是自签名证书,否则Nginx会启动失败
ssl_certificate /etc/nginx/ssl/default.pem;
ssl_certificate_key /etc/nginx/ssl/default.key;
# 直接断开连接,不返回任何内容
return 444;
}这里有一个非常容易踩的坑需要注意:default_server在一个端口上只能出现一次。如果你机器上已经有别的server块声明了listen 80 default_server,新加的配置会导致Nginx重启报错,提示duplicate default server。排查时可以用nginx -T命令输出完整合并后的配置,搜索一下哪些server块占用了default_server标记,把旧的去掉即可。
另外443端口也建议一并拦截。很多人只在80上做了拦截,结果攻击者直接用https://IP的形式依然能访问。而443端口因为涉及TLS握手,必须提供证书,哪怕是一张自签名证书也行,握手完成后同样return 444。这样裸IP的HTTPS访问也会被掐断。
配置完成后记得用nginx -t检查语法,再执行nginx -s reload平滑重载。验证方法很简单:curl一下IP,如果连接被直接重置,说明配置已经生效。
curl -I http://你的服务器IP # 预期结果:curl: (52) Empty reply from server,说明444生效 curl -I http://你的域名 # 预期结果:返回200或者301,正常响应
Apache与宝塔面板的设置方式
Apache的思路类似,也是靠第一个虚拟主机充当默认站点。在httpd.conf或者vhost配置文件中,把默认虚拟主机的DocumentRoot指向一个空目录,并禁止访问,就能实现拦截效果。
<VirtualHost *:80>
ServerName 默认拦截
DocumentRoot /var/www/html/block
<Directory /var/www/html/block>
Require all denied
</Directory>
</VirtualHost>注意这个拦截用的VirtualHost必须放在所有正常站点配置之前加载,因为Apache会把配置文件中第一个匹配端口的虚拟主机作为默认处理。如果放在后面,别人的请求就会被正常的站点接走。修改后执行systemctl restart httpd或apachectl -k graceful生效。
如果你用的是宝塔面板,操作会简单很多。进入面板后依次打开网站、PHP项目上方的默认站点设置,把默认站点功能开启并选择一个返回阻止页的默认站点(或者直接选择一个空站点),保存后所有未绑定域名的访问、包括裸IP访问,都会被拦截。宝塔底层其实还是Nginx或Apache,只是把这个配置过程图形化了。需要注意的是,开启默认站点拦截后,也要检查SSL证书那一层的默认配置,确保HTTPS的IP访问同样被挡住。
配置后的验证与CDN场景注意事项
配置完成后不要只测一种情况,建议做四组测试:用HTTP方式访问IP、用HTTPS方式访问IP、用绑定的域名访问、再用一个未绑定的域名(可以在本地hosts里把随便一个域名指向服务器IP)访问。理想结果是前两种和最后一种都被拦截或拒绝,只有绑定域名正常打开。如果发现未绑定域名还是能打开网站,多半是default_server没有生效,回头检查配置加载顺序。
使用了Cloudflare等CDN的用户要额外注意:禁止IP直接访问并不能隐藏源站IP,它只能防止别人通过IP看到内容。如果你的源站IP早就通过历史DNS记录、邮件头等渠道泄露过,攻击者依然可以直接打源站。更彻底的做法是在服务器防火墙上只放行CDN厂商的回源IP段,其他IP一律拒绝连接,这样即使别人拿到源站IP也无法访问。两者配合使用,安全效果才完整。
最后提醒一点,某些场景下是不能完全禁止IP访问的,比如服务器上还跑着需要通过IP访问的服务(数据库管理工具、监控面板等),或者有程序用IP做健康检查。这类情况建议按端口区分处理:80和443做拦截,其他端口按需放行,避免拦截配置影响正常业务。