Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,41 @@ on:
jobs:
build:
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v2
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'adopt'
cache: maven
java-version: '21'
distribution: 'temurin' # 使用 Eclipse Temurin (AdoptOpenJDK 的继任者)
cache: 'maven'

- name: Cache Maven packages
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Build with Maven
run: mvn -B package -Dmaven.test.skip=true --file pom.xml

- name: Upload Linux distribution package
if: success()
uses: actions/upload-artifact@v4
with:
name: kkfileview-linux
path: server/target/*.tar.gz
retention-days: 7

- name: Upload Windows distribution package
if: success()
uses: actions/upload-artifact@v4
with:
name: kkfileview-windows
path: server/target/*.zip
retention-days: 7
170 changes: 170 additions & 0 deletions SECURITY_CONFIG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# kkFileView 安全配置指南

## ⚠️ 重要安全更新

从 4.4.0 之后版本开始,kkFileView 增强了安全性,默认拒绝所有未配置的外部文件预览请求,以防止 SSRF(服务器端请求伪造)攻击。

## 🔒 安全配置说明

### 1. 信任主机白名单配置(推荐)

`application.properties` 中配置允许预览的域名:

```properties
# 方式1:通过配置文件
trust.host = kkview.cn,yourdomain.com,cdn.example.com

# 方式2:通过环境变量
KK_TRUST_HOST=kkview.cn,yourdomain.com,cdn.example.com
```

**示例场景**
- 只允许预览来自 `oss.aliyuncs.com``cdn.example.com` 的文件
```properties
trust.host = oss.aliyuncs.com,cdn.example.com
```

### 2. 允许所有主机(不推荐,仅测试环境)

```properties
trust.host = *
```

⚠️ **警告**:此配置会允许访问任意外部地址,存在安全风险,仅应在测试环境使用!

### 3. 黑名单配置(高级)

禁止特定域名或内网地址:

```properties
# 禁止访问内网地址(强烈推荐)
not.trust.host = localhost,127.0.0.1,192.168.*,10.*,172.16.*,169.254.*

# 禁止特定恶意域名
not.trust.host = malicious-site.com,spam-domain.net
```

**优先级**:黑名单 > 白名单

### 4. Docker 环境配置

```bash
docker run -d \
-e KK_TRUST_HOST=yourdomain.com,cdn.example.com \
-e KK_NOT_TRUST_HOST=localhost,127.0.0.1 \
-p 8012:8012 \
keking/kkfileview:4.4.0
```

## 🛡️ 安全最佳实践

### ✅ 推荐配置

```properties
# 1. 明确配置信任主机白名单
trust.host = your-cdn.com,your-storage.com

# 2. 配置黑名单防止内网访问
not.trust.host = localhost,127.0.0.1,192.168.*,10.*,172.16.*

# 3. 禁用文件上传(生产环境)
file.upload.disable = true

# 4. 配置基础URL(使用反向代理时)
base.url = https://preview.yourdomain.com
```

### ❌ 不推荐配置

```properties
# 危险:允许所有主机访问
trust.host = *

# 危险:启用文件上传(生产环境)
file.upload.disable = false
```

## 🔍 配置验证

### 测试白名单是否生效

1. 配置白名单:
```properties
trust.host = kkview.cn
```

2. 尝试预览白名单内的文件:
```
http://localhost:8012/onlinePreview?url=https://kkview.cn/test.pdf
✅ 应该可以正常预览
```

3. 尝试预览白名单外的文件:
```
http://localhost:8012/onlinePreview?url=https://other-domain.com/test.pdf
❌ 应该被拒绝,显示"不信任的文件源"
```

### 测试黑名单是否生效

1. 配置黑名单:
```properties
not.trust.host = localhost,127.0.0.1
```

2. 尝试访问本地文件:
```
http://localhost:8012/getCorsFile?urlPath=http://127.0.0.1:8080/admin
❌ 应该被拒绝
```

## 📋 常见问题

### Q1: 升级后无法预览文件了?

**原因**:新版本默认拒绝未配置的主机。

**解决**:在配置文件中添加信任主机列表:
```properties
trust.host = your-file-server.com
```

### Q2: 如何临时恢复旧版本行为?

**不推荐**,但如果确实需要:
```properties
trust.host = *
```

### Q3: 配置了白名单但还是无法访问?

检查以下几点:
1. 域名是否完全匹配(区分大小写)
2. 是否配置了黑名单,黑名单优先级更高
3. 查看日志中的 WARNING 信息
4. 确认环境变量是否正确设置

### Q4: 如何允许子域名?

目前不支持通配符域名匹配,需要明确列出每个子域名:
```properties
trust.host = cdn.example.com,api.example.com,storage.example.com
```

## 🚨 安全事件响应

如果发现可疑的预览请求:

1. 检查日志文件,搜索 "拒绝访问主机" 关键字
2. 确认 `trust.host` 配置是否合理
3. 检查是否有异常的网络请求
4. 如发现攻击行为,及时更新黑名单配置

## 📞 获取帮助

- GitHub Issues: https://github.com/kekingcn/kkFileView/issues
- Gitee Issues: https://gitee.com/kekingcn/file-online-preview/issues

---

**安全提示**:定期检查和更新信任主机列表,遵循最小权限原则。
22 changes: 18 additions & 4 deletions server/src/main/config/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,25 @@ cache.clean.cron = ${KK_CACHE_CLEAN_CRON:0 0 3 * * ?}
#提供预览服务的地址,默认从请求url读,如果使用nginx等反向代理,需要手动设置
#base.url = https://file.keking.cn
base.url = ${KK_BASE_URL:default}
#信任站点,多个用','隔开,设置了之后,会限制只能预览来自信任站点列表的文件,默认不限制
#trust.host = kkview.cn

# ========== 安全配置(重要)==========
# 信任站点白名单配置,多个用','隔开
# ⚠️ 安全提示:为防止SSRF攻击,强烈建议配置信任主机白名单
# ⚠️ 如果不配置,系统将默认拒绝所有外部文件预览请求
#
# 配置示例:
# trust.host = kkview.cn,yourdomain.com,cdn.example.com
#
# 如果需要允许所有域名(不推荐,仅用于测试环境),请设置为:
# trust.host = *
#
# 当前配置:
trust.host = ${KK_TRUST_HOST:default}
#不信任站点,多个用','隔开,设置了之后,会限制来自不信任站点列表的文件,默认不限制
#not.trust.host = kkview.cn

# 不信任站点黑名单配置,多个用','隔开
# 黑名单优先级高于白名单,设置后将禁止预览来自这些站点的文件
# 建议配置:禁止访问内网地址和本地地址
# not.trust.host = localhost,127.0.0.1,0.0.0.0,192.168.*,10.*,172.16.*
not.trust.host= ${KK_NOT_TRUST_HOST:default}
#文本类型,默认如下,可自定义添加
simText = ${KK_SIMTEXT:txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd}
Expand Down
3 changes: 2 additions & 1 deletion server/src/main/java/cn/keking/config/ConfigConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ private static CopyOnWriteArraySet<String> getHostValue(String trustHost) {
if (DEFAULT_VALUE.equalsIgnoreCase(trustHost)) {
return new CopyOnWriteArraySet<>();
} else {
String[] trustHostArray = trustHost.toLowerCase().split(",");
// 去除空格并转小写
String[] trustHostArray = trustHost.toLowerCase().replaceAll("\\s+", "").split(",");
return new CopyOnWriteArraySet<>(Arrays.asList(trustHostArray));
}
}
Expand Down
14 changes: 13 additions & 1 deletion server/src/main/java/cn/keking/web/filter/TrustHostFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,25 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
}

public boolean isNotTrustHost(String host) {
// 如果配置了黑名单,优先检查黑名单
if (CollectionUtils.isNotEmpty(ConfigConstants.getNotTrustHostSet())) {
return ConfigConstants.getNotTrustHostSet().contains(host);
}

// 如果配置了白名单,检查是否在白名单中
if (CollectionUtils.isNotEmpty(ConfigConstants.getTrustHostSet())) {
// 支持通配符 * 表示允许所有主机
if (ConfigConstants.getTrustHostSet().contains("*")) {
logger.debug("允许所有主机访问(通配符模式): {}", host);
return false;
}
return !ConfigConstants.getTrustHostSet().contains(host);
}
return false;

// 安全加固:默认拒绝所有未配置的主机(防止SSRF攻击)
// 如果需要允许所有主机,请在配置文件中明确设置 trust.host = *
logger.warn("未配置信任主机列表,拒绝访问主机: {},请在配置文件中设置 trust.host 或 KK_TRUST_HOST 环境变量", host);
return true;
}

@Override
Expand Down