Skip to content

Commit

Permalink
feat: support CIDR IP ranges in allowlist (DIYgod#14243)
Browse files Browse the repository at this point in the history
  • Loading branch information
josh authored Jan 15, 2024
1 parent 6780b96 commit ed8e195
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
25 changes: 23 additions & 2 deletions lib/middleware/access-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ const reject = (ctx) => {
throw Error('Authentication failed. Access denied.');
};

const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
const cidrPattern = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,2})/;

const ipInCidr = (cidr, ip) => {
const cidrMatch = cidr.match(cidrPattern);
const ipMatch = ip.match(ipv4Pattern);
if (!cidrMatch || !ipMatch) {
return false;
}
const subnetMask = parseInt(cidrMatch[2]);
const cidrIpBits = ipv4ToBitsring(cidrMatch[1]).substring(0, subnetMask);
const ipBits = ipv4ToBitsring(ip).substring(0, subnetMask);
return cidrIpBits === ipBits;
};

const ipv4ToBitsring = (ip) =>
ip
.split('.')
.map((part) => ('00000000' + parseInt(part).toString(2)).slice(-8))
.join('');

module.exports = async (ctx, next) => {
const ip = ctx.ips[0] || ctx.ip;
const requestPath = ctx.request.path;
Expand Down Expand Up @@ -39,13 +60,13 @@ module.exports = async (ctx, next) => {
}

if (config.allowlist) {
if (config.allowlist.find((item) => ip.includes(item) || requestPath.includes(item) || requestUA.includes(item))) {
if (config.allowlist.find((item) => ip.includes(item) || ipInCidr(item, ip) || requestPath.includes(item) || requestUA.includes(item))) {
return grant();
}
}

if (config.denylist) {
if (!config.denylist.find((item) => ip.includes(item) || requestPath.includes(item) || requestUA.includes(item))) {
if (!config.denylist.find((item) => ip.includes(item) || ipInCidr(item, ip) || requestPath.includes(item) || requestUA.includes(item))) {
return grant();
}
}
Expand Down
11 changes: 10 additions & 1 deletion test/middleware/access-control.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('access-control', () => {
it(`allowlist`, async () => {
const key = '1L0veRSSHub';
const code = md5('/test/2' + key);
process.env.ALLOWLIST = 'est/1,233.233.233.,white';
process.env.ALLOWLIST = 'est/1,233.233.233.,103.31.4.0/22,white';
process.env.ACCESS_KEY = key;
server = require('../../lib/index');
const request = supertest(server);
Expand All @@ -94,6 +94,15 @@ describe('access-control', () => {
const response22 = await request.get('/test/2').set('X-Forwarded-For', '233.233.233.233');
expect(response22.status).toBe(200);

const response221 = await request.get('/test/2').set('X-Forwarded-For', '103.31.4.0');
expect(response221.status).toBe(200);

const response222 = await request.get('/test/2').set('X-Forwarded-For', '103.31.7.255');
expect(response222.status).toBe(200);

const response223 = await request.get('/test/2').set('X-Forwarded-For', '103.31.8.0');
checkBlock(response223);

const response23 = await request.get('/test/2').set('user-agent', 'whiteua');
expect(response23.status).toBe(200);

Expand Down

0 comments on commit ed8e195

Please sign in to comment.