mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-08-26 19:42:02 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c18b8d80e1 | |||
| 06ba0aff52 | |||
| 74e401d99c | |||
| 4995bca901 | |||
| 7299fd8762 | |||
| efbadde4ed |
@@ -455,8 +455,8 @@ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtow
|
||||
> 注意: netdisk-fast-download.service中的ExecStart的路径改为实际路径
|
||||
```shell
|
||||
cd ~
|
||||
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/v3.0.2/netdisk-fast-download-bin.zip
|
||||
unzip netdisk-fast-download-bin.zip
|
||||
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/v0.4.2/netdisk-fast-download-linux-amd64.zip
|
||||
unzip netdisk-fast-download.zip
|
||||
cd netdisk-fast-download
|
||||
bash service-install.sh
|
||||
```
|
||||
@@ -544,11 +544,22 @@ Core模块集成Vert.x实现类似spring的注解式路由API
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
## **免责声明**
|
||||
- 用户在使用本项目时,应自行承担风险,并确保其行为符合当地法律法规。开发者不对用户因使用本项目而导致的任何后果负责。
|
||||
|
||||
## 支持该项目
|
||||
开源不易,用爱发电,本项目长期维护如果觉得有帮助, 可以请作者喝杯咖啡, 感谢支持
|
||||
## **声明**
|
||||
|
||||
- 本项目**仅供个人学习与技术交流使用**,请勿用于商业用途或大规模滥用。
|
||||
- 所用接口均来自各网盘**官方开放平台**、官方公开接口及**已知开源项目**,仅解析用户主动提供的分享链接,**不涉及破解或绕过版权保护**。
|
||||
- 本项目**相当于自动化程序代替用户发起请求**,**不会提升或绕过任何会员权限**,也**不会突破网盘的限速策略**;我们**鼓励用户开通官方 VIP/SVIP**以获得更好的下载与加速体验。
|
||||
- 使用者应遵守各网盘服务商的**用户协议与使用条款**,以及所在地区的**法律法规**,违反所产生的后果自行承担。
|
||||
- **高频调用可能触发网盘风控**,导致**账号限流、封禁**或**来源 IP 被屏蔽**,请合理控制请求频率,避免高并发与批量请求。
|
||||
- 网盘接口调整、风控策略变更等因素可能导致功能失效,本项目**不对可用性与稳定性作任何担保**。
|
||||
- 开发者**不对**使用本项目产生的**任何直接或间接损失**(账号封禁、数据丢失、法律纠纷等)**承担责任**。
|
||||
- 开发者保留**随时修改本免责声明**的权利,恕不另行通知。
|
||||
- **下载、部署或使用本项目,即视为您已阅读并接受上述全部条款。**
|
||||
|
||||
|
||||
## 赞助该项目
|
||||
开源不易,用爱发电,本项目长期维护如果觉得有帮助, 可以请开发者[喝杯咖啡](https://blog.qaiu.top/archives/da-shang-zhuan-yong), 感谢支持。
|
||||
|
||||
本项目的服务器由林枫云提供赞助<br>
|
||||
</a>
|
||||
|
||||
@@ -382,9 +382,10 @@ public abstract class PanBase implements IPanTool, Closeable {
|
||||
log.error("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
||||
fail("响应gzip解压或JSON解析失败: {}", e.getMessage());
|
||||
} else {
|
||||
// 上游响应体可能来自内网探测目标,仅写日志,避免经 HTTP 500 回传给调用方
|
||||
String bodyPreview = responseBodyPreview(res);
|
||||
log.error("解析失败: json格式异常: {}", bodyPreview);
|
||||
fail("解析失败: json格式异常: {}", bodyPreview);
|
||||
fail("解析失败: json格式异常");
|
||||
}
|
||||
return JsonObject.of();
|
||||
}
|
||||
|
||||
@@ -111,7 +111,8 @@ public class Ce4Tool extends PanBase {
|
||||
private void requestShareDetail(String baseUrl, String key, String pwd, String path) {
|
||||
String shareApiUrl = baseUrl + SHARE_API_PATH + key;
|
||||
|
||||
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
||||
// 禁止跟随重定向:防止公网 host 302 到内网/元数据绕过 assertPublicHost
|
||||
HttpRequest<Buffer> httpRequest = clientNoRedirects.getAbs(shareApiUrl);
|
||||
if (pwd != null && !pwd.isEmpty()) {
|
||||
httpRequest.addQueryParam("password", pwd);
|
||||
}
|
||||
@@ -232,7 +233,7 @@ public class Ce4Tool extends PanBase {
|
||||
.put("uris", new JsonArray().add(filePath))
|
||||
.put("download", true);
|
||||
|
||||
clientSession.postAbs(fileUrlApi)
|
||||
clientNoRedirects.postAbs(fileUrlApi)
|
||||
.putHeader("Content-Type", "application/json")
|
||||
.sendJsonObject(requestBody)
|
||||
.onSuccess(res -> {
|
||||
|
||||
@@ -78,7 +78,8 @@ public class CeTool extends PanBase {
|
||||
private void tryV4Ping(String baseUrl, String key, String pwd) {
|
||||
String pingUrlV4 = baseUrl + PING_API_V4_PATH;
|
||||
|
||||
clientSession.getAbs(pingUrlV4).send().onSuccess(res -> {
|
||||
// 禁止跟随重定向:assertPublicHost 只校验初始 host,自动 30x 会绕过 SSRF 防护
|
||||
clientNoRedirects.getAbs(pingUrlV4).send().onSuccess(res -> {
|
||||
if (res.statusCode() == 200) {
|
||||
try {
|
||||
JsonObject json = asJson(res);
|
||||
@@ -108,7 +109,7 @@ public class CeTool extends PanBase {
|
||||
private void tryV3Ping(String baseUrl, String key, String pwd) {
|
||||
String pingUrlV3 = baseUrl + PING_API_V3_PATH;
|
||||
|
||||
clientSession.getAbs(pingUrlV3).send().onSuccess(res -> {
|
||||
clientNoRedirects.getAbs(pingUrlV3).send().onSuccess(res -> {
|
||||
if (res.statusCode() == 200) {
|
||||
try {
|
||||
JsonObject json = asJson(res);
|
||||
@@ -139,7 +140,7 @@ public class CeTool extends PanBase {
|
||||
*/
|
||||
private void verifyV3AndParse(String baseUrl, String key, String pwd) {
|
||||
String shareApiUrl = baseUrl + SHARE_API_PATH + key;
|
||||
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
||||
HttpRequest<Buffer> httpRequest = clientNoRedirects.getAbs(shareApiUrl);
|
||||
if (pwd != null && !pwd.isEmpty()) {
|
||||
httpRequest.addQueryParam("password", pwd);
|
||||
}
|
||||
@@ -175,7 +176,7 @@ public class CeTool extends PanBase {
|
||||
*/
|
||||
private void tryV4ShareApi(String baseUrl, String key, String pwd) {
|
||||
String shareApiUrl = baseUrl + "/api/v4/share/info/" + key;
|
||||
HttpRequest<Buffer> httpRequest = clientSession.getAbs(shareApiUrl);
|
||||
HttpRequest<Buffer> httpRequest = clientNoRedirects.getAbs(shareApiUrl);
|
||||
if (pwd != null && !pwd.isEmpty()) {
|
||||
httpRequest.addQueryParam("password", pwd);
|
||||
}
|
||||
@@ -291,7 +292,8 @@ public class CeTool extends PanBase {
|
||||
}
|
||||
|
||||
private void getDownURL(String shareApiUrl) {
|
||||
clientSession.putAbs(shareApiUrl)
|
||||
// PUT 默认不跟随重定向,但仍统一使用 no-redirect 客户端避免配置漂移
|
||||
clientNoRedirects.putAbs(shareApiUrl)
|
||||
.putHeader("Referer", shareLinkInfo.getShareUrl())
|
||||
.send().onSuccess(res -> {
|
||||
JsonObject jsonObject = asJson(res);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package cn.qaiu.parser;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* GHSA-997r-7xx2-p9x6 regression: Cloudreve generic parser must reject
|
||||
* hosts that resolve to loopback / private / link-local / metadata ranges
|
||||
* before any outbound request.
|
||||
*/
|
||||
public class AssertPublicHostTest {
|
||||
|
||||
@Test
|
||||
public void rejectsLoopbackAndPrivateHosts() throws Exception {
|
||||
String[] blocked = {
|
||||
"http://127.0.0.1.nip.io/s/poc",
|
||||
"http://localhost/s/poc",
|
||||
"http://10.0.0.1/s/poc",
|
||||
"http://192.168.1.1/s/poc",
|
||||
"http://172.16.0.1/s/poc",
|
||||
"http://169.254.169.254/s/poc",
|
||||
"http://[::1]/s/poc"
|
||||
};
|
||||
for (String raw : blocked) {
|
||||
try {
|
||||
PanBase.assertPublicHost(new URL(raw));
|
||||
fail("expected block for " + raw);
|
||||
} catch (IOException expected) {
|
||||
assertTrue(expected.getMessage().contains("不允许访问")
|
||||
|| expected.getMessage().contains("无法解析"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowsPublicHost() throws Exception {
|
||||
PanBase.assertPublicHost(new URL("https://example.com/s/demo"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user