Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

安卓设备只有重启第一次可以成功解锁 #423

Closed
mzz2017 opened this issue Mar 9, 2020 · 31 comments
Closed

安卓设备只有重启第一次可以成功解锁 #423

mzz2017 opened this issue Mar 9, 2020 · 31 comments

Comments

@mzz2017
Copy link

mzz2017 commented Mar 9, 2020

环境

安卓设备 网易云V7.0.20最新版

linux网关,通过tproxy全局代理转发请求至8080端口。

启动参数为

docker run -d -p 8080:8080 --name unblock nondanee/unblockneteasemusic -p 8080:8081 -e https://music.163.com

描述问题

无论是全部代理,还是部分代理,在程序启动后的第一次点进歌单后可解锁歌曲,再次进入则变灰,随后无论如何都是灰色。

复现步骤

  1. 启动程序,进入网易云,进入歌单,成功解锁,等待5秒,退出歌单。

  2. 进入歌单,解锁失败。

  3. 进入歌单,解锁失败。

  4. 重启网易云,解锁失败。

  5. 重启程序。

  6. 进入歌单,解锁成功,等待5秒,退出歌单。

  7. 进入歌单,解锁失败。

  8. 重启网易云,解锁失败。

复现几率在70%左右。

各类设备情况

iOS设备解锁正常

Linux网关解锁正常

安卓设备解锁异常(安装证书后仍然异常)

@nondanee
Copy link
Owner

nondanee commented Mar 9, 2020

Android 端安装用户证书无效 #30 (comment)

我用 WLAN 代理无法复现

判断可能是 sni 没拦到,能 debug 的话把 sni 打印出来看一看

if (target.has(socket.sni) && !target.has(url.hostname)) {

linux网关,通过tproxy全局代理转发请求至8080端口。

这是 root 了吧?root 把用户证书改成系统证书试试

@mzz2017
Copy link
Author

mzz2017 commented Mar 9, 2020

步骤2的日志

...(begin)

TUNNEL > 59.111.239.61:443
TUNNEL > 59.111.179.213:443
TUNNEL > 59.111.239.61:443
url Url {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: '59.111.179.213:443',
  port: '443',
  hostname: '59.111.179.213',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'https://59.111.179.213:443/'
} sni: null
url Url {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: '59.111.239.61:443',
  port: '443',
  hostname: '59.111.239.61',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'https://59.111.239.61:443/'
} sni: null
url Url {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: '59.111.239.61:443',
  port: '443',
  hostname: '59.111.239.61',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'https://59.111.239.61:443/'
} sni: null
(end)

这是 root 了吧?root 把用户证书改成系统证书试试

archlinux的笔记本作为网关,用v2ray把相关流量都转发到8080端口。说来也巧,之前有些时候v2ray拦sni也没拦到。

@mzz2017
Copy link
Author

mzz2017 commented Mar 9, 2020

设备没有root,这个问题应该和证书没什么关系吧

@mzz2017
Copy link
Author

mzz2017 commented Mar 9, 2020

等待一段时间再次进入歌单偶然解锁成功日志:

TUNNEL > localhost:8081
TUNNEL > localhost:8081
TUNNEL > localhost:8081
TUNNEL > localhost:8080
MITM > interface3.music.163.com 
TUNNEL > localhost:8080
MITM > interface3.music.163.com 
TUNNEL > api.iplay.163.com:443
url Url {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: 'api.iplay.163.com:443',
  port: '443',
  hostname: 'api.iplay.163.com',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'https://api.iplay.163.com:443/'
} sni: api.iplay.163.com
MITM > interface3.music.163.com 
TUNNEL > localhost:8081
MITM > interface3.music.163.com 
TUNNEL > clientlog3.music.163.com:443
url Url {
  protocol: 'https:',
  slashes: true,
  auth: null,
  host: 'clientlog3.music.163.com:443',
  port: '443',
  hostname: 'clientlog3.music.163.com',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'https://clientlog3.music.163.com:443/'
} sni: clientlog3.music.163.com

@nondanee
Copy link
Owner

nondanee commented Mar 9, 2020

确实没 sni 啊 sni: null

下载 pac 文件打开看看里面有没有包含

59.111.239.61
59.111.179.213

没有的话手动加到 target.host 里

hook.target.host = new Set([

@mzz2017
Copy link
Author

mzz2017 commented Mar 9, 2020

有时步骤2连TUNNEL都没有……
我已经将http和tls流量都转发到8080了

@mzz2017
Copy link
Author

mzz2017 commented Mar 9, 2020

下载 pac 文件打开看看里面有没有包含

哪个地方的pac文件?

@nondanee
Copy link
Owner

nondanee commented Mar 9, 2020

这个问题和证书没有直接关系
但是如果证书被信任也能解决

如果主站 https API (music.163.com) 用域名访问是"正常"的
应该不会再尝试用 httpdns 查出来 ip 强制连接到指定 https API
就没有这些 TUNNEL > ip

@nondanee
Copy link
Owner

nondanee commented Mar 9, 2020

http://<Server Name:PORT>/proxy.pac

@mzz2017
Copy link
Author

mzz2017 commented Mar 9, 2020

确实在termux中curl -v https://music.163.com 后提示CA证书有问题。

function FindProxyForURL(url, host) {
    if (host == 'music.163.com' || host == 'interface.music.163.com' || host == 'interface3.music.163.com' || host == 'apm.music.163.com' || host == 'apm3.music.163.com' || host == '59.111.239.61' || host == '59.111.239.62' || host == '59.111.179.213' || host == '59.111.181.35' || host == '59.111.181.38' || host == '59.111.181.60' || host == '223.252.199.66' || host == '223.252.199.67' || host == '59.111.160.195' || host == '59.111.160.197' || host == '193.112.159.225' || host == '118.24.63.156' || host == '115.236.121.1' || host == '115.236.118.33' || host == '39.105.63.80' || host == '47.100.127.239' || host == '2407:ae80:200:1001::20' || host == '59.111.239.61' || host == '59.111.239.62' || host == '59.111.179.213') {
        return 'PROXY localhost:8080'
    }
    return 'DIRECT'
}

包含上述地址。

设系统代理后正常。

有可能有其他解决方案吗。

@nondanee
Copy link
Owner

nondanee commented Mar 9, 2020

不清楚,第二个端口不要开试试看吧

@mzz2017
Copy link
Author

mzz2017 commented Mar 9, 2020

不清楚,第二个端口不要开试试看吧

这会导致Linux设备异常,不过没关系,谢谢你的帮助。

@mzz2017 mzz2017 closed this as completed Mar 9, 2020
@mzz2017 mzz2017 reopened this Mar 10, 2020
@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

今天manjaro上也出现了这个问题,可能是网络变化(网络中断和恢复)导致的,重启docker容器就好了。

这个问题玄学在重启UnblockNeteaseMusic就会好,而不是重启网易云,安卓也是。

@nondanee
Copy link
Owner

我似乎好像知道是为什么了 😂

@nondanee
Copy link
Owner

好像也没什么问题

hook.target.host = new Set([

你把 hook.negotiate.before 这个整段去掉试一下吧
在这里会动态加 target,重启后会重置

@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

你把 hook.negotiate.before 这个整段去掉试一下吧
在这里会动态加 target,重启后会重置

仍然重启好一次。

@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

当时我应该是看到流量经过8080直接绕过了,因为直接打开music.163.com使用的是他原本的证书。

@nondanee
Copy link
Owner

麻烦用 curl 确认一下

export http_proxy=xxx
curl http://baidu.com

是内部网络挂了吗?或者端口 down 了?pac 还可以正常打开吗?

@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

现在不好复现那个时候的场景,我遇到之后再确认一下吧。

但现在安卓的那个问题是一直可以复现的。

@nondanee
Copy link
Owner

好👌

@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

问题已解决,将clientlog3.music.163.com屏蔽即可。

@nondanee
Copy link
Owner

好的,屏蔽 clientlog 会影响听歌记录,自己权衡一下
(感觉这个和重启没有太大关系)

@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

好的,屏蔽 clientlog 会影响听歌记录,自己权衡一下
(感觉这个和重启没有太大关系)

但实际上它确实奏效了。可以看到音源变灰之前请求了一次clientlog3,随后便似乎不再发送请求。

我看到他发往IP:443的请求,其Host也都是IP:443,似乎还是HTTP非TLS,且body为空,可以看出是一个无意义的GET请求,我没有逆向过不知道这段代码他想做什么。

如果你想复现并调试的话,可以在linux下使用v2ray作透明代理,v2ray配置相关流量转发到8080端口(可以参考docker-compose那个issue),并用电脑开热点,用安卓设备连接,无需填写代理,即可复现。

简单的有一些客户端帮助复现,比方说我在维护的V2RayA,以及Clash、Qv2ray等。

@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

一个好消息。

我将clientlog3.music.163.com加入hook.target.host后,同样解决了问题。

我猜测是否与x-napm-retry有关?

@nondanee
Copy link
Owner

复现和调试黑盒的意义不大,兜底的请求策略应该很复杂
一般情况下请求能拦截到即可,面面俱到也不太可能


target host 里之前有 clientlog,因为听歌记录的打点就保留了没拦截

x-napm-retry 会带上 retry 之前的出错信息,我给抹掉了,有多少作用不太清楚
(降级是我的期望行为不算错误,尽量不要给官方带来困扰)

@mzz2017
Copy link
Author

mzz2017 commented Mar 10, 2020

观察后发现MITM除了给clientlog3.music.163.com颁发了TLS证书以外没有任何修改,猜测网易云可能是在从clientlog3.music.163.com获得了可用的证书后,使得https降级不再进行,导致后续MITM失败。

@nondanee
Copy link
Owner

nondanee commented Mar 10, 2020

不是颁发证书,是导流到 https 端口上
我不可能自己处理二进制报文进行协商和握手
导流到 https 的端口后我只要处理 http 请求就可以了
https 端口和 http 端口共用一套 MITM 逻辑,也是可以修改的

问题应该在 keep-alive 上,之后的请求都使用了 clientlog 的那条 tcp 连接

@mzz2017
Copy link
Author

mzz2017 commented Mar 11, 2020

好的,屏蔽 clientlog 会影响听歌记录,自己权衡一下
(感觉这个和重启没有太大关系)

Hello, UnblockNeteaseMusic会对clientlog进行修改吗,为什么加入host会影响听歌记录呢

@nondanee
Copy link
Owner

nondanee commented Mar 11, 2020

不会修改,加入 host 会被拦截,拦截可能会导致请求失败
clientlog 是日志上报,重要性不高,不像业务接口那样有一系列降级兜底策略,类似 https 域名 > https IP > http ip > http 域名 .....
如果连接被阻断了 (不开 https 端口的情况),或者因为证书异常而请求失败,可能都不会触发降级请求第二次
这只是我看到的现象,可能只是个别请求是这样,可能你那边会重新请求,具体策略我不知道

@mzz2017
Copy link
Author

mzz2017 commented Mar 11, 2020

不会修改,加入 host 会被拦截,拦截可能会导致请求失败
clientlog 是日志上报,重要性不高,不像业务接口那样有一系列降级兜底策略,类似 https 域名 > https IP > http ip > http 域名 .....
如果连接被阻断了 (不开 https 端口的情况),或者因为证书异常而请求失败,可能都不会触发降级请求第二次
这只是我看到的现象,可能只是个别请求是这样,可能你那边会重新请求,具体策略我不知道

明白了,感谢解答。

我这里看到安卓设WLAN代理的情况下和拦截clientlog的情况是一样的,无法查看个人主页,说明应该是降级失败了。所以安卓这个代理方案一样会影响听歌记录。

@nondanee
Copy link
Owner

用户页确实是降级失败,#30 (comment) ,但无法查看不代表影响记录
听歌计数是在 clientlog 打点上报的
现在这样不会影响
你可以自己在安卓上测试听完以后有没有 +1
当然可能你把 clientlog 加入 target 也会 +1,那是最好的了 (具体策略我不知道,对不同客户端不同版本的影响也都不知道)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants