记一次反向代理教学管理服务平台
拥有一定的门槛,本文假设你了解 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
有其他问题可以评论回复。