远程桌面是我每天都要用到的东西,临时在家远程公司电脑排查问题,又或者之前广州疫情,需要居家办公远程公司电脑工作。
远程工具其实有很多,如Todesk、TeamViewer、RustDesk、向日葵等,但我在用过之后都觉得这些不好用,远不如微软自带的远程桌面工具更好用,但这款远程工具却只支持局域网,而我又有在家远程公司电脑的需求,到后来我发现用代理和穿透…
简单来说,就是让处于局域网内网的服务,能够让公网访问到。在公司环境,一般都是整个公司的网络可能分配到公网IP,但内网用的都是局域网IP,经过一层NAT转换的;又或者家用宽带,一般都是整个大内网,并不会有公网IP,所以想要让内网的服务能够提供给外网访问,则需要用到内网穿透。
一般内网穿透,需要引入一台公网的服务器来实现数据包的转发,通过在公共网络上(如互联网)建立一个中转服务器,将来自私有网络的数据包转发到需要连接的设备上,从而实现设备之间的安全通信。像常用的工具有frp、ngrok等。
代理其实就是让别人帮你做某事。放在计算机的世界中,就是客户端在访问服务器时,中间引入了一层代理服务器,通过代理服务器来帮助客户端访问服务器。而这个代理服务器的存在位置,将区分是正向代理还是反向代理。
正向代理是代理客户端向互联网发起请求,这种方式主要可以隐藏客户端,可能多个客户端会通过一个代理服务器访问,而在服务器看来,只有代理服务器来访问,并不知道是哪个客户端发起的访问。
反向代理在互联网环境中,一般是存在于服务端这一端,用于隐藏服务器的真实位置,又或者为服务器提供负载均衡等作用。客户端并不知道自己访问的是哪个服务器。
可能会有人会疑问,已经有内网穿透了,直接访问穿透服务的端口也可以连接,但为什么还要再加一层代理呢?
是因为我的云服务器,部署了好多服务,如frp、portainer、web服务,mysql以及redis等,为此我可能需要为每个服务都开放一个端口到公网中,但本着服务器开放的端口越少越安全,所以我原来就做了一层反向代理,通过代理来访问这些服务,只需要开放代理服务一个端口,便可以直接访问我云服务器上的所有服务,而且用这种方式,我在文章后面还会提到其他的一些场景。
这里使用了ss5服务,到ss5官网下载最新的源码包,官方并没有提供docker版本的,docker仓库上都是个人开发者构建的镜像,而且我也不想ss5和docker绑定在一起,所以选择源码包安装。
ss5官网:http://ss5.sourceforge.net/
关于系统版本,我用的是centos 7,一直偏爱centos 7,centos 8也停止支持了,所以这里以centos 7为准。
# 安装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
主要是修改默认端口和添加账号访问,如果需要涉及其他安全策略,则可以查看官网的配置文档进行配置。
https://ss5.sourceforge.net/configuration.htm
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"
[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 - - - - -
[root@dsx ss5-3.8.9]# vi /etc/opt/ss5/ss5.passwd
user1 pwd2
# 添加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
# 设置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
[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
[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.pid
和Can'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这款软件来进行代理的连接。
下载地址:https://www.proxifier.com/download/ProxifierSetup.exe
安装后直接打开,需要先配置代理服务器,选择Profile->Proxy Servers进行服务器配置,输入上面配置的地址、端口、用户名和密码,可以点击Check进行验证看是否能连接,然后点击OK进行保存。
成功连接并保存后,需要配置代理规则,即配置哪些IP访问会走代理,哪一些不走代理。
代理服务是部署在云服务器上,我们通过代理访问云服务器时,可直接通过云服务器的内网地址来进行访问,因此在配置代理规则时,需要将访问云服务器内网地址的配置为走代理,其他地址均不拦截。依次点击Profile-> Proxification Rules。
新建一条代理规则,比如我的服务器内网地址是10.0.12.3,则需要点击**Add…**添加一条10.0.12.3的代理规则,走向上面配置的代理服务器。
保存后通过内网地址访问服务器上的服务,可以看到在服务器没开放其他端口时,也是可以访问到服务的。
要注意的是socks5并不是一种安全的协议,socks5协议中传输的数据都是明文的,哪怕是设置了连接验证,用户名和密码都是明文的,可以从下图抓包socks5数据包可以看出。
不过我觉得自己用的话也可以不用太担心这种情况,除非别人能够轻而易举抓取到你的数据包,你也可以通过限制访问ip,或者使用TLS证书来进行加密,确保安全性。
部署完ss5服务后,需要部署frp,将公司的电脑穿透到公网服务器上。
frp下载地址:https://github.com/fatedier/frp/releases
frp官网地址:https://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的子键值
客户端此时还需要运行frpc来连接frps服务端,还需要将frpc服务加入到系统服务中,并且可以开机自启动。我在github上找了一个很好用的frp管理器,内置了frpc,可以可图形化管理多份配置文件,还能将服务注册到系统服务中,下面附上github地址。
frp管理器:https://github.com/koho/frpmgr
frp管理器下载地址:https://github.com/koho/frpmgr/releases
将程序下载并安装后,新增一个配置,填入服务器的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代理服务。