外网访问内网的解决方案--反向SSH

外网访问内网的解决方案--反向SSH1 SSH 介绍 2 问题 3 原理 4 操作步骤 5 这种反向代理是不稳定的 1 SSH 介绍 A 要与 B 通信 A 生成一对密钥 A 将公钥发送给 B B 拿到公钥 生成一个随机密码串 对称加密的 key 用于认证完成后的通信

大家好,我是讯享网,很高兴认识大家。

1、SSH介绍:

2、问题:

3、原理:

4、操作步骤:

5、这种反向代理是不稳定的


1、SSH介绍:

  • A要与B通信
  • A生成一对密钥
  • A将公钥发送给B
  • B拿到公钥,生成一个随机密码串(对称加密的key,用于认证完成后的通信),并用公钥加密这个密码串,发送给A
  • A拿到密文,用私钥解密,获得到这个随机密码串
  • B继续发送一个利用上个随机密码串加密的数据给A,A收到后用随机密码串解密这个数据
  • A解密正常后通知B
  • 加密通道建立完成,以后的通信都用这个随机密码串加解密

2、问题:

    当你在不在公司或者不在学校的时候,如果想要用secureCRT访问内网的服务器,但是内网IP对外网是不可见的,这时怎么办?又或者内网的网站只对有内网的IP可以访问,但是你连接的是外网,想要访问内网的网站,怎么办呢?最重要的是现在的教育网支持IPv6,改下hosts文件就可以直接访问Google、YouTube这些网站了,但是如果你在外不是连接的教育网,但是想通过学校的服务器作代理访问Google,但是学校服务器的IP对外不可见,怎么使用代理呢?

3、原理:

    之所以很多转发的方法无法应用在这里,就是因为内网主机对外网其实是不可见的,也就是说外部主机不能用一般的方法访问到内部主机。那么我们就想了,能不能用内网主机找外网主机,找到之后再把这条内网主机登陆外网的信道转换成外网主机登陆内网的信道呢?幸运的是,这个方法的确是可行的,这也就是所谓反向ssh最通俗的理解,这就像寄信一样,”虽然我不知道你的地址,但是你知道我的地址,那么你就先给我写封信,告诉我你的地址,然后我不就可以回信给你了么?“。

4、操作步骤:

     由于我们自己使用的电脑未必有外网IP,因此我们需要一个有固定外网IP的服务器(随便搞个腾讯云、阿里云的小机子就行),然后用这台服务器与内网的机子进行通信,如果要用shell登录内网服务器,我们到时候要先登陆自己的服务器,然后再利用这个服务器去访问内网的主机。准备好有固定IP的公网服务器A,以及待访问的内网机器B。两者都开着sshd服务,端口号默认都是22。

(1)介绍一下使用到的ssh参数:

  • 反向代理 :ssh -fCNR
  • 正向代理:ssh -fCNL
-f 后台执行ssh指令 -C 允许压缩数据 -N 不执行远程指令 -R 将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口 -L 将本地机(客户机)的某个端口转发到远端指定机器的指定端口 -p 指定远程主机的端口

讯享网

(2)在内网主机B执行以下命令:

        $ ssh -NCfR 1111:localhost:22 username@IP -p 22

    这条命令的意思是在后台执行(-f),不实际连接而是做port forwarding(-N),做反向ssh(-R),将公网服务器A的1111端口映射成连接内网服务器B与该公网服务器A的反向ssh的端口22。username是你登录服务器A的用户名,IP是服务器A的IP,然后输入登录服务器A的密码即可。执行完这条命令,我们可以在服务器A上看到他的1111端口已经开始监听:

      LISTEN  0  128    127.0.0.1:1111      *:*

(3)在上面的操作中,公网A的这个1111端口就已经映射成了内网主机B的22端口了,现在我们只要ssh到自己的这个端口就行了。首先用secureCRT登录服务器A,然后在服务器A中执行:

     $ ssh username@localhost -p1111

    这里的username为内网服务器的用户名,ssh本机的1111端口就相当于ssh内网服务器B的22端口,成功的登陆了内网的主机了。

(4)绝招:使用内网做代理http请求


讯享网

    在上面的(2)和(3)中我们已经可以通过自己的公网服务器来shell登录内网服务器了,接下来我们如果通过内网服务器做代理翻墙(内网服务器需是教育网IP)呢?其实原理是一样的,上面的反向ssh是把公网服务器A的1111端口映射为内网服务器B的22端口,这样的话可以在A上远程shell登录B,那么我们可不可以映射其它端口呢?比如代理服务器的端口呢,这样内网服务器B就能帮我们做代理了。
    首先在内网服务器B装上squid代理,代理的端口号为3128,接下来在服务器B执行如下命令:

      $ ssh -N -f -R 3000:localhost:3128 username@IP

   username是你公网服务器A的用户名,IP是你的公网服务器A的IP。这条命令的作用是把你公网服务器A的端口号3000映射为内网服务器B的端口3128,意思是说当我们访问公网服务器A的端口号3000时,等价于访问内网服务器B的3128端口。接下来我们在公网服务器A上执行以下命令:

     $ ssh -C -f -N -g -L 3128:localhost:3000 username@localhost

    这条命令的作用是监听3128端口,并把3128端口的请求转发到3000端口。接下来我们可以在浏览器中设置代理:设置的代理IP为你的公网服务器A的IP,代理端口号为3128。设置好代理后,我们的电脑首先访问的是公网服务器A的端口号3128,然后公网服务器A把3128的端口转发到公网服务器A的端口3000,而3000端口恰好映射为内网服务器B的端口号3128,这样的话就相当于使用内网服务器B的3128端口号做代理,这样就可以畅通无阻的访问内网的网站以及可以翻墙喽,厉不厉害!!!

可能会遇到报错: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

处理方式:
       #vim ~/.ssh/known_hosts
    然后删除和你想要登录的IP相关的信息,或者全部删除也行。
为什么?
   第一次连接时,server将已经生成的公钥(已存放在本地)发送给连接方,连接方没有相应的私钥。server重装之后,生成的公钥发生了变化。连接方存放的还是曾经的公钥。因此公钥不匹配。即认同为server身份已变。解决方法是将原来的公钥给删除了,也就是一切重头再来。又開始了第一次的工作。 

5、这种反向代理是不稳定的

  不幸的是这种反向ssh会因为超时而关闭,为此我们需要另外的方法来提供稳定的方向ssh代理隧道。

(1)做好内网服务器到外网服务器的ssh免密码登陆:

  • 登录内网服务器,创建私钥和公钥:
讯享网$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' #-t 指定类型,-f指定文件生成路径,-P指定文件密码(''表示无密码)
  • 将生成的公钥拷贝到外网服务器: 
ssh-copy-id -i .ssh/id_rsa.pub username@IP # 这里的username为外网服务器用户名,IP为外网服务器的IP
  • 拷贝成功,测试连接,此时内网服务器可以免密登录外网服务器
讯享网$ ssh username@IP # 这里的username为外网服务器用户名,IP为外网服务器的IP

(2)用autossh建立稳定隧道

  •  一开始提到,这种反向连接(Reverse Connection)不稳定,可能随时断开,需要内网主机B再次向外网A发起连接,这时需要个“朋友”帮你在内网B主机执行这条命令。它就是Autossh。来看看Autossh的用法:

          $ autossh -M 5678 -NCR 1111:localhost:22 username@IP -p 22   

  • autossh的参数与ssh的参数是一致的,但是不同的是,在隧道断开的时候,autossh会自动重新连接而ssh不会。另外不同的是我们需要指出的-M参数,这个参数指定一个端口,这个端口是外网的B机器用来接收内网A机器的信息,如果隧道不正常而返回给A机器让他实现重新连接。

(3)做好外网服务器到内网服务器的ssh免密码登陆:

  • 登录外网服务器,创建私钥和公钥:
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' #-t 指定类型,-f指定文件生成路径,-P指定文件密码(''表示无密码)
  • 将生成的公钥拷贝到内网服务器: 
讯享网ssh-copy-id -i .ssh/id_rsa.pub username@localhost -p 1111 # 这里的username为内网服务器的用户名
  • 拷贝成功,测试连接,此时外网服务器可以免密登录内网服务器
$ ssh username@localhost -p1111 # 这里的username为内网服务器的用户名 

(4)Linux上配置自动启动autossh,免去每次重启Linux都要重启autossh的麻烦

    Ubuntu开机后会执行/etc/rc.local文件中的脚本,所以我们可以直接在该文件中添加启动脚本:

讯享网vim /etc/rc.local

  添加内容:

su - username -c "/home/username/xxx.sh" # 这里的xxx.sh为需要开机启动的脚本文件

参考:https://www.cnblogs.com/mengfanrong/p/5096590.html
          https://m.jb51.net/article/112524.htm

小讯
上一篇 2025-01-09 21:36
下一篇 2025-03-05 18:24

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/60803.html