背景
最近,由于有远程访问局域网电脑的需要,于是想着搭建一个frp服务方便自己在家里访问公司电脑,或者在公司访问家里的电脑。这里记录一下整体的过程,一方面作为记录,另外一方面,在搭建的过程中配到部分问题,这里把解决方式记录下来,也可以给碰到相同问题的其他人一些帮助。
构想
个人搭建服务一般都是尽量减少暴露端口,因此,个人的基本设置基本上都是:
基本上就是把HTTP服务都藏在Nginx后面,然后将其他服务都加入到NginxProxyManager的网络中,保证HTTP服务都通过Nginx反向代理。
因此,在搭建frp服务的时候,个人坚持的是同样的原则,尽可能减少端口的暴露。
动手
frps配置
首先,在服务器上配置frps,下面是我frps的配置和docker-compose文件。
docker-compose.yml
version: '3.3'
services:
frps:
restart: always
volumes:
- ./etc/frp/frps.toml:/etc/frp/frps.toml
container_name: frps
image: snowdreamtech/frps
networks:
- nginxproxymanager_default
ports:
- 7000:7000
- 6001:6001
- 6002:6002
networks:
nginxproxymanager_default:
external: true
frps.toml
bindPort = 7000
token = "XXXXXXXXX"
# 日志配置
log.level = "trace"
# dashboard
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "ADMIN"
webServer.password = "ADMIN-PASSWORD"
整体来说,配置非常简单。不过,这里需要对Dashboard配置进行一些简单的说明。
Dashboard说明
一开始,我的配置文件是下面这样:
```toml
bindPort = 7000
# dashboard
webServer.port = 7500
webServer.user = "ADMIN"
webServer.password = "ADMIN-PASSWORD"
整体的内容同官网介绍的类似:
但是,个人发现一个问题:无论在nginx proxy manager中如何配置,都无法访问dashboard。后来排查后发现,如果不设置的话,其默认值为127.0.0.1,属于本地回环地址。其他docker访问其网络的时候,由于对于该容器来说属于外部网络,因此无法访问本地。因此,只需要修改其值为0.0.0.0后,其可以监听外部网络的数据后,既可以正常访问。
frpc配置
在个人电脑端,同样使用docker配置,个人的docker-compose文件和配置如下:
docker-compose.yml
version: '3'
services:
frpc:
restart: always
image: snowdreamtech/frpc
container_name: frpc
volumes:
- ./etc/frp/frpc.toml:/etc/frp/frpc.toml
#network_mode: host
ports:
- 7000:7000
networks:
- npm_default
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
npm_default:
external: true
frpc.toml
serverAddr = "SERVER-ADDRESS" # 服务器地址
serverPort = 7000 # 和服务器一样的端口
token = "TOKEN-THE-SAME-WITH-SERVER"
[[proxies]]
name = "ssh-home"
type = "tcp"
localIP = "host.docker.internal"
localPort = 22
remotePort = 6002
对于frpc的配置来说,主要有两个地方需要说明,这也是我排查了半天才找到原因的地方。
extra_hosts
这一句的作用是将docker网络的网关地址加入到host文件中,后面就可以在容器内使用host.docker.internal
来访问网关;localIP
的设定之所以是网关是因为需要将网络信息转发到主机的ssh中,这样才能实现远程的访问。
在这里简单说一下我碰到的问题和排查过程,有兴趣就继续看,没兴趣就可以直接跳过。
ssh无法访问问题
为了更好的说明问题,这里把具体碰到问题的表现截图放上来:
从图中来看,整体的表现就是使用ssh登录设备,报kex_exchange_identification
错误。单独从输出日志来看,会这个问题发生的原因是认证失败导致的。我谷歌也好、百度也罢,找了很久的信息,并没有找到该问题的合适解决方案。
为了解决这个问题,我做了以下实验:
- 检查内网电脑和服务器的链接,在执行该指令的时候,服务器所显示的日志是什么?
- 检查执行该指令的时候,电脑上sshd的输出内容是什么?再对比本地登录sshd的输出信息是什么?然后确认问题原因。
通过这两个部分的信息来帮助我查找和配查问题。
[!note]
整体来说,个人的思路是个人理解,frp扮演的角色应该是类似于v2ray的角色,实现的是网络的端口转发。ssh的数据包一定先发送给服务器的6002端口,再通过frps转发给frpc,再通过frpc转发给本地ssh。其整体链路如下图:
根据这个思路,把所有的日志登记都调整到输出最详细日志:
- 修改了frps的日志等级,因此可以看到上面的配置文件中
log.level = "trace"
这个信息。 - 修改了sshd的日志配置,修改
/etc/ssh/sshd_config
中LogLevel DEBUG3
然后执行远程登录指令,发现:
- frps的输出正常,但是会遇到快速的链接被关闭;
- 检查本机的sshd的日志输出,没有发现任何的日志输出。
根据这两个信息,个人做出以下推断:数据链路在frpc发送给本地ssh时中断了。因此,需要调整的配置时frpc中关于ssh的配置。在做完下面的修改后,EVERYTHING IS FINE!!!
localIP = "host.docker.internal" # 原来是127.0.0.1,但ssh服务在主机上,需要通过网关访问
后记
要解决问题,要从原理上入手!
评论区