反向代理实现内网穿透

发布于 2020-02-12  117 次阅读


靠谱的方法:使用frp

先贴上Github项目链接:https://github.com/fatedier/frp

frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力,且尝试性支持了点对点穿透。

默认你已经有了一个有固定外网ip的云服务器:(有关云服务器的建立:拥有一个自己的云服务器

配置方法:首先先到GitHub项目中的release下载对应系统版本的软件包,可以直接在云服务器中使用wget +链接 直接下载,也可以先在电脑上下载再传到服务器上(这里的坑详见:下载到云服务器的速度比自己的电脑慢好多咋办

服务器端配置

mkdir新建一个解压目录

mkdir -p /usr/local/frp

注释:
-p:确保目录存在,如不存在则新建

使用wget下载

wget -O /usr/local/frp/frp.tar.gz https://github.com/fatedier/frp/releases/download/v0.31.2/frp_0.31.2_linux_amd64.tar.gz

注释
-O:指定下载文件名(可指定路径)

把下载好的文件用命令解压到解压目录

tar -zxvf [tar.gz包路径] -C [解压目录]

注释:
-x:从tar包中解包
-z:通过gzip指令处理备份文件,即后缀gz的tar包
-v:显示指令执行过程
-f:指定备份文件,即tar包
-C:指定目的目录
                                                   

之后进入解压目录, 首先删掉frpc、frpc.ini两个文件 ,之后使用文本编辑器打开frps.ini。

rm frpc frpc.ini

nano frps.ini

这里仅仅介绍最简配置方式,其他特性功能详见github,有中文文档。

在打开的配置文件中写入:

[common]
bind_port = 7000

这里设置了frp使用的服务器端口,如果frp运行在docker环境下或者云服务器有安全组规则,要记得进行端口映射或开放相关端口的外部访问权限。

保存并退出,之后在命令行输入:

./frps -c frps.ini

这样即使用前面的配置文件开启了frp服务。可以看到终端打印出了日志。

如运行出错请检查用户权限或文件的可执行权限

此时终端始终连接到frps的输出,不能执行其他指令,可以使用nohup或screen使frps在后台运行且不会因为ssh连接中断而终止。

客户端配置

和前面一样,先把frp包下载并解压,之后进入解压目录

删除frps,frps.ini

rm frps frps.ini

文本编辑器打开frpc.ini

nano frpc.ini

此处同样使用最简配置,直接对端口进行映射。假设客户端在70,6000-6100端口提供服务,我们打算直接将本地的70端口原样映射到服务器的70端口,6000-6100端口映射到服务器的8000-8100端口。编辑配置如下

[common]
server_addr = x.x.x.x
server_port = 7000

[range:test_tcp]
type = tcp
local_ip = 127.0.0.1
local_port = 70,6000-6100
remote_port = 70,8000-8100

common段配置远端服务器的地址和提供frp服务的端口

range段定义了一个名为test_tcp的端口范围,把本地网络上的端口映射到服务器的端口,frpc会自动解析配置,并将其拆分成多个代理。

保存并退出,在命令行输入启动命令

./frpc -c ./frpc.ini

可以看到命令行输出了日志,代理创建成功。

此时终端始终连接到frpc的输出,不能执行其他指令,可以使用nohup或screen使frpc在后台运行且不会因为ssh连接中断而终止。

其他的配置详见github项目地址,文档很详细,且有完整的配置文件案例。后面对连接安全相关的配置会再更新。

不咋靠谱的方法:利用ssh的转发

其实ssh的转发更好的用法是通过ssh代理对不带加密的通信进行加密,以提高安全性。但我们也可以使用ssh转发建立代理,访问原本访问不到的资源(

但是ssh的连接时间限制导致原生的openssh并不能提供稳定的代理服务,这时候借助如autossh等工具自动维护ssh连接即可。下面来讲怎么使用:

写在前头的注意事项:

  • tcp连接是双向的,只要建立了连接数据就可以双向传递
  • 建立连接的过程是有方向的,从发起方指向接受方
  • 实现内网穿透参考使用ssh的远端转发功能
  • 动态转发可以实现socket代理穿透防火墙

本地转发

命令:-L (localhost):localport:remotehost:remotehostport sshserver

注释:localhost            本地监听,可忽略,此时侦听127.0.0.1只允许本机访问
      localport       本机开启的端口号
      remotehost      最终连接机器的IP地址
      remotehostport       转发机器的端口号
      sshserver       转发机器的IP地址 
选项:-f 后台启用
     -N 不打开远程shell,处于等待状态(不加-N则直接登录进去)
     -g 启用网关功能 

设置一个情景:

有一个个人主机:ip:192.168.0.1
另一个网络,其网关ip:192.168.0.2,网关服务器开启ssh端口并关闭了其他端口,在这个网关的内网,有一个主机,其ip:192.168.1.3

此时想要用个人主机通过telnet连接内网主机,很明显是不行了,所有流量都会被网关服务器拦截

但是我们可以利用ssh连接网关服务器,利用ssh代理访问内网主机

在个人主机上执行命令:

ssh 5566:192.168.1.3:23 root@192.168.0.2

这时候会在本地主机上随机开放一个端口,使用ssh连接到网关的22端口

现在访问本机上的5566端口

telnet 127.0.0.1 5566

可以发现已经能够访问内网主机了

登录网关服务器,会发现服务器上开放了一个随机端口连接到内网主机的23端口。

此时本地经过5566端口的流量会通过ssh传输到网关,网关服务器解包,开启一个端口作为代理客户端,连接到内网主机的23端口,实现通信。

如果需要将个人主机作为媒介,使网络中其他主机通过个人主机的开放端口telnet连接内网主机,需要指定侦听网段,即执行:

ssh 0.0.0.0:5566:192.168.1.3:23 root@192.168.0.2

0.0.0.0即所有ip均可访问个人主机的开放端口了。其他主机的连接方式:

telnet 192.168.0.1 5566

远端转发

命令:-R sshserverhost:sshserverport:remotehost:remotehostport sshserver

说明: sshserverhost        被转发机器的监听网络,默认127.0.0.1只允许本机访问
      sshserverport         被转发机器开启的端口号
      remotehost          最终连接机器的IP地址
      remotehostport        被转发机器的端口号
      sshserver             被转发机器的IP地址  
选项:-f 后台启用
     -N 不打开远程shell,处于等待状态(不加-N则直接登录进去)
     -g 启用网关功能  

同样一个情景,不同的是这次网关服务器关闭了所有端口,拒绝外部的访问。

有一个个人主机:ip:192.168.0.1
另一个网络,其网关ip:192.168.0.2,网关服务器关闭了所有端口,在这个网关的内网,有一个主机,其ip:192.168.1.3

现在我们想要从个人主机上telnet登录内网主机,直接从个人主机上访问就不可能了,需要在网关服务器上进行设置。

在网关服务器上执行命令:

ssh -R 2233:192.168.1.2:23 root@192.168.0.1

此时网关服务器通过随机端口访问个人主机的22端口建立ssh连接,并让个人主机的ssh服务器监听2233端口。

个人主机上telnet访问本机2233端口:

telnet 127.0.0.1 2233

此时网关服务器利用随机端口做代理客户端,连接内网主机的23端口。通道建立完成,可以成功访问了。

2233端口的流量经ssh隧道转发到网关服务器上,网关服务器再将流量转发到内网主机的23端口。

我们要实现的反向代理内网穿透就可以通过ssh的远端代理实现,同样的,需要使所有ip均可以访问个人主机的开放端口使用代理连接,执行:

ssh -R 0.0.0.0:2233:192.168.1.2:23 root@192.168.0.1

其他用户telnet连接该个人主机的2233端口即可连接到内网主机了。

动态转发

命令: ssh -D localhost:localport sshserver

说明: localhost        被转发机器的监听网络,默认127.0.0.1只允许本机访问
      localport         被转发机器开启的端口号
      sshserver         提供转发的机器的IP地址  
选项:-f 后台启用
     -N 不打开远程shell,处于等待状态(不加-N则直接登录进去)
     -g 启用网关功能  

设置一个情景:

本机192.168.0.1经过一个网关192.168.0.2访问外部192.168.1.x网络,但有一个外部网络的主机192.168.1.4被网关拦截,无法访问,此时有一个ip为192.168.1.3的外部主机可以被直接访问,且外部网络主机直接可以访问,此时就需要实现通过192.168.1.3代理访问被拦截的主机192.168.1.4

在本机上执行以下命令:

ssh -D 1090 root@192.168.1.3

此时本地主机利用随机端口访问192.168.1.3的外部主机22端口建立ssh连接,并在本地的1090端口开启一个socks5服务,所有通过本地socks5服务的请求都会透过ssh传输到192.168.1.3,即请求的主机和端口透过192.168.1.3进行请求,再把请求的结果返回内网的socks5服务器。

同样的,要把个人主机作为代理开放给网络上的其他主机,需指定监听ip,执行:

ssh -D 0.0.0.0:1090 root@192.168.1.3

在其他主机上设置socks5代理,服务地址和端口设置成该主机和开放的1090端口即可。

ssh还不止于此

ssh还支持其他参数:

 -C 为压缩数据,-q 安静模式,-T 禁止远程分配终端,-n 关闭标准输入,-N 不执行远程命令 。。。等等等等

SSH 为建立在应用层基础上的安全协议。SSH 是较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。 用法还有很多。。。以后再多了解了解

另外,一些端口转发还可以通过linux的防火墙配置iptable实现,由于使用的是底层服务,性能更好。这里实现的端口转发并不是很稳定,不适宜长时间运行,ssh连接因为意外中断就不行了,可借用脚本或软件自动重连,维护连接,但作为有限条件下的临时解决方案,还是很方便的。


当其他人都认为你要鸽的时候,你鸽了,亦是一种不鸽