利用SSH 反向代理 ,实现跨局域网连接家里的linux 主机 (树莓派)
软硬件环境:
A、 树莓派 3b+ 1个,安装于我租住的房间中。联网经过多层NAT(网络地址转换),故无公网IP
B、一个有公网IP的VPS(虚拟主机),我使用的是国外的vultr,您也可以选择阿里云,亚马逊等各种厂商产品。这台机器的操作系统为 centos 7.0 ,IP 为 A.A.A.A
C、一台普通的电脑
操作步骤:
1、修改公网服务器 ssh 配置文件 sshd_config 文件:
# vi /etc/ssh/sshd_config 添加 GatewayPorts yes # 重启 ssh 服务 # centos 7 systemctl reload sshd.service # centos 7 以下 service sshd reload
2、局域网中的树莓派连接公网服务器反向代理端口:
这段代码在本地树莓派中执行,这段代码是将本地机器的22端口绑定公网服务器的7233端口
ssh -CqTfnN -R 0.0.0.0:7233:127.0.0.1:22 root@A.A.A.A
3、检查反向代理是否成功:
在公网服务器中执行如下代码,如果出现相同结果则表明 SSH反向代理成功
netstat -anp | grep 7233 tcp 0 0 0.0.0.0:7233 0.0.0.0:* LISTEN 2392/sshd tcp 0 0 :::7233 :::* LISTEN 2392/sshd
4、测试是否能通过反向代理连接局域网中的树莓派:
这时,你可以通过普通电脑的ssh客户端 连接 公网服务器的7233端口。测试连接是否成功
# 这里需要注意的是pi为树莓派的登陆用户名,A.A.A.A为公网服务器地址
ssh -p 7233 pi@A.A.A.A
编写脚本守护反向代理
1、设置树莓派免密码登录公网服务器:
# 在内网树莓派中执行 ssh-keygen -t rsa -P '' # 然后一直按回车, 于是在~/.ssh/中 会生成两个文件 id_rsa 与 id_rsa.pub # 将id_rsa.pub 复制到公网服务器中 scp ~/.ssh/id_rsa.pub root@A.A.A.A:~ #输入密码 #切换到公网服务器中执行如下代码 cat ~/id_rsa.pub >> ~/.ssh/authorized_keys #修改文件权限,这一步很必要 chmod 600 .ssh/authorized_keys chmod 700 .ssh/
2、编写公网服务器关闭代理脚本
#!/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
将脚本内容保存为: /usr/local/bin/kill_ssh_agent,
并赋予执行权限:chmod +x /usr/local/bin/kill_ssh_agent
3、编写客户端代理守护脚本 (注意配置服务器端口及IP)
#!/bin/bash ROMOTE_USERNAME=root ROMOTE_SERVER_IP="A.A.A.A" ROMOTE_PORT=7233 ###[ /sbin/ifconfig|sed -n '/inet addr/s/^[^:]*:\([0-9.]\{7,15\}\) .*/\1/p'|grep -v 127.0.0.1 ] LOCALHOST_IP=`/sbin/ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"` LOCALHOST_PORT=22 while true ; do PID=$(ssh -l root ${ROMOTE_SERVER_IP} netstat -anp | grep ${ROMOTE_PORT} | awk '/sshd/ && !/awk/{print $7}') PID=${PID%%/*} if [ -n "$PID" ] && [ "$PID" -gt "0" ];then sleep 30s else /usr/bin/ssh -l root ${ROMOTE_SERVER_IP} /usr/local/bin/kill_ssh_agent ${ROMOTE_PORT} /usr/bin/ssh -CqTfnN -R 0.0.0.0:${ROMOTE_PORT}:${LOCALHOST_IP}:${LOCALHOST_PORT} ${ROMOTE_USERNAME}@${ROMOTE_SERVER_IP} fi done exit 0
将脚本内容保存为: /usr/local/bin/ssh_agent_deamon,
并赋予执行权限:chmod +x /usr/local/bin/ssh_agent_deamon
4、设置 SSH 连接为长连接 (在公网服务器操作)
vi /etc/ssh/sshd_config #每1分钟发送一个心跳信号给客户端 ClientAliveInterval 60 #最大超时次数,客户端不响应则关闭连接 ClientAliveCountMax 3
5、设置为开机启动 (在内网机器操作):
vi /etc/rc.local /usr/local/bin/ssh_agent_deamon &
遇到的问题:
理论上按照上面的步骤操作,反向代理就能成功了。但是操作中我还是遇到了不少问题。我这里把他们列出来
1.防火墙
防火墙会阻止未经许可端口的数据通过,所以允许端口的防火墙通过是很有必要的。您需要确认每台机器是否有防火墙,如果有防火墙,是否正确的配置了防火墙。
另外,在公网服务器中,很多服务商提供了额外的防火墙服务。在他们的网页控制台可以看到。我的公网服务器就有服务商提供的额外防火墙。我的做法是将centos自带的防火墙关掉,并禁止开机启动。然后配置服务商提供的防火墙,允许反向代理的端口通过。当然您也可以两个防火墙都开着,但要确保他们都通过了您需要的端口。
2.ssh自动登录失败:
自动登录失败,可能因为你的秘钥文件权限不对。ssh秘钥登录对文件权限很敏感。还有我犯了一个错误,我在公网服务器生成秘钥,然后放到本地。导致一度登录失败。正确的做法应是在内网生成秘钥,放到外网服务器中
3.守护脚本不能成功设置反向代理问题:
守护代理是通过 /etc/rc.local 开机启动的,其默认用户为root。我在生成秘钥的时候一直用的普通用户,于是导致在开启自动启动时运行失败。解决办法是,切换到内网机器的root用户,再生成一次秘钥,将秘钥追加到公网服务器的authorized_keys文件中。如果新买的机器不知道root用户的密码是什么,可以看一下参考文章的第4个连接
参考的文章:
https://www.cnblogs.com/phpdragon/p/5314650.html
https://blog.csdn.net/Post_Yuan/article/details/78603212
http://www.mamicode.com/info-detail-2128504.html
https://blog.csdn.net/faryang/article/details/50779767
原文参考:https://blog.csdn.net/qq_28766327/article/details/82117409
使用autossh自动代替守护脚本
如果条件运行,可以在客户端安装autossh,autossh 是一个用来监控 SSH 链接,并自动进行重连的工具。
ubuntu/debian下的安装
sudo apt-get install autossh
使用的方式非常简单:
autossh -M 12345 -f -CqTfnN -R 0.0.0.0:7233:0.0.0.0:22 root@A.A.A.A
关于autossh的原理,参考:https://blog.csdn.net/wesleyflagon/article/details/85304336
谢谢您的来访,欢迎关注交流!以下是我的个人联系方式
电子邮箱:spring.wind2006@163.com,QQ:402085437,微信号:tm402085437