[Linux 架站] Wireguard VPN 設定教學

Wireguard 是由 Jason A. Donenfeld 開發的,
基於 UDP 協定的 VPN (Virtual private network) 程式,
有著比 IPsec 與 OpenVPN 更高的效能,
但設定上有一些些小複雜,這篇教學就來釋疑關於 Wireguard 詳細伺服器與用戶端的設定。

安裝 (以下是 Ubuntu 的指令)

sudo apt install wireguard

這裡有各式系統版本安裝指令:https://www.wireguard.com/install/

建立伺服器 (Server) 金鑰

建立伺服器 (Server) 金鑰,
金鑰是非對稱式加密的金鑰,有公鑰與私鑰各一對,
產生金鑰很簡單,用一行指令完成:

$ wg genkey | tee server_privateKey | wg pubkey > server_publicKey

就會產生二個檔案:

  • server_privateKey 伺服器私鑰
  • server_publicKey 伺服器公鑰

先留著備用。

建立用戶端 (Client) 的金鑰

建立用戶端 (Client) 的金鑰,指令相同:

$ wg genkey | tee client1_privateKey | wg pubkey > client1_publicKey

就會產生二個檔案:

  • client1_privateKey 用戶01私鑰
  • client1_publicKey 用戶01公鑰

留著備用。

建立共享密鑰 (PresharedKey) (非必要)

這選項非必要,如果你需要加強防護,可以再建立這個 共享密鑰 (PresharedKey) 來加強防護。
這個金鑰只需要產生 一個 就好。伺服器、用戶端 通通都是設定這一把。
如果要加共享密鑰,就通通都加,如果不加就通通不加。

wg genpsk > psk

留著備用。

設定值

接下來就是讓人有點混亂的地方了,撰寫設定檔。
以下分成三個部分,伺服器設定檔、 Client01 設定檔、 Client02 設定檔 來分別介紹。

伺服器 (Server) 設定檔

我們可以用 vi 來修改設定檔

$ vi /etc/wireguard/wg0.conf

有可能沒有這個資料夾,有可能沒有這個檔案,請自行建立。

大致會填入:

  1. 伺服器私鑰 Server PrivateKey
  2. 伺服器配發 IP 地址(假設為:192.168.100.1/24)
  3. 連接埠 (Port) (假設為:51820)
  4. 所有用戶的設定
    1. 該用戶配發的 IP 位址 (需事先指定好)
    2. 該用戶的公鑰 (PublicKey)

大致範例如下:

[Interface]
Address = 192.168.100.1/24
PrivateKey = IDnOe........(伺服器私鑰 Server PrivateKey)........xNFM=
MTU = 1500
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT && iptables -A FORWARD -o wg0 -j ACCEPT && iptables -t nat -A POSTROUTING -o ens4 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT && iptables -D FORWARD -o wg0 -j ACCEPT && iptables -t nat -D POSTROUTING -o ens4 -j MASQUERADE

# Client01
[Peer]
AllowedIPs = 192.168.100.2/32
PublicKey = p58AA........(用戶01公鑰 Client01 PublicKey)........cK8AY=

# Client02
[Peer]
AllowedIPs = 192.168.100.3/32
PublicKey = JM5oVD........(用戶02公鑰 Client02 PublicKey)........Axjyc=

分成 [Interface] 段落與 [Peer] 段落

伺服器 (Server) 的 [Interface] 段落

伺服器的 [Interface] 段落,存放伺服器的設定

  • Address:為 VPN 內網的 IP 位址
    (範例是 IP 是 192.168.100.1,子網路遮罩 24 意思為 255.255.255.0)
  • PrivateKey:這邊填入剛剛產生的伺服器私鑰
  • MTU:為 Maximum Transmission Unit (最大傳輸單元)
    意指設定最大封包大小(這個值可不設定)
  • ListenPort:聆聽的連接埠 (Port)
  • PostUp:當 VPN 服務啟動時要連帶執行的指令
  • PostDown:恰巧跟前者相反,當 VPN 服務停止時要連帶執行的指令

伺服器 (Server) 的 [Peer] 段落

伺服器的 [Peer] 段落,是存放 能連進來的用戶 列表
有幾個用戶就設定幾段 [Peer] 段落
上面例子是設定二個能連進來的用戶
(Server 的 Peer 定義跟 Client 定義不一樣,要注意)

  • PublicKey:這邊填入用戶的公鑰
  • PresharedKey:填入產生共享密鑰之 psk 檔內容(該選項非必要)
  • AllowedIPs:設定該用戶連進來配發的 IP 位址,每個人都必須唯一值,不可重複

用戶一號 Client01 設定檔

以下列出 Client 設定檔,可以參酌修改。
需要填入:

  1. 用戶01私鑰 Client01 PrivateKey
  2. 伺服器公鑰 Server PublicKey
  3. 配發用戶01的 IP (假設為:192.168.100.2/24)
  4. 伺服器位址 (假設為:vpn.example.com:51820)
  5. 共享密鑰 (如果有的話,本範例沒有)
[Interface]
PrivateKey = AOAHHE........(用戶01私鑰 Client01 PrivateKey)........7RDE0=
Address = 192.168.100.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = RNrgG........(伺服器公鑰 Server PublicKey)........EpJ0A=
AllowedIPs = 192.168.1.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 30

用戶二號 Client02 設定檔

跟 Client01 差不多,只是有小小的不同,故列出來給大家參考。
需要填入:

  1. 用戶02私鑰 Client02 PrivateKey
  2. 伺服器公鑰 Server PublicKey
  3. 配發用戶02的 IP (假設為:192.168.100.3/24)
  4. 伺服器位址 (假設為:vpn.example.com:51820)
  5. 共享密鑰 (如果有的話,本範例沒有)
[Interface]
PrivateKey = eWEo5G........(用戶02私鑰 Client02 PrivateKey)........0RBQc=
Address = 192.168.100.3/24
DNS = 1.1.1.1

[Peer]
PublicKey = RNrgG........(伺服器公鑰 Server PublicKey)........EpJ0A=
AllowedIPs = 192.168.1.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 30

二個用戶基本上大同小異,一併這邊做一個說明

用戶端 (Client) 的 [Interface] 段落

  • PrivateKey:這邊填入該用戶的私鑰
  • Address:填入與伺服器設定相同配發 IP 位址,一定要跟伺服器寫的一致
  • DNS:給定指定的 DNS Server (範例為:1.1.1.1 也可以用 8.8.8.8 或者別的 DNS)

用戶端 (Client) 的 [Peer] 段落

這邊定義了伺服器的連線資訊
(Server 的 Peer 定義跟 Client 定義不一樣,要注意)

  • PublicKey:填入伺服器的公鑰
  • PresharedKey:填入產生共享密鑰之 psk 檔內容(該選項非必要)
  • AllowedIPs:這邊設定比較特別,設定 哪些網段的流量會流向 VPN
    如果設定 0.0.0.0/0 的話,意指所有對外連線都會流向 VPN(如果要透過跳板機來上網就可以如此設定)。
    你可以設定特定的網段,例如伺服器群所在的網段,意指如果有連接伺服器群才會流向 VPN,否則直接對外,直接直連 Internet 而不透過 VPN。
  • Endpoint:連線到伺服器的位址(可以用網址,也可以用 IP)
  • PersistentKeepalive:保持連線的設定,範例設定 30 意指 30 秒會檢查一次連線。

啟動 Wireguard 伺服器

$ wg-quick up wg0

這樣可以把這個 VPN 伺服器啟動,你會發現多一個網路介面,名字就是我們命名的 wg0

可以用以下指令列出網路介面

$ ip a

啟動 Wireguard 用戶端 (Client) ,連線至伺服器

$ wg-quick up client1

然後測試

$ curl ipinfo.io/ip

看看 IP 有沒有變化?(如果全部對外流量都流進 VPN 的話,理論上 Public IP 位址一定會不一樣。)
或者 ping 看看你的伺服器群

(在 ping 沒有關的時候),測試看看有沒有正常回應 ping

Troubleshooting 疑難排解

設定 VPN 最難的就是除錯了。列出一些我遇到的問題。最多的情況就是連不上,
但連不上分成很多種情況,小弟這邊列出來可以一一檢查。

可以觀察

  • Data received
  • Data sent
  • Lastest handshake

這幾個值還有 Log

問題:做不了 Handshake

如果 Data received 少的很可憐,Log 顯示沒有做到一次 Handshake,很有可能是被擋了。
請檢查防火牆 (Firewall) 有沒有開對應的 Port。
尤其是雲端主機(Amazon, GCP…等),他們後台有自帶一個防火牆,直接從他的後台做設定。

用戶端請檢查連線資訊是否有錯?欲連接的 IP 位址、連接埠 (Port) 是否有錯?
測試一下 DNS,是不是存粹 DNS 無法正確解析?
而或者你的 Nameserver 的 A 紀錄根本就是設錯的?

pingnslookup 查證。

問題:Handshake 有成功,但網路整個連不上

要檢查 Wireguard 伺服器 (Server) 設定的 PostUpPostDown 裡面的指令有沒有問題。
裡面有寫了二個介面 wg0ens4

  • wg0:是 Wireguard 啟動時,會自動產生的介面名稱,這個 需跟你的檔名一致
  • ens4:是對外的介面名稱 (Interface),也有可能是 eth0 或者別的名字。

用戶端 [Peer] 段落的 AllowedIPs 是不是設定了 0.0.0.0/0
意指所有對外連線都會流向 VPN,如果設定上去整個網路貌似斷線就是這個緣故。

伺服器端 (Server) 的 net.ipv4.ip_forwardnet.ipv6.conf.all.forwarding 有沒有正確打開?
因為 Wireguard 伺服器設定的 PostUpPostDown 裡面有設定 FORWARD 必須打開。

問題:Handshake 有成功,但 ping 不到伺服器

如果是設定 VPN 來存取伺服器群的話,
可以測試連上 VPN 後,使用伺服器的 私人 IP (Private IP) 能不能正確 ping 到?
如果不行,請檢查用戶端 [Peer] 段落的 AllowedIPs 網段是不是設錯?
尤其是 子網路遮罩 (Subnet mask) 是不是有算對?

如果是 Class B 的 私人 IP
就不會是常見的 /24 (255.255.255.0)
而會是 /20 (255.255.240.0)

看你伺服器群的網路怎麼設計。

重點整理

最後統合幾個設定重點:

  • 整套系統採非對稱式加密,會產生公鑰私鑰一對金鑰,
    用公鑰加密、私鑰可解密
    故需要二對金鑰
  • 所有的用戶端 (Client) 需要預先指定好分配的 IP 位址
  • 伺服器 (Server):填入伺服器自身的私鑰,與所有用戶端 (Client) 公鑰
  • 用戶端 (Client):填入伺服器公鑰與自身的私鑰
  • 記得查看 Log 來除錯 (debug) 並檢查設定檔問題

以上幾點供參考,祝設定順利。😊

很複雜?來,這有工具XD

很後來亂逛才看到的,直接幫你生好
https://www.wireguardconfig.com/

參考資料

Linux Server 伺服器建置筆記 (用 Ubuntu 設定基礎網路 & SSH伺服器)

這邊整理了一些手動 Linux server 伺服器安裝,需注意的一些事情與指令。
備忘一下以備不時之需。
(如果是設定雲端主機的話,部分步驟可以跳過,它預設都幫你建好了。)

製作可開機 USB (Bootable USB)

使用 UNetbootin 軟體

軟體下載:https://unetbootin.github.io/

選擇 USB drive,選擇 ISO 就可以了
針對目標機器做開機。

Mac 系統的話,可以使用 Etcher
軟體下載:https://www.balena.io/etcher/

做法差不多


選擇作業系統:

  • Debian 系列:可選擇 Ubuntu, Debian
  • RedHat 系列:可選擇 RHEL, CentOS, Fedora
  • BSD 系列:可選擇 FreeBSD
  • SUSE 系列:可選擇 OpenSUSE

前二項是筆者較為熟悉的,推薦 Ubuntu, Debian, CentOS 做為選項。

ISO 的版本很多:

  • Desktop ISO:有一個完整的 Live CD 可供試用
  • Server ISO:有預載一些伺服器使用的套件
  • Minimal ISO:只是檔案小,預設網路驅動了之後,大多都從網路上抓

不知怎麼選擇的話,預設就選 Desktop ISO
(以下撰文用 ubuntu 做示範)

網路指令相關

這邊列出常用的網路指令,如果網路不通的事情,當然要優先處理。

列出網路介面與 IP 位址

$ ip a
$ ip addr show
$ ifconfig

這幾個指令都可以,輸出格式稍有不同。

列出路由閘道 Gateway 設定

$ route -n

設定網路連線資訊

這邊介紹一個新東西:netplan
網路對它介紹不多,但個人覺得非常可以取代目前網路設定不方便的窘境。

假設你要設定的網路連線資訊如下:

  • 目標介面: eth0

  • IP 位址 (IP Address): 192.168.10.200

  • 子網路遮罩 (Netmask): 255.255.255.0 (/24)

  • 網路閘道 (Gateway): 192.168.10.1

  • 主要 DNS 為 8.8.8.8

  • 次要 DNS 為 168.95.1.1

(請根據你的自身環境修改,這裡只是舉例)

只要找到 /etc/netplan/01-netcfg.yaml 這個檔案並編輯

$ sudo vi /etc/netplan/01-netcfg.yaml

修改成類似以下內容:

network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      addresses: [192.168.10.200/24]
      gateway4: 192.168.10.1
      nameservers:
        addresses: [8.8.8.8,168.95.1.1]
      dhcp4: no

(請根據你的自身環境修改,這裡只是舉例)

就這樣而已,省二、三個指令,簡單又直覺。

如果你要 dhcp (自動取得 IP 位址) 那更簡單了:

network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: yes

然後存檔離開

執行一個很直覺的指令: netplan try

$ sudo netplan try
Do you want to keep these settings?

Press ENTER before the timeout to accept the new configuration
Changes will revert in 120 seconds

是否要保留設定?按 Enter 保留設定,不然 120 秒後會復原。
就跟切換螢幕解析度一樣簡單。

爾或者可以用 netplan apply 直接套用。

$ sudo netplan apply

(舊式) 設定 IP 位址 (IP Address)

$ sudo ip addr add 192.168.10.200/24 dev eth0

這邊用 192.168.10.200 做為例子,請修改成恰當的值。

(舊式) 設定網路閘道 Gateway

$ sudo route add default gw 192.168.10.1 eth0

這邊用 192.168.10.1 做為例子,請修改成恰當的值。

(舊式) 設定 DNS

$ sudo echo nameserver 8.8.8.8″ > /etc/resolv.conf

這邊用 8.8.8.8 的 Google DNS 做為例子,你也可以調整成你喜歡的。

DHCP Relase

釋放從 DHCP 取得的 IP 位址

$ sudo dhclient -r

指令等同 Windows 裡的 ipconfig /release

DHCP Renew

從 DHCP 重新取得新的 IP

$ sudo dhclient

指令等同 Windows 裡的 ipconfig /renew

啟動/關閉 網路介面 (ip 指令)

$ ip link set dev eth0 up
$ ip link set dev eth0 down

例如介面名稱為 eth0,請自行修改成合適的網路名稱。

啟動/關閉 網路介面 (ifconfig 指令)

$ /sbin/ifconfig eth0 up
$ /sbin/ifconfig eth0 down

例如介面名稱為 eth0,請自行修改成合適的網路名稱。

列出所有網路介面與狀態

$ ip link show
$ ifconfig -a

這二個都可以

檢查外部公有 IP (Public IP)

$ curl ipinfo.io/ip

一個簡單的指令可以查詢外部公有IP地址 (Public IP)

SSH 相關

安裝 SSH Server (應該預設就有安裝了)

應該預設就有安裝了,如果沒有安裝,請手動用指令安裝之。
(以下為 ubuntu 的指令)

$ sudo apt install -y ssh openssh-server

開機預設啟動 ssh

$ sudo systemctl enable ssh

啟動 ssh

$ sudo systemctl start ssh

查看 ssh 狀態

$ sudo systemctl status ssh

使用 ssh key 取代密碼登入

增加方便性也加強安全性,建議用 ssh key (pem) 檔案來登入 ssh。

產生 ssh key

$ ssh-keygen

指定檔案,例如 id_rsa 檔案(檔名可自訂)。
密碼 passphrase 可以留空

將會產生 id_rsa (私鑰) 與 id_rsa.pub (公鑰) 檔案。

接下來的步驟將是把您的公鑰複製到伺服器上(或者是把私鑰下載回使用者電腦上)。
使用者(你)透過電腦上的私鑰來做連線。

自動複製 ssh key

(在 Client 端執行此指令)
這個步驟是自動把您的公鑰複製到伺服器上。

$ ssh-copy-id -i ~/.ssh/id_rsa -p 22 [email protected]

如果不能運作也不用太糾結,等等有手動的方式。

運行結果:

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/user/.ssh/id_rsa.pub"
The authenticity of host '[192.168.10.200]:22 ([192.168.10.200]:22)' can't be established.
ECDSA key fingerprint is SHA256:wYmwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcFme8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:

Number of key(s) added:        1

Now try logging into the machine, with:   "ssh -p '22' '[email protected]'"
and check to make sure that only the key(s) you wanted were added.

另外一個指令,作法相同。

$ cat ~/.ssh/id_rsa.pub | ssh -p 22 [email protected] "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

或者手動複製產生之公鑰 (PublicKey) 到伺服器的 ~/.ssh/authorized_keys 檔案。
(如果沒有 .ssh 隱藏資料夾與 authorized_keys 檔案,請自行建立。)

設定 SSH 關閉密碼登入

$ vi /etc/ssh/sshd_config

找到這行並修改

PasswordAuthentication no

設定免密碼 sudo

(這個步驟非必要)
在設定之前,先調整預設開啟的編輯器。
因為小弟長期習慣用 vim 所以用此指令先切換預設開啟的編輯器

$ sudo update-alternatives --config editor
There are 4 choices for the alternative editor (providing /usr/bin/editor).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /bin/nano            40        auto mode
  1            /bin/ed             -100       manual mode
  2            /bin/nano            40        manual mode
  3            /usr/bin/vim.basic   30        manual mode
  4            /usr/bin/vim.tiny    15        manual mode

Press <enter> to keep the current choice[*], or type selection number: 3
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/editor (editor) in manual mode

ubuntu 預設是開 nano 編輯器,可以用這個來修改
可以選擇 3 改用 vim 編輯器。

然後使用該指令編輯設定檔

$ sudo visudo

找到

%sudo   ALL=(ALL:ALL) ALL

把它改成

%sudo   ALL=(ALL:ALL) NOPASSWD: ALL

然後存檔離開。

連線 SSH

這個可以做為 bash script 以後方便使用。

$ ssh -i ~/.ssh/id_rsa -p 22 [email protected]

軟體更新

時時軟體更新、修補漏洞、修復 Bug 是很重要的,以下是一些常用的指令

更新套件庫清單(取得有哪些套件已更新)

$ sudo apt update -y

更新套件

$ sudo apt upgrade -y

確認版號

$ lsb_release -a

其實另外二個都可以,個人比較喜歡這個

$ cat /etc/os-release  
$ hostnamectl

列出 Linux 核心版本號

$ uname -r

整個大版本更新
例如從 ubuntu 20.04LTS 升到 ubuntu 22.04.2LTS

$ sudo do-release-upgrade

參考資料

https://www.cyberciti.biz/faq/ubuntu-linux-install-openssh-server/
https://www.digitalocean.com/community/tutorials/how-to-configure-ssh-key-based-authentication-on-a-linux-server
https://vitux.com/ubuntu-ip-address-management/
https://www.cyberciti.biz/faq/howto-linux-renew-dhcp-client-ip-address/
https://tldp.org/HOWTO/Linux+IPv6-HOWTO/ch05s02.html
https://www.cyberciti.biz/faq/upgrade-ubuntu-20-04-lts-to-22-04-lts/