0%

正威網路行銷工作室,專注於基隆、台北與全台客製化網頁設計,提供專業 RWD 響應式、SEO 搜尋引擎優化、品牌形象設計與網站維護託管服務。

搜尋文章
聯絡資訊
地址基隆市仁二路 220 號 5 樓
追蹤我們

禁止用 IP 直接開啟網站:Apache .htaccess 與 Nginx 的設定寫法

如何在Apache中禁用直接IP訪問

網站平常是用網域(例如 www.example.com)開啟的,但網域背後其實對應到一台主機的 IP 位址。如果在瀏覽器直接輸入這個 IP,有時候也能看到你的網站。

這篇說明為什麼要擋掉這種連線,以及 Apache(.htaccess)與 Nginx 的設定方法。

為什麼要擋掉 IP 直接連線?

  • 避免重複內容:同一個網站用網域、用 IP 都能開啟,搜尋引擎有機會把 IP 版本也收錄進去,變成兩個重複的網站。
  • 避免憑證警告:SSL 憑證是發給網域的,用 https:// 加 IP 連線一定會出現「不安全」的警告。
  • 減少掃描流量:很多自動掃描程式是直接一個一個 IP 掃過去,而不是用網域連線。擋掉之後可以少掉不少無意義的請求。
  • 網站前面有 Cloudflare 等 CDN 時:有人直接用主機 IP 連線,就等於繞過了 CDN 的防火牆與快取。

先確認:你的主機需要處理嗎?

  • 共用虛擬主機:一個 IP 上通常放了很多網站,直接輸入 IP 看到的是主機商的預設頁面,不是你的網站。這種情況不需要處理,連線根本不會進到你的網站資料夾,.htaccess 也不會被執行。
  • VPS、雲端主機、獨立主機:一個 IP 只有你的網站時,直接輸入 IP 很可能就會開到你的網站,這時才需要處理。虛擬主機如果有另外購買獨立 IP,情況也一樣。

最簡單的確認方法:在瀏覽器輸入 http://你的主機IP/,看看開出來的是什麼。主機 IP 可以在主機控制台查到。

方法一:用 .htaccess 把 IP 連線轉回網域

適用 Apache、LiteSpeed 主機。放在網站根目錄 .htaccess 的最上面(WordPress 的 # BEGIN WordPress 上面),把 www.example.com 換成你的網域:

Apache (.htaccess)
RewriteEngine On
RewriteCond %{HTTP_HOST} ^[0-9.]+(:[0-9]+)?$ [OR]
RewriteCond %{HTTP_HOST} ^\[
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]
  • 第一個條件:連線用的是 IPv4 位址(例如 203.0.113.10,後面加了連接埠也算)。
  • 第二個條件:連線用的是 IPv6 位址(IPv6 在網址裡會用中括號包起來)。
  • 符合其中一個,就用 301 轉到正式網域。

%{REQUEST_URI} 會帶上完整的路徑,網址參數也會保留,所以 http://203.0.113.10/about/ 會轉到 https://www.example.com/about/。

想直接拒絕,而不是轉址

不想讓 IP 連線看到任何東西,可以直接回應 403 禁止存取:

Apache (.htaccess)
RewriteEngine On
RewriteCond %{HTTP_HOST} ^[0-9.]+(:[0-9]+)?$ [OR]
RewriteCond %{HTTP_HOST} ^\[
RewriteRule ^ - [F]

舊寫法的問題

這篇文章舊版的寫法是:

Apache (.htaccess)
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www.example.com
RewriteRule (.*) https://www.example.com$1 [R=301,L]

意思是「只要網址不是 www.example.com,就轉到 www.example.com」,概念沒錯,但有兩個問題:

  1. 少了斜線:放在 .htaccess 裡時,(.*) 抓到的路徑開頭沒有斜線,/about/ 會被轉成 https://www.example.comabout/ 這種錯誤網址。要寫成 https://www.example.com/$1,或改用 %{REQUEST_URI}。
  2. 沒有處理 https:網址已經是 www.example.com 時不會轉,所以 http 的連線還是停在 http。

如果你的目的就是「不管用什麼網址連進來,一律統一成同一個網址」,可以用這個修正後的版本,同時處理 IP、沒有 www 的網址與 https:

Apache (.htaccess)
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [L,R=301]

要注意,同一個資料夾如果還有其他網域或測試用的子網域指過來,也會全部被轉走。網站前面有 Cloudflare 等 CDN 時,判斷 https 的方式不同,請看.htaccess 強制 HTTPS 寫法。

已經用了自動抓網域的寫法?

.htaccess 用法大全裡「統一網址」的寫法會自動抓網域名稱,不用改成自己的網址,但遇到 IP 連線時,會轉到 https://www.203.0.113.10/ 或 https://203.0.113.10/ 這類不存在、或會出現憑證警告的網址。

解決方法是把本篇方法一的 IP 規則放在它的前面。IP 連線會先被轉走(或拒絕),就不會跑到後面的規則。

方法二:Apache 設定預設虛擬主機(VPS)

有權限修改 Apache 設定檔的話,比較乾淨的做法是設一個「預設虛擬主機」,專門接收網域對不上的連線。

Apache 收到的網址如果沒有對應到任何網站的 ServerName 或 ServerAlias,會交給第一個載入的虛擬主機處理,所以這段設定要排在所有網站的前面(Ubuntu、Debian 上可以放在檔名排序最前面的 000-default.conf):

Apache (.htaccess)
<VirtualHost *:80>
    ServerName default.invalid
    <Location "/">
        Require all denied
    </Location>
</VirtualHost>

修改後先檢查語法,再重新載入 Apache:

Shell / 終端機
sudo apachectl configtest
sudo systemctl reload apache2

CentOS、Rocky Linux 等系統的服務名稱是 httpd。HTTPS(443 埠)的預設虛擬主機也需要一張憑證才能設定,比較複雜,不熟悉的話請主機商或系統管理員協助。

方法三:Nginx 主機

Nginx 不讀 .htaccess。在 Nginx 設定裡加一個 default_server,網域對不上的連線一律直接關閉:

Nginx
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 444;
}

444 是 Nginx 專用的代碼,意思是不回應任何內容、直接關閉連線。

HTTPS 的部分,較新版本的 Nginx 可以用 ssl_reject_handshake 在加密連線建立時就直接拒絕,不需要另外準備憑證:

Nginx
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;
    ssl_reject_handshake on;
}

同一個連接埠只能有一個 default_server。如果其他設定檔(例如系統內建的 default)已經有 default_server,要先拿掉,不然會出現重複的錯誤。修改後先執行 sudo nginx -t 檢查語法,再執行 sudo systemctl reload nginx。

設好之後怎麼測試?

  • 瀏覽器輸入 http://你的主機IP/:應該轉到正式網域,或出現禁止存取、無法連線。
  • 正式網域要照常能開,網站裡的頁面也多點幾頁確認。
  • 有終端機的話,可以用 curl 看主機的回應:
Shell / 終端機
curl -I http://203.0.113.10/

設定成轉址的話,會看到 301 以及 Location: https://www.example.com/。

延伸閱讀

主機設定改錯一行,整個網站就可能打不開,動手前一定要先備份。正威網路行銷是 25 年經驗的基隆網頁設計工作室,也提供網站維護託管,主機與網址設定的問題歡迎來聊聊。

分享這篇文章

返回文章列表更多「html網頁語法教學」文章

發表留言

還沒有人留言,歡迎第一個分享你的想法或問題。留言經審核後才會顯示,Email 不會公開。

讓我們一起打造
您的專屬網站!