介紹如何修改Linux的DNS伺服器連線,以Ubuntu為例。
需要系統版本:Ubuntu 24.04以上。
DNS伺服器規定了Linux上網時查詢網域與IP的規則。為什麼要修改DNS伺服器?用途有三:
- 使用更快的網路上網。有的時候台灣國內中華電信的DNS速度有點慢,改為Google的DNS就能夠更快的載入網頁。
- 連線到自訂擋廣告DNS,例如AdGuard或PiHole,從連線的源頭根本性的阻絕廣告。
- 繞過DNS污染的封鎖。有些國家會看不順眼的網站發動域名伺服器污染,導致無法連線。修改DNS可以解決這個問題。
修改Linux的DNS伺服器,可以用指令或者圖形界面達成。
1. 關於/etc/resolv.conf#
Linux的DNS設定有二個重要檔案,/etc/resolv.conf
告訴Linux要連線到哪個伺服器去查詢DNS。至於/etc/hosts
則是在本機手動定義網域與IP的對應關係,這不是我們要改的東西。
理論上可以透過編輯/etc/resolv.conf
檔案來直接修改DNS伺服器,那麼我們應該直接改這個檔案嗎?否。較新的Linux發行版多半使用「NetworkManager」或「systemd-networkd」管理連線,Ubuntu使用的Netplan也會尊重NetworkManager端的設定。/etc/resolv.conf
檔案內容由NetworkManager或systemd-networkd來自動產生,不應該手動編輯。
假設系統使用systemd-networkd管理網路,那麼一定會順帶安裝「systemd-resolved」套件,用於管理DNS。反之有安裝NetworkManager的系統,不見得會安裝systemd-resolved套件。
以Ubuntu Desktop 24.04來說,預設是使用NetworkManager + systemd-resolved的方案。
為什麼NetworkManager就能改DNS,還要systemd-resolved呢…?這是獨立的DNS伺服器,提供DNS快取以及DNS over TLS的功能,可以讓許多服務設定DNS,又不會互相搶/etc/resolv.conf
的控制權。
Linux會透過NetworkManager或systemd-resolved管理DNS,這點可以查看服務狀態是否為active來確定:
sudo systemctl status NetworkManager
sudo systemctl status systemd-resolved
沒有systemd-resolved的情況下,如果透過NetworkManager的附屬指令nmcli
或者resolvconf
去改DNS,會將變更寫入/etc/resolv.conf
檔案。用指令cat /etc/resolv.conf
查看,裡面會寫上# Generated by NetworkManager
的字樣。
# Generated by NetworkManager
nameserver 192.168.1.1
不過NetworkManager也可以跟systemd-resolved一同使用,前者一旦偵測到後者存在就會自動適應變化。要是系統安裝了systemd-resolved,就會導致/etc/resolv.conf
變成符號連結檔,指向/run/systemd/resolve/stub-resolv.conf
。這點可以用ls -l /etc/resolv.conf
指令確認:
root root /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
安裝systemd-resolved之後,用指令cat /etc/resolv.conf
查看,裡面會寫上# managed by man:systemd-resolved
的字樣,nameserver會固定指向127.0.0.53。
# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
# Do not edit
nameserver 127.0.0.53
此時NetworkManager就會自動改用systemd-resolved去修改DNS。這樣我們就有了二個設定DNS的方式,一個是nmcli指令,另外一個是改systemd-resolved設定檔。總之,避免直接修改/etc/resolv.conf
檔案的內容。
2. 查看Linux使用的DNS伺服器#
每一個網路卡都有自己的DNS伺服器,像「乙太網路連線」、「Wifi連線」使用的可能是不同的DNS伺服器。
用NetworkManager附屬的nmcli指令,即可查看DNS伺服器。
nmcli dev show
這個指令會自動選取目前使用中的連線,所以只要用grep讀取DNS的數值就能知道DNS伺服器位址了。
nmcli dev show | grep DNS
# 範例輸出
IP4.DNS[1]: 192.168.1.1
或者,用
nmcli dev
指令列出所有網路卡,再確認DNS位址,例如nmcli dev show enp2s0
。因為Ubuntu使用systemd-resolved,所以它也能列出目前網路卡正在使用的DNS伺服器:
sudo resolvectl status
# 範例輸出
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (enp2s0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 192.168.1.1
3. 修改Linux的DNS伺服器#
這裡以Google的DNS伺服器為例,我們將要把DNS伺服器改為8.8.8.8
和8.8.4.4
。
選擇你方便的方式即可。
nmcli指令#
- 列出目前的網路連線,例如乙太網路連線應該會顯示為
eth0
之類的名稱,它使用的網路卡為enp2s0
nmcli con show
# 範例輸出
NAME UUID TYPE DEVICE
eth0 1fdab9b9-ba1e-47ab-9886-ee034b4bb709 ethernet enp2s0
- 選取乙太網路連線
eth0
,修改DNS。若有多個DNS伺服器就用空格隔開。
nmcli con mod "eth0" ipv4.dns "8.8.8.8 8.8.4.4"
- 關閉自動取得DNS的功能
nmcli con mod "eth0" ipv4.ignore-auto-dns yes
- 重新啟動網路連線。
sudo systemctl restart NetworkManager
- 查看DNS伺服器:
nmcli dev show enp2s0 | grep DNS
# 範例輸出
IP4.DNS[1]: 8.8.8.8
修改systemd-resolved設定檔#
systemd-resolved設定檔與nmcli指令的差別在於,這裡設定的是「全域DNS伺服器」,不論乙太網路還是Wifi網路,都會自動套用一樣的DNS。
- 編輯設定檔
sudo vim /etc/systemd/resolved.conf
- 填入要使用的DNS。多個DNS伺服器使用空格隔開。
[Resolve]
DNS=8.8.8.8 8.8.4.4
- 重新啟動systemd-resolved服務:
sudo systemctl restart systemd-resolved
- 查看DNS伺服器:
sudo resolvectl status
# 範例輸出
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
DNS Servers: 8.8.8.8 8.8.4.4
Link 2 (enp2s0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
DNS Servers: 8.8.8.8
圖形界面#
GNOME桌面:系統設定 → 連線,選取有線網路,點選旁邊的齒輪,切換到IPV4連線,取消勾選自動DNS。填入DNS伺服器。
KDE Plasma桌面:系統設定 → 連線,選取乙太網路。點選IPV4,在其他域名伺服器,輸入DNS伺服器,再按下套用。