# 以 Windows PC 作為節點伺服器之科學上網筆記
本文將以 Windows PC 作為伺服器,使用 V2Ray 工具搭配 vmess+ws+tls+web 完成翻牆用的節點搭建,過程中也會實作較為簡單的 vmess+tcp 及 vmess+ws+tls。只要你有能上網的電腦,並且對外有可訪問的公網 IP,就能不花一分錢,實現自建節點。
:::warning
請務必先確認你的網路運營商有配發給你家電腦一個外網可訪問的 IPv4 地址,我的情況是:若直接讓電腦使用 PPPoE 撥號,運營商會分配一個公網 IPv4 地址給我,但使用 DHCP 時,拿到的只有內網地址。
在終端機輸入以下命令,可以檢查設備分配的地址
```shell
ipconfig
```
下面這張圖就是有拿到公網地址的結果。

如果你的 IPv4 地址是像這樣 192.168 開頭的話,就代表不是公網地址。

:::
## 序
由於某些原因,下個月要去一趟中國。為了確保在中國的上網安全,在下做了一系列的功課,學習了從網路架構到 GFW 的運作方式,以及目前流行的各類翻牆軟體、協議,並且成功在家中的 Windows 主機上架設好了節點伺服器用以翻牆。
由於網路上主要的翻牆教學都是以 VPS + linux 為主,但我相信一定會有像我這樣的情況:前往中國而有科學上網需求,但又不想使用不穩定的免費 VPN,或者是花錢買機場、VPS,在有限資源的情況下又只有自家的 Windows PC 有機會可以作為節點伺服器。故本篇將詳細說明我的設置流程,需要的可以參考。
本文著重在技術的實現,而非原理講解,故本文將不會著墨於細節原理。若有想深入探究原理的人,推薦[不良林](https://www.youtube.com/@bulianglin)的 youtube 頻道給你們。
## 流程簡介
#### 第一階段
搭建 V2Ray 的 vmess+tcp 節點。實現最簡單的 vmess+tcp 代理。
#### 第二階段
註冊域名,建立 https 連結,包含申請證書(由可信任機構頒發)。
#### 第三階段
套用域名與證書,實現 vmess+ws+tls 流量偽裝。
#### 第四階段
使用 nginx 搭建偽裝站點,達到迴避 GFW 主動探測的目的,即 vmess+ws+tls+web 伺服器端設置。
## 實作流程
### 第一階段
搭建 V2Ray 的 vmess+tcp 節點。實現最簡單的 vmess+tcp 代理。
#### Step 1
在 Windows 伺服器下載 Windows 端的 [V2Ray Core](https://github.com/v2fly/v2ray-core/releases) (我這邊使用的是 v5.14.1,可下載當前最新的就好)

以及 [Nginx for windows](https://nginx.org/en/download.html) (我這邊使用 1.27.0)(nginx 在 vmess+tcp 不會用到,vmess+ws+tls+web 跟證書申請時才需要)

接著解壓縮,放在你喜歡的目錄下,推薦直接丟 D 槽下 ( D:/v2ray/v2ray.exe 跟 D:/nginx/nginx.exe ) 就好,下面也會以這個 D 槽路徑為範例。
#### Step 2
設置 v2ray 的 config.json 文件,如下
```json
{
"inbounds": [
{
"port": 8388,
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "e5a3ef20-a939-47d0-9e23-4c97836e0fa6",
"alterId": 0
}
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {}
}
]
}
```
port 端口可以跟我的不一樣,65535 以下的正整數都行,但之後用戶端設定的時候要記得跟這邊的一樣。
clients 的 id 也可以跟我不一樣,使用的 UUID 可讓[這個網站](https://www.uuidgenerator.net/)隨機生成,之後的設置也記得跟這邊的一致。
嘗試運行一下 v2ray.exe:在終端機開啟同個根目錄,執行
```shell
v2ray.exe run
```
或者
```shell
v2ray.exe run -c "config.json"
```
若 v2ray 版本是 4.x.x,你可能要運行
```shell
v2ray.exe -c "config.json"
```
它如果跳出防火牆通知,按確認就行了。
接著如果你看到

就表示執行成功。而這就是伺服器端的 vmess+tcp 實踐。
(若要結束運行,輸入 Ctrl+C 就行了。)
#### Step 3
vmess+tcp 客戶端配置。
###### Windows 裝置
可以選擇不同客戶端軟體,只要能支持 vmess 協議的都行(像是 v2rayN、Clash 等)。這邊以 v2RayN 為例。
首先要下載 v2rayN 客戶端。前往 [github 頁面](https://github.com/2dust/v2rayN/releases),找最新版本即可,我這邊用的是 6.43。
下載這個 v2rayN-With-Core.zip 的壓縮檔

解壓縮後直接運行 v2rayN.exe 即可。
接下來要加入我們剛剛創建好的節點。
在左上角選擇「伺服器」,選擇「新增[VMess]伺服器」。

別名:隨便填
位址:填入你的伺服器 IP 地址
埠:填入之前 config.json 設置的 port,我這邊就是 8388。

最後點選確定,右鍵選擇「測試伺服器真連結延遲」,如果延遲不是-1,則表示成功搭建 vmess+tcp 節點。
###### Android 裝置
學會 Windows 客戶端的使用,其實其他軟體乃至不同的裝置的設置都是非常雷同。
在 Android 操作系統中,可以使用 [v2rayNG](https://play.google.com/store/apps/details?id=com.v2ray.ang) 進行類似操作。故在此就不多贅述。
:::warning
現有情報表明,vmess+tcp 已經能夠被 GFW 精準探測,所以極不建議只使用 vmess+tcp 進行科學上網。若被 GFW 主動探測到,你搭的節點 IP 很大機率會被牆。所以建議繼續往下看,下面的 vmess+ws+tls+web 能夠達到較為安全的科學上網環境。
:::
:::warning
為防止 DNS 洩漏,在 v2rayN 建議啟用 TUN模式,在 v2rayNG 建議前往「設定」->「轉送設定」將轉送模式設置為「全域 Proxy」。

:::
---
### 第二階段
註冊域名,建立 https 連結,包含申請證書(由可信任機構頒發)。
#### Step 1
首先要註冊一個域名。
前往 [no-ip](https://www.noip.com/),註冊一個帳號,並創建一個域名。
進入 Dashboard,在側欄進入「Dynamic DNS」->「No-IP Hostnames」,點選「Create Hostname」。

填寫必要資料。Hostname 跟 Domain 可隨便選,而 IPv4 Address 要填伺服器的 IPv4 位址。

:::warning
由於是免費域名,之後記得要測試該域名是否有被牆。方法在第四階段會說。
:::
#### Step 2
再來要為域名申請 SSL 證書。(你可以選擇使用自簽證書,不過為了完美模擬正常網站的請求,這邊還是推薦使用可信任的機構頒發的證書)
前往 [ZeroSSL](https://zerossl.com/),註冊一個帳號。
點選「New Certificate」。
在「Domains」輸入剛剛註冊的域名,然後在「Validity」選擇「90-Day Certificate」(免費方案,到期後可以再用相同步驟申請一次)。接著一直下一步,跳轉到 Varify Domain 的頁面。
這個頁面是要驗證你是否是該域名的持有者。
我們選第三個,以 HTTP File Upload 進行驗證。

點選「Download Auth File」獲得一份 txt 檔案。
前往伺服器的 nginx 資料夾,在裡面創建一個兩層資料夾「.well-known/pki-validation」,並且將下載的 txt 檔案放到 pki-validation 之下。
在「config」資料夾中,編輯「nginx.conf」如下。
```
worker_processes 1;
events {
worker_connections 1024;
}
http {
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name [your ip]; # 你的 IP
location /.well-known/pki-validation/ {
# 符合你的 nginx 路徑
alias D:/nginx/.well-known/pki-validation/;
}
location / {
root html;
index index.html index.htm;
}
}
}
```
`[your ip]` 的部分要輸入你的伺服器 IPv4 位址。
接著在根目錄開啟終端機,輸入以下內容,來啟動伺服器。
```shell
start nginx
```
先在自己的瀏覽器測試一下以下網址是否能正常顯示下載的 txt 內容(`[your domain]` 是你註冊的域名,`[your txt].txt`是你下載下來的 txt 檔案)
```shell
http://[your domain]/.well-known/pki-validation/[your txt].txt
```
若能正常顯示,就可以到 ZeroSSL 在 Finalize 中點選 Verify Domain 進行驗證。
驗證完畢後,在下拉選單中選擇 NGINX,下載一份壓縮檔。可以先將裡面的 certificate.crt 以及 private.key 解壓縮複製到 v2ray 的資料夾下。
到此,域名跟證書就已經申請完成了。
:::info
可以在 nginx 根目錄下的終端機輸入
`nginx.exe -s stop` 或 `./nginx.exe -s stop` 停止 nginx 的執行。再者,也可以直接 Ctrl+Shift+Esc 打開工作管理員,搜尋到 nginx.exe,直接停止工作。
:::
---
### 第三階段
套用域名與證書,實現 vmess+ws+tls 流量偽裝。
#### Step 1
到伺服器的 v2ray 資料夾 (D:/v2ray),找到之前修改過的 config.json 文件。修改成以下內容。
```json
{
"inbounds": [
{
"port": 8288,
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "e5a3ef20-a939-47d0-9e23-4c97836e0fa6",
"alterId": 0
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": {
"certificates": [
{
"certificateFile": "D:/v2ray/certificate.crt",
"keyFile": "D:/v2ray/private.key"
}
]
}
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {}
}
]
}
```
id 跟前面 vmess+tcp 一樣可以填你自己的。而 port 的部分為了區分前面的 vmess+tcp,這裡我選用 8288。在`"certificates"` 下填入剛剛申請到的證書路徑。
接下來就是啟動 v2ray.exe 以及客戶端連線,就跟第一階段的時候差不多。
在客戶端,我們將「位址」改為剛剛註冊的域名,port 就填寫這次的 8288。
底層傳輸方式中,我們將「傳輸協定」改為 ws,「傳輸層安全」選擇 tls。使用自簽證書的話,可以將「跳過憑證驗證」設為 True。
同樣地,在 v2rayN 右鍵選擇「測試伺服器真連結延遲」,若有出現非 -1 的延遲,就代表 vmess+ws+tls 搭建成功。
:::warning
vmess+ws+tls 同樣無法到達完美的流量偽裝。如果 GFW 進行主動探測(向你註冊的域名發出網站請求),回傳的頁面會是一個 Bad Request ,而不是正常的網站,所以依舊有很高的機率被 GFW 封鎖。為此,我們就有了最終階段: vmess+ws+tls+web。
:::
---
### 第四階段
使用 nginx 將主頁面轉發到偽裝站點,達到迴避 GFW 主動探測的目的,即 vmess+ws+tls+web 伺服器端設置。
第三階段最大的毛病就是:網站如果被正常訪問就會漏餡,所以第四階段的目的就是解決這個問題。
在第二階段我們使用 nginx 是為了要域名驗證,而在這邊,我們就要用它來作為轉發的工具,也就是:當 GFW 對你的網站發起請求時,我們讓伺服器透過 nginx 返回一個在中國可以正常訪問的網站,來欺騙 GFW。
#### Step 1
配置伺服器 v2ray & nginx 設置。
將 v2ray 資料夾下的 config.json 修改為
```json
{
"inbounds": [
{
"port": 8488,
"listen":"127.0.0.1",
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "e5a3ef20-a939-47d0-9e23-4c97836e0fa6",
"alterId": 0
}
]
},
"streamSettings": {
"network": "ws",
"wsSettings": {
"path": "/myray"
}
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {}
}
]
}
```
將 D:/nginx/conf 下的 nginx.conf 修改為
```
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name [your domain]; # 你的域名
ssl_certificate D:/v2ray/certificate.crt; # 之前複製到 v2ray 資料夾下的證書檔案
ssl_certificate_key D:/v2ray/private.key; # 同上
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
location / {
proxy_pass https://www.bing.com; # 偽裝網址
proxy_ssl_server_name on;
proxy_redirect off;
sub_filter_once off;
sub_filter "www.bing.com" $server_name;
proxy_set_header Host "www.bing.com";
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language "zh-CN";
}
location /myray {
proxy_redirect off;
proxy_pass http://127.0.0.1:8488; # 填寫轉發的內網 IP 與端口
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name [your domain]; # 你的域名
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
}
```
首先,port 為了跟之前做區別,我設為 8488。而這裡,v2ray 只監聽來自於 nginx 轉發的位址 127.0.0.1。所以現在,當 GFW 直接訪問你的域名網站(https://[yourdomain])(預設接入 443 端口),nginx 會回傳偽裝網站(bing.com)的內容,只有當 GFW 訪問 https://[your domain]/myray 時,才會漏餡。而這個 myray 的目錄我們可以隨便換,更改 `"path": "/myray"` 參數以及 `location /myray` 的名稱就行了。
#### Step 2
啟動伺服器。
在 v2ray 根目錄啟動 v2ray
```shell
v2ray.exe run -c "config.json"
```
接著在 nginx 根目錄啟動 nginx
```shell
start nginx
```
(結束服務就在 v2ray 終端機按 ctrl+C,在 nginx 終端機輸入 `nginx.exe -s stop` )
最後,客戶端設定時,在「底層傳輸方式」中將「路徑」設為剛剛的目錄 myray,測試延遲沒問題的話,vmess+ws+tls+web 就大功告成了~
順帶一提,這裡 Android 手機端的 V2rayNG 似乎一定要把「跳過憑證驗證(allowInsecure)」設置為 true 才能順利連線。
### 測試
最後,你可以透過 [boce.com](https://www.boce.com/) 或 [greatfire.org](https://zh.greatfire.org/analyzer) 來測試你架設的 vmess+ws+tls+web 的域名,以及伺服器 IP 有沒有被牆。
## 結語
雖然線上測試都能過關,但實際情況誰都說不準。只有真正實地到中國測試連線才能知道成功與否。祝所有翻牆人都能找到自己的出路。
最後我想為這幾天做的一系列功課,寫下一些感言。
我覺得,建牆與翻牆的對抗可謂「道高一尺,魔高一丈」。沒有 100% 絕對可行的翻牆方式。當初 ShodowSocks 出來的時候,所有人無不是高喊「牆已形同虛設~」「牆要倒啦~」;而到了現在,它終究也因為牆的升級而逐漸成為了歷史的產物。而其他新世代的翻牆協議 shodowsocksR、vmess、vless、trojan ...,也可能某一天變得不再靠普。
唯有牆倒下的那天,這段抗爭才能夠平息。
## 參考資料
不良林 [https://www.youtube.com/@bulianglin](https://www.youtube.com/@bulianglin)
ChatGPT [https://chat.openai.com](https://chat.openai.com)