作为一个合格的程序员,应该抱着在哪里都要加班的理想。

为了在家调试方便,老高使用frp将自己放在公司的开发机器的ssh端口开放出来了,但是配置frp客户端的过程中总是出现下面的一句话:

2019/08/30 23:42:47 [W] [service.go:82] login to server failed: EOF
EOF

开始怀疑是frp的版本问题,于是客户端和服务端都换上了最新的版本,结果还是无法解决问题,继续尝试更换端口,问题依旧。

网上搜索一圈,发现遇到login to server failed: EOF问题的人还真不少,下面看看老高是如何解决的吧!

本地抓包

开启Wireshark,选择网卡,输入过滤规则:

tcp and ip.addr==xxx.xxx.220.109

wireshark 抓包

后面的那三个RST包很可疑,其中还有三个IRC协议的包,打开看一下,发现原来是认证数据。

{"version":"0.28.2","hostname":"","os":"darwin","arch":"amd64","user":"","privilege_key":"144fa23b09635f403ccd18","timestamp":1567119104,"run_id":"","pool_count":1}

服务端抓包

打开终端,输入命令

# xxxx 为frp监听端口
tcpdump -i eth0  port xxxx -n

23:57:54.041136 IP 180.167.229.162.64674 > xx.xx.xx.xx.PPPP: Flags [S], seq 2454088299, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 1598952560 ecr 0,sackOK,eol], length 0
23:57:54.041203 IP xx.xx.xx.xx.PPPP > 180.167.229.162.64674: Flags [S.], seq 2502814427, ack 2454088300, win 65160, options [mss 1460,sackOK,TS val 3508779989 ecr 1598952560,nop,wscale 6], length 0
23:57:54.171283 IP 180.167.229.162.64674 > xx.xx.xx.xx.PPPP: Flags [.], ack 1, win 2058, options [nop,nop,TS val 1598952691 ecr 3508779989], length 0
23:57:54.171670 IP 180.167.229.162.64674 > xx.xx.xx.xx.PPPP: Flags [P.], seq 1:13, ack 1, win 2058, options [nop,nop,TS val 1598952692 ecr 3508779989], length 12
23:57:54.171694 IP xx.xx.xx.xx.PPPP > 180.167.229.162.64674: Flags [.], ack 13, win 1018, options [nop,nop,TS val 3508780120 ecr 1598952692], length 0
23:57:54.171896 IP xx.xx.xx.xx.PPPP > 180.167.229.162.64674: Flags [P.], seq 1:13, ack 13, win 1018, options [nop,nop,TS val 3508780120 ecr 1598952692], length 12
23:57:54.172366 IP 180.167.229.162.64674 > xx.xx.xx.xx.PPPP: Flags [P.], seq 13:25, ack 1, win 2058, options [nop,nop,TS val 1598952692 ecr 3508779989], length 12
23:57:54.172391 IP 180.167.229.162.64674 > xx.xx.xx.xx.PPPP: Flags [R.], seq 25, ack 1, win 8224, length 0
23:57:54.301735 IP 180.167.229.162.64674 > xx.xx.xx.xx.PPPP: Flags [R.], seq 13, ack 1, win 8224, length 0
23:57:54.302089 IP 180.167.229.162.64674 > xx.xx.xx.xx.PPPP: Flags [R.], seq 13, ack 13, win 8224, length 0

好嘛,注意最后三个包,也是RST,而且方向刚好和我在本地抓包相反,很明显,这是受到了替身攻击!😄

解决

看来公司的防火墙应该是探测到了某些特征流量而触发了规则,导致frp认证的包被重置,于是服务端frp关闭了链接,而翻开源码,我们能看到再发送完认证信息后执行了ReadMsgInto方法,因为连接已经关闭,所以我们就得到了EOF错误!

回头再看wireshark的RST包之前的三个TCP包,很有可能是这一段明文数据暴露了frp,然后导致被防火墙封杀。

那么如何解决login to server failed: EOF的问题呢?

其实看了源代码就知道了,原来frp在v0.25.0版本后增加了一个客户端选项,支持了tls传输,也就是非对称加密,在frps初始化服务时,在已经为我们运行了一个简易的TLS服务,简直完美!

开启的办法很简单,在服务端客户端原来的[common]配置中加入tls_enable = true即可!

注意:服务端和客户端都要配置!

另一种解决办法

既然防火墙检测了我的tcp,那我换成udp行不行?

frp支持使用kcp作为底层的通讯协议,而kcp默认就是基于udp协议,废话不多说,赶紧试一试!

步骤(假设kcp的端口为7000):

  1. 服务端原来的[common]配置中加入kcp_bind_port = 7000,使其支持udp
  2. 客户端原来的[common]处加入protocol = kcp即可,注意端口一定要对上!

标签: tcp, frp, kcp

已有 19 条评论

  1. 太皇太后您有喜了 太皇太后您有喜了

    受益匪浅

  2. guihuashaoxaing guihuashaoxaing

    牛逼就完事了

  3. ersic ersic

    谢谢,解决了问题。

  4. 哈哈哈 哈哈哈

    niubi

  5. diave diave

    牛逼

  6. flightsong flightsong

    老哥,稳~

  7. 路人乙 路人乙

    老哥稳的,解决了。
    今天公司服务器卡死,重启了,重启之后内穿就不行了,疯狂报错EOF。
    加了tls就好了。
    感谢老哥

  8. 373Kice 373Kice

    太优秀了,我必须要顶一下

  9. 感谢感谢!原来如此! 感谢感谢!原来如此!

    感谢感谢!原来如此!,我说怎么家里 几台机子都没问题 公司的死活登陆不上

  10. 换成kcp真的解决了万恶的EOF,第一种方法我开了但好像也没有用。不知道是不是因为openwrt用的是26版本frp才不行。。

    1. 你可以抓包或者换端口试试,按理说第一种方法是可以的

      1. caizheng caizheng

        单独设置客户端不行!

        客户端和服务端都添加 tls 参数后, 解决!

        客户端版本: 0.32.0
        服务端版本: 0.32.0

添加新评论