擁有一定的門檻,本文假設你了解 Linux 的基本操作,如創建並編輯文件、基本的進程管理等。
參考了 GitHub 項目 反向代理工大教務管理系統 及其一篇博客 反向代理教務系統,但由於學校不同,也遇到了一些上面沒有提到的問題,故記錄於此。
環境與准備
-
騰訊雲服務器
操作系統 CPU 內存 公網帶寬 Ubuntu Server 20.04 LTS 64位 1核 2GB 1Mbps -
Nginx
一、安裝 MotionPro 客戶端
-
將下載好的 .sh 傳至服務器(因為它官方需要驗證碼認證后才能下載,所以我選擇下載到本地后通過 FTP 上傳)。
-
授予可執行權限
chmod u+x MotionPro_Linux_Ubuntu_x64_v1.2.9.sh
-
執行安裝腳本
sudo ./MotionPro_Linux_Ubuntu_x64_v1.2.9.sh
-
可以測試一下是否可用
MotionPro --host vpn.你的學校.edu.cn --user 你的賬號 --passwd 你的密碼
,但是你將會和你的服務器失去連接。修改路由表,目的是你的linux機器可以同時訪問工大vpn和公網,如果不修改路由表,你的虛擬機在連接到vpn后,會和你自己斷開連接,這時候連ssh都連不上了,只能通過主機提供商的后台重啟機器,切記切記
回到騰訊雲重啟你的主機即可重新通過 SSH 連接你的雲服務器。
在這里可能會提醒沒有啟動 vpnd,直接在命令行輸入
vpnd
后回車即可。后面會將怎么處理。
二、完成修改路由表腳本
第一步中如果可以使用 MotionPro 成功連接 VPN 會出現與 SSH 斷開連接的情況,原因是連接 VPN 會改變服務器的路由,由於路由不對稱,本地就會失去與服務器之間的連接。
修改路由表的作用就是讓我們的服務器開啟 VPN 后,在訪問需要校園網才能訪問的地址時通過 VPN 產生的路由,其他時候都使用默認路由。
在 Linux 里,修改路由表可以使用 route
進行修改,但是由於連接 VPN 后失去了鏈接,所以可以預先寫個腳本來在連接 VPN 后修改路由表。
在我一開始提到的文章里,作者是使用 route_add.sh 來修改的,內容如下:
#!/bin/bash
echo "start"
for((i=1; i<172; i++))
do
v=$(/sbin/route add -net "$i".0.0.0 netmask 255.0.0.0 gw 182.92.123.247 dev eth1) #182.92.123.247 is the gateway address of your Virtual-Machine server.
echo "$v"
done
for((i=173; i<256; i++))
do
v=$(/sbin/route add -net "$i".0.0.0 netmask 255.0.0.0 gw 182.92.123.247 dev eth1)
echo "$v"
done
/sbin/route add -net 172.0.0.0 netmask 255.0.0.0 gw 1.1.1.1 dev tun0 #let 172.0.0.0 route to vpn channel.
/sbin/route del default #delete default route,we have add all route manually just before.
echo "finished"
v=$(/sbin/route)
echo "$v"
這里附帶上 Issue 上作者的補充說明
對於route_add.sh,這個比較麻煩一點,腳本里面的內容要根據你自己的主機實際情況改一下,需要注意的有這么幾個地方:
v=$(/sbin/route add -net "$i".0.0.0 netmask 255.0.0.0 gw 182.92.123.247 dev eth1) /sbin/route add -net 172.0.0.0 netmask 255.0.0.0 gw 1.1.1.1 dev tun0
了解 route add 名行命令里面每一個參數什么意思
子網掩碼應該就用 255.0.0.0
網關地址這個要用你主機默認路由表里的網關地址
接口名稱eth1 也是來自於主機,不同主機不一樣,你要改成你自己的
172.0.0.0這個地址段包含了咋們學校所有內網主機,所以需要針對這個使用vpn的代理通道,其中tun0網絡名稱應該是固定的,代理直至1.1.1.1你也要實際在你的主機上觀察,這一步比較費事,因為你一旦連上vpn,你和主機就斷開連接了,所以可能需要打印一些必要的日志信息來觀察最簡單的就是在連接vpn后加一句
/sbin/route >> iplist.txt
也就是說,這個文件對於不同學校以及不同主機來說是有區別的。
我這里重新解釋一下他文件中的一些字段為什么這樣寫:
-
他使用了兩段循環執行
/sbin/route add -net "$i".0.0.0 netmask 255.0.0.0 gw 182.92.123.247 dev eth1
,把 172 跳過了。是因為他學校的教務系統的 IP 都是172.*.*.*,所以通過這些命令,讓除了訪問172.*.*.*的 IP 地址,其他都通過原來的路由。 -
182.92.123.247
這個是他自己網卡的 IP 地址。這個可以通過ifconfig
命令查看。eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.8 netmask 255.255.240.0 broadcast 172.17.15.255 inet6 fe80::5054:ff:fe4f:45b6 prefixlen 64 scopeid 0x20<link> ether 52:54:00:4f:45:b6 txqueuelen 1000 (Ethernet) RX packets 44385 bytes 12912991 (12.9 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 41628 bytes 8406493 (8.4 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
其中我的
172.17.0.8
即是他的182.92.123.247
-
eth1
這個是他的默認網卡名稱,即是讓訪問除校園網以外的地址所采用的網卡,也是可以通過ifconfig
查詢你的默認網卡。如上一條所示,我的默認網卡名稱為eth0
-
/sbin/route add -net 172.0.0.0 netmask 255.0.0.0 gw 1.1.1.1 dev tun0
這一條則是讓訪問校園網即172.*.*.*時走tun0(MotionPro產生的)。其中255.0.0.0
和1.1.1.1
不需要改變。
所以對於我個人來說,這個腳本應該修改為:
#!/bin/bash
echo "start"
for((i=1; i<202; i++))
do
v=$(/sbin/route add -net "$i".0.0.0 netmask 255.0.0.0 gw 172.17.0.8 dev eth0)
echo "$v"
done
for((i=203; i<256; i++))
do
v=$(/sbin/route add -net "$i".0.0.0 netmask 255.0.0.0 gw 172.17.0.8 dev eth0)
echo "$v"
done
/sbin/route add -net 202.0.0.0 netmask 255.0.0.0 gw 1.1.1.1 dev tun0
/sbin/route del default #delete default route,we have add all route manually just before.
echo "finished"
v=$(/sbin/route)
echo "$v"
再通過另一個腳本調用“啟動MotionPro”和“修改路由表”:
MotionPro --host vpn.你的學校.edu.cn --user 你的賬號 --passwd 你的密碼
sleep 5s
sudo /home/ubuntu/vpn/script/route_add.sh >> /home/ubuntu/vpn/logs/route_add.log
通過 chmod
授予權限后啟動。可以看到 VPN 連接成功,同時 SSH 也沒有斷開連接了。再 ping 一下學校的 ip 也可以訪問了。
三、反向代理
這個需要修改 Nginx 的配置,我也沒有很了解,這里借鑒原作者的內容,刪除了關於 https 配置 ssl 的內容。具體位置請搜索 Nginx 配置文件位置。
upstream jxgl{
# 你的大學的教學管理系統的網站
server jxgl.你的大學.edu.cn:80;
}
server{
listen 80;
server_name 127.0.0.1;
location =/{
proxy_set_header Host $host;
proxy_pass http://jxgl;
}
location /{
proxy_set_header Host $host;
proxy_pass http://jxgl;
}
}
之后重啟 Nginx 即可。sudo systemctl restart nginx
四、完善腳本
完善內容:
- 日志輸出添加時間
- 15 分鍾檢測一次,根據 MotionPro 提供的狀態決定是否重連
- 由於我的學校有 3 個 VPN 連接入口,在其中一個不成功的情況下我可以連接其他的入口,所以添加多個連接命令
下面是我的兩個文件。
home/ubuntu/vpn/script/check.sh
#!/bin/bash
idle="VPN Status: idle"
connected="VPN Status: connected"
stat=$(MotionPro -a)
if [ "$stat" == "$connected" ]
then
time=$(date "+%Y-%m-%d %H:%M:%S")
echo "$stat"
echo "$time"
exit 0
fi
if [ "$stat" == "$idle" ]
then
echo "-try vpn1-"
MotionPro --host vpn1.你的學校.edu.cn --user 你的賬號 --passwd 你的密碼
sleep 5s
fi
stat=$(MotionPro -a)
if [ "$stat" == "$idle" ]
then
echo "-try vpn2-"
MotionPro --host vpn2.你的學校.edu.cn --user 你的賬號 --passwd 你的密碼
sleep 5s
fi
stat=$(MotionPro -a)
if [ "$stat" == "$idle" ]
then
echo "-try vpn3-"
MotionPro --host vpn3.你的學校.edu.cn --user 你的賬號 --passwd 你的密碼
sleep 5s
fi
stat=$(MotionPro -a)
if [ "$stat" == "$connected" ]
then
sudo /home/ubuntu/vpn/script/route_add.sh 1>>/home/ubuntu/vpn/logs/route_add`date +'-%Y-%m-%d'`.log 2>>/home/ubuntu/vpn/logs/route_add_error`date +'-%Y-%m-%d'`.log
fi
time=$(date "+%Y-%m-%d %H:%M:%S")
echo "-$stat-"
echo "$time"
home/ubuntu/vpn/script/route_add.sh
#!/bin/bash
for((i=1; i<256; i++))
do
if [ $i -eq 202 ]
then
continue
fi
/sbin/route add -net "$i".0.0.0 netmask 255.0.0.0 gw 172.17.0.8 dev eth0 #172.17.0.8 is the gateway address of your Virtual-Machine server.
done
/sbin/route add -net 202.0.0.0 netmask 255.0.0.0 gw 1.1.1.1 dev tun0 #let 202.0.0.0 route to vpn channel.
/sbin/route del default #delete default route,we have add all route manually just before.
time=$(date "+%Y-%m-%d %H:%M:%S")
echo "$time"
之后通過其他腳本或進程管理等方式 N 分鍾執行一次即可。
五、其他問題
啟動 MotionPro 需要提前啟動 vpnd,本來打算找一下教程加入到開機自動啟動里,即一種加入到 /etc/rc.local
的方法,但是打開后發現 vpnd 已經存在。之后通過 systemctl status rc-local service
檢查了一下,報錯如下:
Starting /etc/rc.local Compatibility...
rc-local.service: Failed to execute command: Exec format error
rc-local.service: Failed at step EXEC spawning /etc/rc.local: Exec formate error
rc-local.service: Control process exited, code=exited status=203
rc-local.service: Failed with result 'exit-code'.
Failed to start /etc/rc.local Compatibility.
看來是 rc.local 沒有成功啟動。
網上搜到兩個解決方法,我都添加進去后生效了,並不知道哪一個是正確的,所以都貼出來了。
sudo vim /etc/systemd/system/rc-local.service
在結尾添加
[Install]
WantedBy=multi-user.target
sudo vim /etc/re.local
在開頭添加
#!/bin/sh -e
有其他問題可以評論回復。