代理和穿透还能这么玩?

6,408 阅读13分钟

前言

远程桌面是我每天都要用到的东西,临时在家远程公司电脑排查问题,又或者之前广州疫情,需要居家办公远程公司电脑工作。

远程工具其实有很多,如Todesk、TeamViewer、RustDesk、向日葵等,但我在用过之后都觉得这些不好用,远不如微软自带的远程桌面工具更好用,但这款远程工具却只支持局域网,而我又有在家远程公司电脑的需求,到后来我发现用代理和穿透......

什么是内网穿透

简单来说,就是让处于局域网内网的服务,能够让公网访问到。在公司环境,一般都是整个公司的网络可能分配到公网IP,但内网用的都是局域网IP,经过一层NAT转换的;又或者家用宽带,一般都是整个大内网,并不会有公网IP,所以想要让内网的服务能够提供给外网访问,则需要用到内网穿透。

一般内网穿透,需要引入一台公网的服务器来实现数据包的转发,通过在公共网络上(如互联网)建立一个中转服务器,将来自私有网络的数据包转发到需要连接的设备上,从而实现设备之间的安全通信。像常用的工具有frp、ngrok等。

什么是网络代理

代理其实就是让别人帮你做某事。放在计算机的世界中,就是客户端在访问服务器时,中间引入了一层代理服务器,通过代理服务器来帮助客户端访问服务器。而这个代理服务器的存在位置,将区分是正向代理还是反向代理。

正向代理

正向代理是代理客户端向互联网发起请求,这种方式主要可以隐藏客户端,可能多个客户端会通过一个代理服务器访问,而在服务器看来,只有代理服务器来访问,并不知道是哪个客户端发起的访问。

反向代理

反向代理在互联网环境中,一般是存在于服务端这一端,用于隐藏服务器的真实位置,又或者为服务器提供负载均衡等作用。客户端并不知道自己访问的是哪个服务器。

为什么要用代理+穿透

可能会有人会疑问,已经有内网穿透了,直接访问穿透服务的端口也可以连接,但为什么还要再加一层代理呢?

是因为我的云服务器,部署了好多服务,如frp、portainer、web服务,mysql以及redis等,为此我可能需要为每个服务都开放一个端口到公网中,但本着服务器开放的端口越少越安全,所以我原来就做了一层反向代理,通过代理来访问这些服务,只需要开放代理服务一个端口,便可以直接访问我云服务器上的所有服务,而且用这种方式,我在文章后面还会提到其他的一些场景。

搭建Socks5代理

这里使用了ss5服务,到ss5官网下载最新的源码包,官方并没有提供docker版本的,docker仓库上都是个人开发者构建的镜像,而且我也不想ss5和docker绑定在一起,所以选择源码包安装。

ss5官网:ss5.sourceforge.net/

关于系统版本,我用的是centos 7,一直偏爱centos 7,centos 8也停止支持了,所以这里以centos 7为准。

下载编译安装ss5

# 安装gcc编译和ss5所需要的依赖包
[root@dsx ~]# yum install -y gcc openldap-devel pam-devel openssl-devel cyrus-sasl-devel# 进入`/usr/local`目录下载ss5源码包
[root@dsx ~]# cd /usr/local && wget https://phoenixnap.dl.sourceforge.net/project/ss5/ss5/3.8.9-8/ss5-3.8.9-8.tar.gz# 解压并进入目录,并编译安装ss5
[root@dsx local]# tar -zxvf ss5-3.8.9-8.tar.gz
[root@dsx local]# cd ss5-3.8.9
[root@dsx ss5-3.8.9]# ./configure && make && make install

配置ss5

主要是修改默认端口和添加账号访问,如果需要涉及其他安全策略,则可以查看官网的配置文档进行配置。

ss5.sourceforge.net/configurati…

  • 安装成功后,修改 /etc/sysconfig/ss5,将SS5_OPTS=" -u root "取消注释,并添加0.0.0.0:14567,目的是修改默认端口,使用默认端口不安全。

-u root表示ss5服务器以root身份运行,-b 0.0.0.0:14567表示服务器将监听本地所有网络的14567端口

[root@dsx ss5-3.8.9]# vi /etc/sysconfig/ss5
# Add startup option here
SS5_OPTS=" -u root -b 0.0.0.0:14567"
  • 开启验证,修改ss5配置文件 /etc/opt/ss5/ss5.conf,将下面两个地方的注释放开,修改auth行的Authentication列,将“-”改为“u”,修改permit行的Auth列,将“-”改为“u”。
[root@dsx ss5-3.8.9]# vi /etc/opt/ss5/ss5.conf
# ///////////////////////////////////////////////////////////////////////////////////
#       SHost           SPort           Authentication
#
auth    0.0.0.0/0               -               u
​
#/////////////////////////////////////////////////////////////////////////////////////////////////
#      Auth     SHost           SPort   DHost           DPort   Fixup   Group   Band    ExpDate
#
permit u        0.0.0.0/0       -       0.0.0.0/0       -       -       -       -       -
  • 添加访问账号密码,修改 /etc/opt/ss5/ss5.passwd 文件,一行对应一个账号,用户名和密码用空格隔开。
[root@dsx ss5-3.8.9]# vi /etc/opt/ss5/ss5.passwd 
user1 pwd2

启动ss5

  • 设置ss5服务开机自启动,并启动ss5代理
# 添加ss5启动脚本的执行权限
[root@dsx ~]# chmod +x /etc/init.d/ss5
# 将ss5添加到系统服务中,会随着系统启动而启动
[root@dsx ~]# chkconfig --add ss5
# 重新启动ss5服务
[root@dsx ~]# systemctl restart ss5#如果用的版本是3.8.9,则还需要在系统启动时创建/var/run/ss5文件夹,否则ss5无法正常启动
[root@dsx ~]# vi /etc/rc.d/rc.local
mkdir /var/run/ss5
# 保存后,记得rc.local需要设置执行权限
[root@dsx ~]# chmod +x /etc/rc.d/rc.local
  • 防火墙放行ss5服务端口,并刷新防火墙策略使之生效
# 设置14567端口永久放行
[root@dsx ss5-3.8.9]# firewall-cmd --add-port=14567/tcp --permanent
success
[root@dsx ss5-3.8.9]# firewall-cmd --reload
success

可能遇到的问题

  • 刚安装完用systemctl启动或重启ss5时可能会报错
[root@dsx ss5-3.8.9]# systemctl restart ss5
Warning: ss5.service changed on disk. Run 'systemctl daemon-reload' to reload units.
# 这时候只需要刷新一下systemctl管理器即可
[root@dsx ss5-3.8.9]# systemctl daemon-reload
  • 如果出现Unit not found无法启动,则需要先用chkconfig将ss5加入到系统服务中
[root@dsx ss5-3.8.9]# systemctl restart ss5
Failed to start ss5.service: Unit not found.
[root@dsx ss5-3.8.9]# chkconfig --add ss5
  • 重启后无法启动问题

如果没设置开机自动创建 /var/run/ss5文件夹,会导致ss5无法正常启动,服务是启动的,但使用netstat -tunlp查看却无监听端口

systemctl status ss5查看可发现是因为报了Can't create pid file /var/run/ss5/ss5.pidCan't unlink pid file /var/run/ss5/ss5.pid

[root@dsx ss5-3.8.9]# systemctl status ss5
 ss5.service - SYSV: This script takes care of starting and stopping ss5
   Loaded: loaded (/etc/rc.d/init.d/ss5; bad; vendor preset: disabled)
   Active: active (exited) since  2023-03-19 09:37:55 CST; 19s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 1030 ExecStart=/etc/rc.d/init.d/ss5 start (code=exited, status=0/SUCCESS)
    Tasks: 0
   Memory: 0B

3 19 09:37:55 localhost.localdomain systemd[1]: Starting SYSV: This script takes care of starting and stoppin...5...
3 19 09:37:55 localhost.localdomain ss5[1030]: /etc/rc.d/init.d/ss5:  18 行:[: =: 期待一元表达式
3 19 09:37:55 localhost.localdomain ss5[1030]: [71B blob data]
3 19 09:37:55 localhost.localdomain ss5[1030]: Can't unlink pid file /var/run/ss5/ss5.pid
3 19 09:37:55 localhost.localdomain ss5[1030]: done
3 19 09:37:55 localhost.localdomain systemd[1]: Started SYSV: This script takes care of starting and stopping ss5.
Hint: Some lines were ellipsized, use -l to show in full.

此时只需要手动创建 /var/run/ss5文件夹并重启ss5服务即可启动,再重新根据上面章节启动ss5最后的小点进行配置

[root@dsx ss5-3.8.9]# mkdir /var/run/ss5 && systemctl restart ss5
[root@dsx ss5-3.8.9]# systemctl status ss5
 ss5.service - SYSV: This script takes care of starting and stopping ss5
   Loaded: loaded (/etc/rc.d/init.d/ss5; bad; vendor preset: disabled)
   Active: active (running) since  2023-03-19 09:49:22 CST; 4s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 6896 ExecStop=/etc/rc.d/init.d/ss5 stop (code=exited, status=0/SUCCESS)
  Process: 15098 ExecStart=/etc/rc.d/init.d/ss5 start (code=exited, status=0/SUCCESS)
    Tasks: 1
   Memory: 1.1M
   CGroup: /system.slice/ss5.service
           └─15107 /usr/sbin/ss5 -t -u root -b 0.0.0.0:14567

3 19 09:49:22 localhost.localdomain systemd[1]: Starting SYSV: This script takes care of starting and stoppin...5...
3 19 09:49:22 localhost.localdomain ss5[15098]: /etc/rc.d/init.d/ss5:  18 行:[: =: 期待一元表达式
3 19 09:49:22 localhost.localdomain ss5[15098]: [33B blob data]
3 19 09:49:22 localhost.localdomain systemd[1]: Started SYSV: This script takes care of starting and stopping ss5.
Hint: Some lines were ellipsized, use -l to show in full.

测试连接

服务是部署在云服务器上,所以记得还需要开放云服务器的防火墙端口。在客户端的软件上,我选了proxifier这款软件来进行代理的连接。

下载地址:www.proxifier.com/download/Pr…

安装后直接打开,需要先配置代理服务器,选择Profile->Proxy Servers进行服务器配置,输入上面配置的地址、端口、用户名和密码,可以点击Check进行验证看是否能连接,然后点击OK进行保存。

成功连接并保存后,需要配置代理规则,即配置哪些IP访问会走代理,哪一些不走代理。

代理服务是部署在云服务器上,我们通过代理访问云服务器时,可直接通过云服务器的内网地址来进行访问,因此在配置代理规则时,需要将访问云服务器内网地址的配置为走代理,其他地址均不拦截。依次点击Profile-> Proxification Rules

新建一条代理规则,比如我的服务器内网地址是10.0.12.3,则需要点击Add... 添加一条10.0.12.3的代理规则,走向上面配置的代理服务器。

保存后通过内网地址访问服务器上的服务,可以看到在服务器没开放其他端口时,也是可以访问到服务的。

socks5安全问题

要注意的是socks5并不是一种安全的协议,socks5协议中传输的数据都是明文的,哪怕是设置了连接验证,用户名和密码都是明文的,可以从下图抓包socks5数据包可以看出。

不过我觉得自己用的话也可以不用太担心这种情况,除非别人能够轻而易举抓取到你的数据包,你也可以通过限制访问ip,或者使用TLS证书来进行加密,确保安全性。

部署frp服务

服务端部署

部署完ss5服务后,需要部署frp,将公司的电脑穿透到公网服务器上。

frp下载地址:github.com/fatedier/fr…

frp官网地址:gofrp.org/docs/

# 下载frp, 并将frp上传到服务器上的/usr/lcoal目录
[root@dsx ~]# cd /usr/local
[root@dsx local]# tar -zxvf frp_0.48.0_linux_amd64.tar.gz 
[root@dsx local]# mv frp_0.48.0_linux_amd64 frp
[root@dsx local]# ls frp
frpc  frpc_full.ini  frpc.ini  frps  frps_full.ini  frps.ini  LICENSE

可以看到frp文件夹里面的结构,frps是服务端用到的程序,frps.ini则是服务端程序用到的配置文件;frpc是客户端用到的程序,而frpc.ini则是客户端程序用到的配置文件。其实就是frps是我们云服务器需要运行的,而frpc是公司电脑上需要运行的。

先对frps.ini进行配置,修改了一下frp服务连接的端口和验证的token,这个端口也需要在防火墙上进行开放,这样公司电脑在没有启动proxifier也可以进行远程。

frp是一个很强大的内网穿透工具,需要其他功能的话可以查看官网文档自行配置。

[root@dsx frp]# vi /usr/local/frps.ini
[common]
bind_port = 20000
token = 123456# 防火墙放行20000端口
[root@dsx frp]# firewall-cmd --add-port=20000/tcp --permanent
success
[root@dsx frp]# firewall-cmd --reload
success
​
# 启动frp服务,如果有需要可以写个配置文件将frps服务添加到系统服务,用systemctl命令来调用
[root@dsx frp]# ./frps -c frps.ini
# 需要后台运行的可以使用下面的语句
[root@dsx frp]# nohup /usr/local/frp/frps -c frps.ini >> /usr/local/frp/run.log &# 设置开机自启动,添加运行脚本,并将运行结果输出到frp目录下的
[root@dsx frp]# vi /etc/rc.local
/usr/local/frp/frps -c frps.ini >> /usr/local/frp/run.log

开启远程桌面

在连接前,公司电脑还需要开启远程桌面访问,可以在此电脑->高级系统设置->远程中,开启远程桌面。

修改默认远程端口

远程桌面用到的默认端口是3389,之前大学有过勒索病毒利用3389端口进行传播,学校还因此将3389的网络包屏蔽了(上课需要用到远程),还好当初我已经换成其他端口了,所以对我没什么影响。这里还是将默认的端口改成其他比较好。

  • win+R打开运行,并输入regedit回车打开注册表
  • 查找HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp,然后修改PortNumber的子键值

  • 查找HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp,然后修改portnumber的值
  • 两个值修改后重启电脑即可

客户端连接

客户端此时还需要运行frpc来连接frps服务端,还需要将frpc服务加入到系统服务中,并且可以开机自启动。我在github上找了一个很好用的frp管理器,内置了frpc,可以可图形化管理多份配置文件,还能将服务注册到系统服务中,下面附上github地址。

frp管理器:github.com/koho/frpmgr

frp管理器下载地址:github.com/koho/frpmgr…

将程序下载并安装后,新增一个配置,填入服务器的ip,连接端口,并在认证标签页填写设置的token。

选择刚才新建的配置文件,点击添加,添加两条规则,分别是tcp和udp,将本地的8659映射到服务器上的28659端口,点击保存即可。

接着在自己的电脑上,使用mstsc远程工具进行访问,记得要先开启proxifier代理客户端,使用快捷键win+R输入mstsc打开远程桌面,输入内网ip+上面设置的端口:10.0.12.3:28659,输入账号密码即可连接上公司的电脑。

一点想法

其实我在家里还有一台服务器,部署了挺多服务的,如网盘、Mysql、Redis、Aria2、Jenkins、plex等服务,还有一些摄像头的设备,如果每个服务都开放一个端口出来,肯定是不够安全的,而且开启太多端口映射,也会让路由器的速度变慢,所以代理这时候就可以派上用场了,利用代理仅需要开放一个端口映射即可访问这些服务,因为我之前申请到动态公网IP,所以能直接用DDNS来访问到家里的服务。

如果是所在地区没法申请动态公网IP的,还可以做一个变换,利用穿透将代理服务映射到公网中,这样也能访问。

最后

frp本身也是提供了socks5代理的功能的,是可以不需要用到ss5服务,但我是一开始先配置的ss5,用了一段时候后有需求才加上frp的。而且分开两个服务的话,也方便用不同的代理服务和穿透服务来互相搭配,比如用ss5服务+ngrok穿透,或者用其他的socks5代理服务。

扫码_搜索联合传播样式-白色版.png