背景

最近突发奇想,怎么让基于Apache服务的网站只能通过域名访问?也就是说,在浏览器地址栏直接输入IP就不允许访问。这样有个好处就是,必须是知道域名的用户才能访问网站内容,如果只是通过某种方式捕获到IP,不让他知道网站运行着什么内容。

基础

我的服务器环境是Ubuntu 16.04,其他版本的系统也差不多,只要是Apache 2.x版本就行。并且,网站支持了HTTPS访问。

首先,确保Apache服务器已经启用了 mod_rewrite 模块:

1
2
3
sudo a2enmod rewrite
# 重启Apache服务
sudo systemctl restart apache2

配置

接下来,我们就通过修改配置来实现需求。先找到配置文件:

1
cd /etc/apache2/sites-available/

此目录下一般有 000-default.confdefault-ssl.conf 这两个文件,因为支持了HTTPS,所以我们直接修改后者:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin your-email@example.com
ServerName your-domain.com
DocumentRoot /var/www/html

SSLEngine on
SSLCertificateFile /path/to/your_certificate.crt
SSLCertificateKeyFile /path/to/your_private.key
SSLCertificateChainFile /path/to/your_chainfile.pem

# 上面都是示例,重点关注下面这几行
RewriteEngine on
RewriteCond %{HTTP_HOST} ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$
RewriteRule ^(.*)$ - [F]
</VirtualHost>
</IfModule>

大家的其他配置基本都差不多,主要是追加最后那3行配置,其作用是检查HTTP请求的主机头是否是IP地址(由数字和点组成),如果是,则返回403 Forbidden响应,从而阻止通过IP地址访问网站

顺便也贴一下我的非HTTPS配置(即 000-default.conf ),这样完整一点:

1
2
3
4
5
6
7
8
9
10
11
12
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

# 上面都是示例,重点关注下面这几行
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

配置搞定以后,再次重启一下Apache服务。

测试

此时再尝试用IP访问网页,浏览器就会出现403错误信息:

Forbidden

You don’t have permission to access this resource.


Apache/2.4.18 (Ubuntu) Server at 123.123.123.123 Port 443

这样就对了。