利用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

 

posted @ 2020-06-10 10:15  程序人生♨︎  阅读(1024)  评论(0编辑  收藏  举报