把網域指向你的 VPS:A 記錄、AAAA、TTL 與名稱伺服器
手上有網域和 VPS 的 IP,今晚就能接起來。A 與 AAAA 記錄怎麼填、裸網域為什麼不能用 CNAME、搬機前後怎麼調 TTL,還有 Cloudflare 橘色雲朵開著時要注意的事。
把網域指向你的 VPS:最短的路徑
把網域指向你的 VPS,要做的事只有一件:在管理該網域的 DNS 面板上新增一筆 A 記錄,名稱欄填 @,類型選 A,值填 VPS 的公用 IPv4 位址,TTL 先設 300 秒。存檔,等舊的快取過期,然後用 dig +short A example.com 確認回來的就是你那一組位址。這樣就完成了。
下面的篇幅幾乎都在講另一件事:為什麼你明明填了,網站卻還是打不開。卡住的地方通常不是觀念,而是面板上那幾個欄位的名字,以及「你編輯的那份設定根本沒有人在讀」。
動手之前先把兩樣東西放在手邊。第一是 VPS 的公用位址,在機器上跑 curl -4 https://ifconfig.me 或 ip -4 addr show 都拿得到。要注意不要拿到 10. 、172.16. 到 172.31. 、192.168. 開頭的位址,那些是內網位址,外面連不進來,填進 DNS 之後全世界都會連到自己家的路由器。第二是「現在是誰在回答這個網域的查詢」,這比「網域在哪裡買的」重要得多。
改名稱伺服器和改一筆記錄是兩件不同的事
網域有兩層設定,很多人把它們混在一起,於是改了半天沒有反應。
第一層在註冊商(registrar),也就是你付錢續約的地方。那裡設定的是網域的委派(delegation):這個網域交給哪一組名稱伺服器(NS,name server)回答。改這個,等於把整份區域檔(zone)換一家管。
第二層在那組名稱伺服器所屬的 DNS 供應商面板。那裡編輯的是區域檔裡的一筆一筆記錄:A、AAAA、CNAME、MX、TXT。改這個,只影響你動到的那個名字。
兩者壞掉的症狀不一樣。委派設錯,是整個網域一起壞,連 dig NS example.com 都拿不到正確答案。單筆記錄填錯,是只有那一個名字壞,其他子網域照常。
最常見的死路是這樣:網域在 GoDaddy 買,但名稱伺服器已經改指到 Cloudflare,人卻回到 GoDaddy 的 DNS 面板加 A 記錄。GoDaddy 那份區域檔還在,只是全世界沒有任何解析器會去問它。先跑這一行確認你該去哪一家面板:
dig +short NS example.com回來的那幾台主機名,屬於哪一家供應商,你就要在哪一家的面板編輯記錄。Windows 使用者用 nslookup -type=NS example.com 也可以。
還有一個時間差要先知道:頂層網域(例如 .com 或 .tw)給出的委派記錄,TTL 通常是 172800 秒,也就是兩天。所以換名稱伺服器要等的時間,比改一筆記錄久得多。如果你今晚就要上線,不要在今晚換 NS,改現有那組的記錄就好。
面板上那四個欄位到底要填什麼
不管哪一家,新增記錄的表單都是同樣四個欄位,只是叫法不同。
- 主機名稱 / 名稱 / Name / Host:這個記錄的名字。填
@代表裸網域本身(apex,也就是 example.com)。有些面板是留空白代表裸網域。填www代表 www.example.com。 - 類型 / Type:A、AAAA、CNAME、TXT 這些。
- 指向的值 / 內容 / 資料 / Value / Content / Points to:A 記錄填 IPv4 位址,AAAA 填 IPv6 位址,CNAME 填另一個網域名稱。
- TTL:這筆答案允許被快取多久,單位是秒。
各家面板的中文標籤大致是這樣:Cloudflare 的英文介面是 Type、Name、IPv4 address、Proxy status、TTL;GoDaddy 中文介面寫「類型、名稱、值、TTL」;Gandi 讓你直接編輯區域檔文字,所以你看到的是標準的區域檔語法;中華電信 HiNet 的網域代管,以及多數 TWNIC 認證的 .tw 註冊商面板,寫的是「主機名稱」「類型」「指向的值」或「內容」。名字不同,意思一樣。
這裡有一個幾乎每個人都踩過的坑:名稱欄位通常是相對於區域名稱的。你填 www,面板會自動補成 www.example.com。如果你老實地填了 www.example.com,有些面板會再接一次,變成 www.example.com.example.com,於是你 dig 原本那個名字什麼都查不到。存檔之後看列表上顯示的完整名稱是什麼,這是最快的判斷方式。如果面板接受結尾帶一個點的寫法(www.example.com.),那個點的意思就是「這是完整名稱,不要再接了」。
A 記錄給 IPv4,AAAA 記錄給 IPv6
A 記錄把名字對應到一個 IPv4 位址。AAAA 記錄把名字對應到一個 IPv6 位址。兩者可以同時存在,而且在雙堆疊的機器上本來就該同時存在。
但是 AAAA 只有在你的服務真的在 IPv6 位址上監聽時才可以加。瀏覽器用 Happy Eyeballs 的做法,會同時嘗試 IPv6 和 IPv4,IPv6 先有回應就走 IPv6。所以一筆指向「有位址但沒有人在聽」的 AAAA,結果是有些人連得上、有些人連不上,而且連不上的那群人看到的是逾時,不是明確的錯誤。這種問題非常難從回報中判斷。
加 AAAA 之前,在 VPS 上確認監聽位址:
sudo ss -tlnp看 443 那一行綁在什麼位址上。如果只看到 0.0.0.0:443,代表服務只聽 IPv4,這時候就先不要加 AAAA。設好之後,從外面用 curl -6 -I https://example.com 測一次,確認 IPv6 這條路真的通。
裸網域為什麼不能用 CNAME
你想把 example.com 指到某個服務給你的主機名,面板卻拒絕,錯誤訊息大意是 CNAME 不能與其他記錄共存。這不是面板的限制,是 DNS 協定本身的規則。
原因很直接:CNAME 的定義是「這個名字就是另一個名字的別名,它底下不能再有任何其他資料」。而裸網域一定帶著 SOA 記錄和 NS 記錄,那是區域存在的必要條件。兩者互相牴觸,所以裸網域不能設 CNAME。子網域沒有這個問題,www 或 app 想設 CNAME 都可以。
供應商的解法叫 ALIAS、ANAME 或 CNAME flattening(Cloudflare 用最後這個名字)。你在面板上填一個目標主機名,權威伺服器在回答查詢之前,先自己把那個主機名解析成 A 或 AAAA,再用你的網域名字把位址回給對方。所以線上實際看到的是一筆正常的 A 記錄,協定沒有被違反。
代價要知道:解析是在供應商的節點上做的,不是在使用者附近做的。如果目標服務會依照查詢來源的地理位置回不同位址,你的使用者拿到的會是「離供應商近」的那一組,不是離自己近的那一組。對於指向自己單一台 VPS 的情況,這個代價是零,因為位址只有一個。
www 和裸網域:兩筆記錄,一個 301
兩個名字都要能用。最簡單也最不會出事的做法,是兩筆都設成一樣的 A 記錄:@ 指向 VPS 的 IP,www 也指向同一個 IP。然後在 web 伺服器上選一個當正式網址,另一個回 301 轉址。
DNS 不能做轉址。DNS 只回答「這個名字對應到哪個位址」,它沒有辦法回答「請改去另一個網址」。轉址是 HTTP 層的行為,屬於 Nginx 或 Caddy 的設定,寫法可以參考Nginx 反向代理與 server 區塊的設定解析。
有些註冊商面板提供「網址轉址」或 Web Forwarding。那是供應商幫你跑一台 HTTP 伺服器回 301,不是 DNS 功能。它會佔用你的裸網域,讓 80 埠的請求根本到不了你的 VPS,於是 HTTP-01 憑證驗證也跟著失敗。要自己控制網站的話,不要用它。
搬機器之前先把 TTL 調低
TTL 是「下游解析器可以把這個答案留在快取裡多久」。關鍵在於:快取是別人持有的,你改記錄不會讓已經發出去的答案失效。TTL 3600 的記錄被某個 ISP 解析器抓走之後,接下來一小時內,它的使用者拿到的都是舊位址,不管你在面板上改了幾次。
所以搬到新 VPS 的順序是這樣:
- 搬家前,先把要動到的那幾筆記錄 TTL 從 3600 改成 300。
- 等至少一個舊 TTL 的時間(原本是 3600,就等一小時以上)。在這段時間過去之前,新的低 TTL 還沒有傳開。
- 改 IP。這時候最長只會有五分鐘的落差。
- 確認新機器穩定之後,把 TTL 調回 3600 或更高,減少查詢次數和延遲。
搬家期間讓新舊兩台都活著,直到舊機器的存取紀錄不再有人進來為止。整個搬遷流程還有資料、憑證和服務啟動順序要顧,那部分寫在把既有服務搬到新的 VPS裡。
還有一個容易被忽略的快取:查不到的名字也會被快取。這叫負向快取,時間長度由區域的 SOA 記錄裡的 minimum 欄位決定,不是由那筆記錄的 TTL 決定,因為那筆記錄當時還不存在。所以一個壞習慣是,記錄還沒建好就先 dig 一次,結果那個「不存在」被快取了十五分鐘,你建好之後反而要等更久。要先看,就直接問權威伺服器。
Cloudflare 的橘色雲朵改變了什麼
在 Cloudflare 的 DNS 列表裡,每筆記錄旁邊有一朵雲。橘色是 Proxied,灰色是 DNS only。
灰色的行為和其他供應商一樣:查詢回來就是你填的那個位址。橘色則是把記錄改成 Cloudflare 的 anycast 位址,使用者連到 Cloudflare,Cloudflare 再回頭連你的 VPS。所以橘色雲朵開著的時候,dig +short A example.com 回來的不會是你的 IP,這不是設定錯了。要確認自己填的值,看面板上的欄位,不要看 dig。
開了代理之後有三件事會變。
來源位址還是查得到,防火牆不能省。 憑證透明度紀錄裡的舊憑證、歷史 DNS 資料庫、忘了關代理的子網域(mail、ftp、cpanel 這類)、MX 記錄、伺服器自己寄出的信件標頭,都會洩漏來源 IP,全網掃描再比對回應內容也做得到。真正有效的做法是在 VPS 上只放行 Cloudflare 的位址連 80 和 443,其他來源一律丟棄,位址清單在 https://www.cloudflare.com/ips/ 。規則怎麼寫可以照VPS 上的 ufw 防火牆基本設定,但要注意一件事:如果你用 Docker 跑服務,ufw 的規則可能根本沒有生效,原因寫在Docker 發佈連接埠會繞過 ufw。順帶一提,鎖太緊也會出事:漏掉某一段 Cloudflare 位址,訪客看到的會是 Error 522: Connection timed out。
代理只處理 HTTP 和 HTTPS,而且只在特定連接埠上。 SSH 不會經過代理。拿一個橘色雲朵的名字去 ssh,你連到的是 Cloudflare,不是你的機器,症狀通常是連線被拒或卡住不動(怎麼分辨這兩種,見SSH connection refused 和 timed out 的差別)。留一個灰色雲朵的名字給管理用途,或直接用 IP 連。
憑證的簽發路徑會變。 訪客在瀏覽器看到的是 Cloudflare 的邊緣憑證,但你的來源主機仍然需要自己的憑證。SSL/TLS 模式設成 Full (strict) 而來源憑證無效或過期時,訪客看到的是 Error 526: Invalid SSL certificate。另外,HTTP-01 驗證的請求會先進 Cloudflare 再轉回來源,只要你沒有用規則攔截或改寫 /.well-known/acme-challenge/ 的路徑,它仍然會通。想完全不依賴 80 埠,或是要簽萬用字元憑證,就改用 DNS-01:用 API token 自動寫入 _acme-challenge 的 TXT 記錄,做法在用 Certbot 走 DNS-01 簽萬用字元憑證。
順便檢查 CAA 記錄。CAA 規定哪幾家憑證機構可以幫這個網域簽憑證。如果區域裡有 CAA 卻沒有列出你要用的那一家,簽發會被拒絕,ACME 回傳的訊息裡會出現 CAA record for example.com prevents issuance。用 dig +short CAA example.com 看一眼就知道有沒有這回事。
驗證:這幾個指令你自己跑
每一步都有對應的檢查。下面不寫「應該會顯示什麼」,因為答案取決於你自己的位址和供應商,你要做的是比對它和你填進面板的值是否一致。
先看一般解析結果:
dig +short A example.com
dig +short AAAA example.com
dig +short A www.example.com要看的重點是:A 那一行只有你填的那一組位址,沒有多出別的;如果你沒有設 AAAA,第二行應該是空的;www 和裸網域指到同一個地方。多出一組位址,通常是舊記錄沒刪,瀏覽器會在兩個位址之間輪流,症狀是「有時候正常有時候壞掉」。
跳過本機快取,直接問權威伺服器:
dig +short NS example.com
dig A example.com @ns1.your-dns-provider.example第一行拿到權威主機名,把它填進第二行的 @ 後面。權威伺服器的回答不受任何快取影響,所以它回答的就是你的區域現在真正的內容。它對了,代表你面板改對了,剩下的只是等快取退掉。
對照公開解析器,看快取退了沒:
dig +short A example.com @1.1.1.1
dig +short A example.com @8.8.8.8
dig +short A example.com @168.95.1.1最後那個是 HiNet 的解析器。台灣和香港的使用者很多走電信業者自己的解析器,它退快取的速度不一定跟公開解析器一樣,所以值得分開確認。Windows 上對應的寫法是 nslookup -type=A example.com 1.1.1.1。
想看整條委派鏈從根伺服器開始怎麼走,用 dig +trace example.com。這個指令在懷疑名稱伺服器設錯時特別有用,因為它不吃快取,一層一層問下去。DNS 查詢的整個流程,DNS 解析實際上經過哪些角色有完整的說明。
清掉自己這端的快取再測一次。Linux 上是 resolvectl flush-caches,Windows 是 ipconfig /flushdns,macOS 是 sudo dscacheutil -flushcache。瀏覽器另外有自己的 DNS 快取和 HSTS 清單,所以用無痕視窗測,或乾脆先用 curl 測。如果你的手機或電腦設了私有 DNS 或 DoH,結果會再多一層變數,這部分見私有 DNS 會改變你查到什麼。
還是打不開時,先分辨是 DNS 還是伺服器
這兩個指令完全跳過 DNS,直接連位址:
curl -H "Host: example.com" http://203.0.113.10/
curl --resolve example.com:443:203.0.113.10 https://example.com/把 203.0.113.10 換成你的 VPS 位址。第一行連 IP,但在 HTTP 標頭裡宣告網域名稱,用來確認 web 伺服器上的 server 區塊(vhost)有掛對名字。第二行連 IP,但整個 TLS 握手和 SNI 都用網域名稱,等於模擬 DNS 已經正確之後的情形。
判斷方式很乾脆。這兩行成功、用網域直接連失敗,問題在 DNS 或快取,回上一節繼續查。這兩行也失敗,問題在伺服器或防火牆,DNS 再改一百次都沒有用。這時候回 VPS 上用 sudo ss -tlnp 確認服務有在聽 80 和 443,用 sudo ufw status 確認規則有放行。
SSH 連得上、網站打不開,幾乎都屬於後者:DNS 沒問題,是 80 和 443 沒開,或是服務沒起來。
記錄答對之後,下一步是憑證和 vhost
記錄一旦回答正確的位址,DNS 這一段的工作就結束了,不需要再碰它。接下來是兩件事:申請一張憑證,讓 https 能用;設定 server 區塊,讓網域對應到正確的目錄或後端服務。HTTP-01 驗證要求網域已經指向這台機器,所以順序不能顛倒,這也是為什麼先做 DNS。
完整的建站流程在在自己的 VPS 上架設網站,為什麼一定要把 http 導向 https 則在伺服器上 HTTP 與 HTTPS 的差別講得比較清楚。
最後提醒一次順序:先確認誰在回答你的網域,再確認記錄的名稱欄位沒有被接成兩次,最後才調 TTL。這三件事處理好,網域指向 VPS 就不會再出問題。
FAQ
裸網域為什麼不能設 CNAME?
因為 CNAME 的定義是「這個名字是另一個名字的別名,底下不能再有其他資料」,而裸網域一定帶著 SOA 和 NS 記錄,兩者衝突,所以面板會拒絕。要把裸網域指到一個主機名而不是位址,用供應商提供的 ALIAS、ANAME 或 CNAME flattening:權威伺服器會先把目標解析成位址,再用你的網域名字回答,線上看到的仍然是一筆 A 記錄。如果你是指向自己的單一台 VPS,直接填 A 記錄就好,不需要這些。
我改了記錄,要多久才會生效?
權威伺服器是立刻生效的,用 dig +short NS example.com 拿到主機名,再 dig A example.com @那台主機 就能確認。其他人看到的時間,取決於舊記錄的 TTL,因為快取握在下游解析器手上,你改記錄不會讓已經發出去的答案提前失效。所以搬家要先降 TTL,等舊 TTL 過完再改位址。換名稱伺服器是另一回事,頂層網域的委派 TTL 常常是兩天。
我在註冊商面板加了 A 記錄,為什麼 dig 查不到?
多半是你的名稱伺服器已經指到別家,例如指到 Cloudflare,你卻在原本的註冊商面板編輯。註冊商那份區域檔還在,只是沒有人會去問它。跑 dig +short NS example.com,回來的是哪一家,就去哪一家的面板改。另一個可能是名稱欄位填了完整網域,被面板再接了一次區域名稱,看列表上顯示的完整名稱就知道。
Cloudflare 開了橘色雲朵,VPS 還需要防火牆嗎?
需要,而且更需要。代理只是讓 DNS 回答 Cloudflare 的位址,來源 IP 仍然會從憑證透明度紀錄、歷史 DNS 資料、沒開代理的子網域或郵件標頭洩漏出去,對方拿到位址就能直接繞過代理連你的機器。正確做法是只放行 Cloudflare 公布的位址範圍連 80 和 443。要注意漏掉某一段位址時,訪客會看到 Error 522: Connection timed out,那代表是你的防火牆擋掉了 Cloudflare,不是網站掛了。