ssh 反向代理

ssh反向代理

1 基本操作

设 A主机 内网主机 192.168.37.132 sshd 服务开在22端口

B主机 外网主机 122.10.10.10 sshd 服务开在22端口

在A主机使用如下命令

ssh -NR 1234:localhost:22 [email protected] -p 22

指派B的1234端口映射到自己的22端口上,B的ssh开在22上(-p 22)

可简写为

ssh -NR 1234:localhost:22 [email protected]

-R remote_free_port:localhost:local_ssh_port

指派远程上的 remote_free_port 到本地地址上的 local_ssh_port上

建立远程SSH隧道(隧道服务端建立监听端口)

将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口.

-N 不执行远程指令,否则会出现一个B主机的shell,可以执行命令

参数详解:https://www.jianshu.com/p/5865c9c39acc

A主机执行该命令的意思是将B主机的1234端口绑定到A主机的22端口

就是说B主机1234端口接收到的数据都会转发给A主机的22端口

这样我们就可以在B主机使用命令:

ss -ant

可以看到B主机的127.0.0.1:1234端口已经占用了

说明ssh反向连接成功了

接下来在B主机使用如下命令即可连接处于内网的A主机

ssh user@localhost -p 1234

2 免密码

另外我们可以使用ssh-copy-id 命令实现公匙登录,每次就不用输入密码了。

A,B主机都各自将对方的id_rsa.pub加入自己的authorized_keys,这样A主机反向连接不需要输入密码,B主机连接A也不需要输入密码了。

不懂ssh-copy-id的话可以看看我的另一篇关于ssh免密登录的博客

3 修改sshd_config使得允许B公网主机作为网关

基本的操作后你的使用方法是:

ssh到公网服务器B,有了一个B的shell,然后用这个B的shell,ssh本地的1234端口,到A。

那么使用的方法如下:

ssh [email protected] -p 22
ssh root@localhost -p 1234

但是可以将/etc/ssh/sshd_config配置文件中的GatewayPorts属性改为yes。

GatewayPorts:

是否允许远程主机连接本地的转发端口。默认值是"no"。
sshd(8) 默认将远程端口转发绑定到loopback地址。这样将阻止其它远程主机连接到转发端口。
GatewayPorts 指令可以让 sshd 将远程端口转发绑定到非loopback地址,这样就可以允许远程主机连接了。
"no"表示仅允许本地连接,"yes"表示强制将远程端口转发绑定到统配地址(wildcard address),

这样一来,你就可以直接去连接B的1234端口了,而不用先进入B,获得一个B的shell。

直接像下面这样使用:

ssh [email protected] -p 1234

4 配置config为服务器取别名,实现tcp持久化连接

同时,配置~/.ssh/config会使连接更加简单。

vim ~/.ssh/config

然后写入你需要的内容,例如:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/multiplex/%r@%h:%p
    ControlPersist 4h
    ServerAliveInterval 6
    ServerAliveCountMax 200
    Compression yes

Host github.com
    Hostname ssh.github.com
    User "*************@qq.com"
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa
    Port 443

Host vps
    Hostname **.**.**.**
    User root
    Port 1289
    IdentityFile ~/.ssh/id_rsa

Host shiyanshi
    Hostname **.**.**.**
    User root
    Port 8444
    IdentityFile ~/.ssh/id_rsa

上述配置的意思大致解释如下:

对于所有Host,就是主机,
自动使用tcp多路复用
控制tcp的临时文件放在multiplex文件夹下(需要自己创建)
一个tcp连接的持续时间是4小时,4小时内不管啥时候重连,都是用的这个tcp,可能会快一点吧,哈哈
每6秒查看服务器是否还活着,保存连接
连续200次查看
传输的数据确定压缩

对于github.com
连接的主机的名字是ssh.github.com
user是*************@qq.com
使用id_rsa这个私匙
端口是443

对于vps
hostname(即ip) 是**.**.**.**
连接过去用的用户是 root
对面的端口是1289

...

有了这个,你根据你的情况配置好config后,就可以用别名来连接了。

如:

ssh vps

5 使用脚本帮助断开重连

上述config的配置也包含了持久化操作,可以保证在不出现意外断开情况时,保证连接通畅,但是如果出现断网,等意外断线情况时如何重连呢?

有的博客说是使用autossh帮助我们掉线重连,但是经我自己测试,发现这个东西并没有什么卵用,配置文件的说明也找不到,并不能帮助我们断线重连。

这个不靠谱的autossh的参考链接:https://zhuanlan.zhihu.com/p/112227542

有兴趣可以看看,反正我感觉是没啥卵用。

靠谱的方法还是自己写个shell脚本。

第一步:公网服务器配置

修改公网主机 B 的 SSH 配置文件/etc/ssh/sshd_config

GatewayPorts yes

这样可以把监听的端口绑定到任意 IP 0.0.0.0 上,否则只有本机 127.0.0.1 可以访问。

重启 sshd 服务

sudo service sshd restart

第二步:断线免密登录自动重连

ssh 反向链接会因为超时而关闭,如果关闭了那从外网连通内网的通道就无法维持,为此我们需要结合免密码登录及 AutoSSH 来提供稳定的 ssh 反向代理隧道。

1、在内网主机 A 上产生公钥和私钥

ssh-keygen

然后按三次回车执行默认选项生成公钥和私钥。会生成密钥文件和私钥文件 id_rsa,id_rsa.pub 或 id_dsa,id_dsa.pub

2、拷贝秘钥 在内网主机 A 上继续执行如下命令,将内网主机 A 上的秘钥文件 copy 到公网主机 B 中。

ssh-copy-id  username@ip

其中“username”是公网主机 B 的用户名,ip 为公网主机 B 的 ip,然后按照提示输入公网主机 B 的密码就完成了。

第三步:写脚本实现断线重连

思路是使用ss命令检查我们的反向代理是否存在,如果不存在说明断开了,那么就重连

样例:

rproxy.sh:

#!/bin/bash

while true
do

ssans=`ss -ant | grep "192.168.42.131:22" | wc -l`

if [ $ssans == 0 ]
then
        ssh -fNR 8765:localhost:22 [email protected] -p 22 >/dev/null 2>&1
fi

sleep 60

done

基本说明:

首先用变量ssans接住检查结果。

然后如果检查结果为0,说明连接断开了,那么就去连,并将输出和错误信息重定向到/dev/null中

第四步:开启自启动

方法一,直接修改rc.local

vi /etc/rc.d/rc.local

添加内容:

(bash rproxy.sh &)
chmod 755 /etc/rc.d/rc.local

方法二,添加服务

把上边的rproxy.sh脚本放在/etc/rproxy这里(哪里都行,你对应修改下面脚本就好)

去/etc/init.d/下创建文件rproxy(随便叫啥名字都行,不一定是这个)

#!/bin/bash
### BEGIN INIT INFO
# Provides: rproxy
# Required-Start: $remote_fs $network
# Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: rproxy
### END INIT INFO

case "$1" in
start)
  ps -aux | grep "rproxy.sh" | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1
  ps -aux | grep "xxx.xxx.xxx.xxx" | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1
  (bash /etc/rproxy/rproxy.sh > /dev/null 2>&1 &)
  ;;
stop)
  ps -aux | grep "rproxy.sh" | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1
  ps -aux | grep "xxx.xxx.xxx.xxx" | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1
  ;;
restart)
  ps -aux | grep "rproxy.sh" | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1
  ps -aux | grep "xxx.xxx.xxx.xxx" | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1
  (bash /etc/rproxy/rproxy.sh > /dev/null 2>&1 &)
  ;;
esac
exit 0

修改权限

chmod 755 rproxy

开启服务

update-rc.d rproxy defaults

这样以来他就实现了开机自启,并且你可以想服务一样操作了

service rproxy start
service rproxy stop
service rproxy restart
文章目录