本文教程需要有一台公网服务器
【本文参考链接】
利用SSH 反向代理 ,实现跨局域网连接家里的linux 主机 (树莓派)
centos7查看端口是否开放
最近新入了一台树莓派4,顺便把我的2b出了。以前只是拿来当作3D打印服务器,虽然公司的网络有公网IP,但是这个IP也不固定,每次重新拨号或者停电之类的操作都会使得公网IP改变。
以前试过花生壳等内网穿透软件,最近想试试新的方法,公司刚好也有公网服务器(阿里云),所以才有了这篇文章。
关于反向代理的介绍,可以查看百度百科:反向代理
注:本文中的公网服务器地址为
11.22.33.44
,公网服务器端口为8022
,树莓派端口为22
,一定要根据你自己的实际情况修改为你的配置。
一、修改公网服务器ssh配置文件
#vi /etc/ssh/sshd_config
找到GatewayPorts
,默认设置为no
,将其修改为yes
GatewayPorts yes
然后重启ssh服务:
# centos 7
systemctl reload sshd.service
# centos 7以下
service sshd reload
二、将局域网中的树莓派连接到公网服务器反向代理端口
# ssh -CqTfnN -R 0.0.0.0:8022:127.0.0.1:22 [email protected]
其中,8022
为公网反向代理端口,22
为树莓派的ssh
端口,11.22.33.44
为公网服务器的IP地址。
上述代码即:将树莓派的22
端口反向代理到IP地址11.22.33.44
的8022端口
三、检查公网服务器反向代理是否成功
公网服务器执行netstat -anp | grep 8022
,如果出现类似下面的结果,则表示SSH反向代理成功。
tcp 0 0 0.0.0.0:8022 0.0.0.0:* LISTEN 6520/sshd: root
四、测试反向代理是否成功
完成上面的步骤以后,就可以通过其他电脑的ssh客户端,连接公网服务器的8022端口了。
# ssh -p 8022 [email protected]
如果连接失败,继续往下看~
五、开放公网服务器端口
如果按照前面的步骤操作以后,发现第四步连接不上,可能是公网服务器需要开放端口。
- 首先需要在服务器管理面板开放
8022
端口,每个供应商可能操作不同,这里不再赘述。 - 我用的服务器系统是
centos 7
,输入命令netstat -tlunp | grep 8022
,得到以下结果:
tcp 0 0 0.0.0.0:8022 0.0.0.0:* LISTEN 6520/sshd: root
可以看到系统开放了8022
端口。然后检查防火墙端口,输入iptables-save | grep 8022
,发现什么也没有输出。说明防火墙将8022
端口拦截了,需要开放防火墙的端口:
firewall-cmd --zone=public --add-port=8022/tcp --permanent
firewall-cmd --reload
第一条命令是添加端口,第二条命令是重载防火墙。看到success
字样后,再次输入iptables-save | grep 8022
可以看到如下字样,则表示防火墙配置成功。这时候再回到第四步测试就可以连接了。
-A IN_public_allow -p tcp -m tcp --dport 8022 -m conntrack --ctstate NEW,UNTRACKED -j ACCEPT
以下内容为复制参考链接一中的原文,并做了注释,已经测试正常
六、编写脚本守护反向代理
1. 设置树莓派免密码登录公网服务器
在内网树莓派中切换到root
账户:sudo su
,然后执行以下命令生成ssh
公钥
ssh-keygen -t rsa -P ''
在/root/.ssh/
中 会生成两个文件id_rsa
与id_rsa.pub
,然后将id_rsa.pub
复制到公网服务器中
scp /root/.ssh/id_rsa.pub [email protected]:~
切换到公网服务器中执行如下代码
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
修改文件权限,这一步很必要
chmod 600 /root/.ssh/authorized_keys
chmod 700 /root/.ssh/
2. 在公网服务器总新建关闭代理的脚本
从树莓派上调用此脚本,可以从公网服务器关闭反向代理进程。
执行sudo vi /root/kill_ssh_agent.sh
,并输入以下内容:
#!/bin/sh
if [ -n "$1" ] && [ "$1" -gt "0" ];then
PID=$(netstat -anp | grep $1 | awk '/sshd/ && !/awk/{print $7}')
PID=${PID%%/*}
if [ -n "${PID}" ];then
kill -9 $PID && exit 0
fi
fi
exit 1
将此脚本保存为kill_ssh_agent.sh
,并记住路径,我的是保存在了/root/kill_ssh_agent.sh
,然后添加可执行权限:
sudo chmod +x /root/kill_ssh_agent.sh
3. 在树莓派上创建反向代理进程守护脚本
在树莓派上执行sudo vi /root/ssh_agent_daemon.sh
,并输入以下内容:
#!/bin/bash
REMOTE_USERNAME=root
REMOTE_SERVER_IP="11.22.33.44"
REMOTE_PORT=8022
#原文中用此命令获取IP
#LOCALHOST_IP=`/sbin/ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tr -d "addr:"`
#其实用下面的代码就可以获取到
#LOCALHOTST_IP=$(hostname -I)
#但是经测试,这么写可能会连接不上的,所以按照之前的写法,直接如下写成本机地址即可
LOCALHOTST_IP="127.0.0.1"
LOCALHOST_PORT=22
while true ;
do
PID=$(ssh -l root ${REMOTE_SERVER_IP} netstat -anp | grep ${REMOTE_PORT} | awk '/sshd/ && !/awk/{print $7}')
PID=${PID%%/*}
if [ -n "$PID" ] && [ "$PID" -gt "0" ];then
sleep 30s
else
/usr/bin/ssh -l root ${REMOTE_SERVER_IP} /bin/sh /root/kill_ssh_agent.sh ${REMOTE_PORT}
/usr/bin/ssh -CqTfnN -R 0.0.0.0:${REMOTE_PORT}:${LOCALHOST_IP}:${LOCALHOST_PORT} ${REMOTE_USERNAME}@${REMOTE_SERVER_IP}
fi
done
exit 0
保存,并添加可执行权限:
sudo chmod +x /root/ssh_agent_daemon.sh
这个路径也要用到。
4. 在公网服务器中,设置 SSH 连接为长连接
sudo vi /etc/ssh/sshd_config
找到ClientAliveInterval
和ClientAliveCountMax
,并按照下面修改:
#每1分钟发送一个心跳信号给客户端
ClientAliveInterval 60
#最大超时次数,客户端不响应则关闭连接
ClientAliveCountMax 3
5. 在树莓派中将守护进程脚本设置为开机启动
sudo vi /etc/rc.local
将下面这一行添加到exit 0
之前
/bin/sh /root/ssh_agent_daemon.sh &
注意脚本路径,这里必须写完整路径
/root/ssh_agent_daemon.sh
,一定不要写成~/ssh_agent_daemon.sh
,否则会启动失败