feat!: allowlist & denylist (#13681)

* feat!: allowlist & denylist

* Update website/i18n/zh/docusaurus-plugin-content-docs/current/install/README.md

* Update website/i18n/zh/docusaurus-plugin-content-docs/current/install/README.md

* Update website/i18n/zh/docusaurus-plugin-content-docs/current/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* chore: revert

---------
This commit is contained in:
Henry Wang
2023-11-03 13:21:17 +00:00
committed by GitHub
parent 90026020a8
commit d6056e2dbc
7 changed files with 72 additions and 72 deletions

View File

@@ -85,8 +85,8 @@ const calculateValue = () => {
pass: envs.HTTP_BASIC_AUTH_PASS || 'passw0rd',
},
// access control
blacklist: envs.BLACKLIST && envs.BLACKLIST.split(','),
whitelist: envs.WHITELIST && envs.WHITELIST.split(','),
denylist: envs.DENYLIST && envs.DENYLIST.split(','),
allowlist: envs.ALLOWLIST && envs.ALLOWLIST.split(','),
allowLocalhost: envs.ALLOW_LOCALHOST,
accessKey: envs.ACCESS_KEY,
// logging

View File

@@ -15,7 +15,7 @@ module.exports = async (ctx, next) => {
const accessKey = ctx.query.key;
const accessCode = ctx.query.code;
const isControlled = config.accessKey || config.whitelist || config.blacklist;
const isControlled = config.accessKey || config.allowlist || config.denylist;
const allowLocalhost = config.allowLocalhost && (await isLocalhost(ip));
@@ -38,14 +38,14 @@ module.exports = async (ctx, next) => {
}
}
if (config.whitelist) {
if (config.whitelist.find((white) => ip.includes(white) || requestPath.includes(white) || requestUA.includes(white))) {
if (config.allowlist) {
if (config.allowlist.find((item) => ip.includes(item) || requestPath.includes(item) || requestUA.includes(item))) {
return grant();
}
}
if (config.blacklist) {
if (!config.blacklist.find((black) => ip.includes(black) || requestPath.includes(black) || requestUA.includes(black))) {
if (config.denylist) {
if (!config.denylist.find((item) => ip.includes(item) || requestPath.includes(item) || requestUA.includes(item))) {
return grant();
}
}

View File

@@ -6,7 +6,7 @@ const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
const baseUrl = 'https://ostudy.ynnedu.cn/';
const blacklist = ['ynnu-mv.html', 'https://chjiao.ynnu.edu.cn/zsgz/zsjz.htm', 'https://chjiao.ynnu.edu.cn/info/1006/1404.htm', 'https://chjiao.ynnu.edu.cn/zsgz/dksw.htm'];
const denylist = ['ynnu-mv.html', 'https://chjiao.ynnu.edu.cn/zsgz/zsjz.htm', 'https://chjiao.ynnu.edu.cn/info/1006/1404.htm', 'https://chjiao.ynnu.edu.cn/zsgz/dksw.htm'];
const { body } = await got(baseUrl);
const $index = cheerio.load(body);
ctx.state.data = {
@@ -16,7 +16,7 @@ module.exports = async (ctx) => {
// 顶部幻灯片抓取
Promise.all(
$index('div[carousel-item] > div')
.filter((_, element) => !blacklist.includes($index(element).find('a').attr('href')))
.filter((_, element) => !denylist.includes($index(element).find('a').attr('href')))
.map((_, element) => {
const $element = $index(element);
const $a = $element.find('a');
@@ -46,7 +46,7 @@ module.exports = async (ctx) => {
Promise.all(
cheerio
.load($index('#serviceInform-tpl').html())('.news-li:not(:last-child)')
.filter((_, element) => !blacklist.includes($index(element).find('a').attr('href')))
.filter((_, element) => !denylist.includes($index(element).find('a').attr('href')))
.map((_, element) => {
const $element = $index(element);
const $a = $element.find('a');

View File

@@ -1,5 +1,5 @@
const noFound = 'Auto: Route No Found';
const whiteListedUser = ['dependabot[bot]', 'pull[bot]']; // dependabot and downstream PR requested by pull[bot]
const allowedUser = ['dependabot[bot]', 'pull[bot]']; // dependabot and downstream PR requested by pull[bot]
module.exports = async ({ github, context, core }, body, number, sender) => {
core.debug(`sender: ${sender}`);
@@ -82,10 +82,10 @@ module.exports = async ({ github, context, core }, body, number, sender) => {
await updatePrState('open');
}
if (whiteListedUser.includes(sender)) {
core.info('PR created by a whitelisted user, passing');
if (allowedUser.includes(sender)) {
core.info('PR created by a allowed user, passing');
await removeLabel();
await addLabels(['Auto: whitelisted']);
await addLabels(['Auto: allowed']);
return;
} else {
core.debug('PR created by ' + sender);

View File

@@ -10,17 +10,17 @@ function checkBlock(response) {
afterEach(() => {
delete process.env.ACCESS_KEY;
delete process.env.BLACKLIST;
delete process.env.WHITELIST;
delete process.env.DENYLIST;
delete process.env.ALLOWLIST;
jest.resetModules();
server.close();
});
describe('access-control', () => {
it(`blacklist`, async () => {
it(`denylist`, async () => {
const key = '1L0veRSSHub';
const code = md5('/test/2' + key);
process.env.BLACKLIST = 'est/1,233.233.233.,black';
process.env.DENYLIST = 'est/1,233.233.233.,black';
process.env.ACCESS_KEY = key;
server = require('../../lib/index');
const request = supertest(server);
@@ -43,21 +43,21 @@ describe('access-control', () => {
const response23 = await request.get('/test/2').set('user-agent', 'blackua');
checkBlock(response23);
// wrong key/code, not on blacklist
// wrong key/code, not on denylist
const response311 = await request.get(`/test/2?key=wrong+${key}`);
expect(response311.status).toBe(200);
const response312 = await request.get(`/test/2?code=wrong+${code}`);
expect(response312.status).toBe(200);
// wrong key/code, on blacklist
// wrong key/code, on denylist
const response321 = await request.get(`/test/2?key=wrong+${key}`).set('X-Forwarded-For', '233.233.233.233');
checkBlock(response321);
const response322 = await request.get(`/test/2?code=wrong+${code}`).set('X-Forwarded-For', '233.233.233.233');
checkBlock(response322);
// right key/code, on blacklist
// right key/code, on denylist
const response331 = await request.get(`/test/2?key=${key}`).set('X-Forwarded-For', '233.233.233.233');
expect(response331.status).toBe(200);
@@ -65,10 +65,10 @@ describe('access-control', () => {
expect(response332.status).toBe(200);
});
it(`whitelist`, async () => {
it(`allowlist`, async () => {
const key = '1L0veRSSHub';
const code = md5('/test/2' + key);
process.env.WHITELIST = 'est/1,233.233.233.,white';
process.env.ALLOWLIST = 'est/1,233.233.233.,white';
process.env.ACCESS_KEY = key;
server = require('../../lib/index');
const request = supertest(server);
@@ -97,14 +97,14 @@ describe('access-control', () => {
const response23 = await request.get('/test/2').set('user-agent', 'whiteua');
expect(response23.status).toBe(200);
// wrong key/code, not on whitelist
// wrong key/code, not on allowlist
const response311 = await request.get(`/test/2?code=wrong+${code}`);
checkBlock(response311);
const response312 = await request.get(`/test/2?key=wrong+${key}`);
checkBlock(response312);
// wrong key/code, on whitelist
// wrong key/code, on allowlist
const response321 = await request.get(`/test/2?code=wrong+${code}`).set('X-Forwarded-For', '233.233.233.233');
expect(response321.status).toBe(200);

View File

@@ -638,15 +638,15 @@ For readers that do not support HTTP Basic authentication, please refer to [Acce
### Access Control Configuration
RSSHub supports access control via access key/code, whitelisting and blacklisting, enabling any will activate access control for all routes. `ALLOW_LOCALHOST: true` will grant access to all localhost IP addresses.
RSSHub supports access control via access key/code, allowlisting and denylisting, enabling any will activate access control for all routes. `ALLOW_LOCALHOST: true` will grant access to all localhost IP addresses.
#### White/blacklisting
#### Allowlisting/denylisting
- `WHITELIST`: the blacklist. When set, values in `BLACKLIST` are disregarded
- `ALLOWLIST`: the allowlist. When set, values in `DENYLIST` are disregarded
- `BLACKLIST`: the blacklist
- `DENYLIST`: the denylist
White/blacklisting support IP, route and UA as values, fuzzy matching. Use `,` as the delimiter to separate multiple values, eg: `WHITELIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
Allowlisting/denylisting support IP, route and UA as values, fuzzy matching. Use `,` as the delimiter to separate multiple values, eg: `ALLOWLIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
#### Access Key/Code
@@ -662,12 +662,12 @@ Access code is the md5 generated based on the access key + route, eg:
- Or using `key` directly, eg: `https://rsshub.app/qdaily/column/59?key=ILoveRSSHub`
See the relation between access key/code and white/blacklisting.
See the relation between access key/code and allowlist/denylisting.
| | Whitelisted | Blacklisted | Correct access key/code | Wrong access key/code | No access key/code |
| | Allowlist | Denylist | Correct access key/code | Wrong access key/code | No access key/code |
| ----------- | ----------- | ----------- | ----------------------- | --------------------- | ------------------ |
| Whitelisted | ✅ | ✅ | ✅ | ✅ | ✅ |
| Blacklisted | ✅ | ❌ | ✅ | ❌ | ❌ |
| Allowlist | ✅ | ✅ | ✅ | ✅ | ✅ |
| Denylist | ✅ | ❌ | ✅ | ❌ | ❌ |
### Logging Configurations
@@ -888,7 +888,7 @@ See docs of the specified route and `lib/config.js` for detailed information.
- pianyuan 全部路由:[注册地址](https://pianyuan.org)
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例: PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- Pixabay: [Documentation](https://pixabay.com/api/docs/)
@@ -1020,7 +1020,7 @@ See docs of the specified route and `lib/config.js` for detailed information.
- 网易云歌单及听歌排行
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值.
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值
- 微博 个人时间线路由:[申请地址](https://open.weibo.com/connect)
@@ -1030,11 +1030,11 @@ See docs of the specified route and `lib/config.js` for detailed information.
- 微博 自定义分组
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式:
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) (确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件)
2. 按下`F12`打开控制台,切换至`Network(网络)`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 (该情形下捕获到的请求路径应包含`/feed/group`)
4. 查看该请求的`Headers(请求头)`, 找到`Cookie`字段并复制内容
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) 确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件
2. 按下`F12`打开控制台,切换至`Network网络`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 该情形下捕获到的请求路径应包含`/feed/group`
4. 查看该请求的`Headers请求头`, 找到`Cookie`字段并复制内容
- 小宇宙:需要 App 登陆后抓包获取相应数据。
@@ -1054,5 +1054,5 @@ See docs of the specified route and `lib/config.js` for detailed information.
- 知乎用户关注时间线
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值.
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值.
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值

View File

@@ -27,7 +27,7 @@ sidebar: auto
默认推荐使用 `diygod/rsshub``diygod/rsshub:latest` 最新版镜像以获取最新路由。
`diygod/rsshub:latest` 存在问题时,可以使用以日期为标签的近期镜像临时使用,例如:
`diygod/rsshub:latest` 存在问题时,可以使用以日期为标签的近期镜像临时使用,例如
```bash
$ docker pull diygod/rsshub:2021-06-18
@@ -144,7 +144,7 @@ $ docker run -d --name rsshub -p 1200:1200 -e CACHE_EXPIRE=3600 -e GITHUB_ACCESS
## Ansible 部署
这个 Ansible playbook 包括了 RSSHub, Redis, browserless (依赖 Docker) 以及 Caddy 2
这个 Ansible playbook 包括了 RSSHub, Redis, browserless 依赖 Docker 以及 Caddy 2
目前只支持 Ubuntu 20.04
@@ -632,15 +632,15 @@ async function handleRequest(request) {
### 访问控制配置
RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行访问控制。开启任意选项将会激活全局访问控制,没有访问权限将会导致访问被拒绝。同时可以通过 `ALLOW_LOCALHOST: true` 赋予所有本地 IP 访问权限。
RSSHub 支持使用访问密钥 / 码,允许清单和拒绝清单三种方式进行访问控制。开启任意选项将会激活全局访问控制,没有访问权限将会导致访问被拒绝。同时可以通过 `ALLOW_LOCALHOST: true` 赋予所有本地 IP 访问权限。
#### 黑白名
#### 允许清单/拒绝清
- `WHITELIST`: 白名单,设置白名单后黑名单无效
- `ALLOWLIST`: 允许清单,设置允许清单后拒绝清单无效
- `BLACKLIST`: 黑名
- `DENYLIST`: 拒绝清
黑白名单支持 IP、路由和 UA模糊匹配设置多项时用英文逗号 `,` 隔开,例如 `WHITELIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
允许清单/拒绝清单支持 IP、路由和 UA模糊匹配设置多项时用英文逗号 `,` 隔开,例如 `ALLOWLIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
#### 访问密钥 / 码
@@ -656,13 +656,13 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 或使用访问密钥 `key` 直接访问所有路由,例如:`https://rsshub.app/qdaily/column/59?key=ILoveRSSHub`
访问密钥 / 码与黑白名单的访问控制关系如下:
访问密钥 / 码与允许清单/拒绝清单的访问控制关系如下:
| | 正确访问密钥 / 码 | 错误访问密钥 / 码 | 无访问密钥 / 码 |
| ---------- | ----------------- | ----------------- | --------------- |
| 在白名单中 | ✅ | ✅ | ✅ |
| 在黑名单中 | ✅ | ❌ | ❌ |
| 无黑白名单 | ✅ | ❌ | ❌ |
| 在允许清单中 | ✅ | ✅ | ✅ |
| 在拒绝清单中 | ✅ | ❌ | ❌ |
| 无允许清单/拒绝清单 | ✅ | ❌ | ❌ |
### 日志配置
@@ -785,7 +785,7 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- Discourse
- `DISCOURSE_CONFIG_{id}`: 一个 Discourse 驱动的论坛的配置信息, `id` 可自由设定为任意数字或字符串。值应形如`{"link":link,"key":key}`。其中:
- `DISCOURSE_CONFIG_{id}`: 一个 Discourse 驱动的论坛的配置信息, `id` 可自由设定为任意数字或字符串。值应形如`{"link":link,"key":key}`。其中
- `link`:论坛的链接。
- `key`访问论坛 API 的密钥,可参考 [此处代码](https://pastebin.com/YbLCgdWW) 以获取。需要确保有足够权限访问对应资源。
@@ -871,7 +871,7 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- pianyuan 全部路由:[注册地址](https://pianyuan.org)
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例: PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- pixiv 全部路由:[注册地址](https://accounts.pixiv.net/signup)
@@ -1011,7 +1011,7 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 网易云歌单及听歌排行
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值.
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值
- 微博 个人时间线路由:[申请地址](https://open.weibo.com/connect)
@@ -1021,11 +1021,11 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 微博 自定义分组
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式:
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) (确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件)
2. 按下`F12`打开控制台,切换至`Network(网络)`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 (该情形下捕获到的请求路径应包含`/feed/group`)
4. 查看该请求的`Headers(请求头)`, 找到`Cookie`字段并复制内容
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) 确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件
2. 按下`F12`打开控制台,切换至`Network网络`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 该情形下捕获到的请求路径应包含`/feed/group`
4. 查看该请求的`Headers请求头`, 找到`Cookie`字段并复制内容
- 小宇宙:需要 App 登陆后抓包获取相应数据。
@@ -1045,5 +1045,5 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 知乎用户关注时间线
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值.
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值.
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值