Skip to content
This repository has been archived by the owner on Jun 27, 2024. It is now read-only.

Commit

Permalink
refactor: removed customLists, use customRanges instead
Browse files Browse the repository at this point in the history
chore: `deno task check`
  • Loading branch information
ivy committed Aug 19, 2023
1 parent 6428584 commit b54b9c6
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 87 deletions.
64 changes: 35 additions & 29 deletions ext/firewall.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,50 @@
import { createExtension } from "../mod.ts";
import { createExtension } from '../mod.ts'

let vpnList: string[];
let datacenterList: string[];
let customList: string[];
let vpnList: string[]
let datacenterList: string[]

type FirewallOptions = {
blockVPN?: boolean;
blockDatacenter?: boolean;
customRange?: string[];
/** a list of urls that return a list of ip ranges to block in plaintext separated by newlines */
customLists?: string[];
blockVPN?: boolean
blockDatacenter?: boolean
customRanges?: string[]
}

export const firewall = createExtension<FirewallOptions>({
async onPlugIn({settings: opts}) {
await update(opts);
// setInterval(() => {update(opts)}, 300000);
async onPlugIn() {
await update()
},
onRequest({ _: opts, app }) {
if (opts?.blockVPN && vpnList.find((range) => isIpInRange(app.ip, range))) {
return new Response(null, { status: 403 })
}
if (
opts?.blockDatacenter &&
datacenterList.find((range) => isIpInRange(app.ip, range))
) return new Response(null, { status: 403 })
if (
opts?.customRanges &&
opts.customRanges.find((range) => isIpInRange(app.ip, range))
) return new Response(null, { status: 403 })
},
onRequest({_: opts, app}) {
if (opts?.blockVPN && vpnList.find((range) => isIpInRange(app.ip, range))) return new Response(null, {status: 403});
if (opts?.blockDatacenter && datacenterList.find((range) => isIpInRange(app.ip, range))) return new Response(null, {status: 403});
if (opts?.customRange && opts.customRange.find((range) => isIpInRange(app.ip, range))) return new Response(null, {status: 403});
if (customList.find((range) => isIpInRange(app.ip, range))) return new Response(null, {status: 403});
}
})

async function update(args?: FirewallOptions) {
vpnList = (await (await fetch("https://cdn.jsdelivr.net/gh/X4BNet/lists_vpn/output/vpn/ipv4.txt")).text()).split('\n');
datacenterList = (await (await fetch("https://cdn.jsdelivr.net/gh/X4BNet/lists_vpn/output/datacenter/ipv4.txt")).text()).split('\n');
if (args?.customLists) customList = (await Promise.all(args.customLists.map((url) => fetch(url).then((res) => res.text())))).join('\n').split('\n');
async function update() {
vpnList = (await (await fetch(
'https://cdn.jsdelivr.net/gh/X4BNet/lists_vpn/output/vpn/ipv4.txt',
)).text()).split('\n')
datacenterList = (await (await fetch(
'https://cdn.jsdelivr.net/gh/X4BNet/lists_vpn/output/datacenter/ipv4.txt',
)).text()).split('\n')
}

function isIpInRange(ip: string, range: string) {
const [rangeIp, rangeMask] = range.split("/");
const rangeStart = ipToNumber(rangeIp) >>> 0;
const rangeEnd = rangeStart + ((1 << (32 - parseInt(rangeMask))) - 1);
const numIp = ipToNumber(ip);
return numIp >= rangeStart && numIp <= rangeEnd;
const [rangeIp, rangeMask] = range.split('/')
const rangeStart = ipToNumber(rangeIp) >>> 0
const rangeEnd = rangeStart + ((1 << (32 - parseInt(rangeMask))) - 1)
const numIp = ipToNumber(ip)
return numIp >= rangeStart && numIp <= rangeEnd
}

function ipToNumber(ip: string) {
return ip.split(".").reduce((acc, val) => (acc << 8) | parseInt(val), 0) >>> 0;
}
return ip.split('.').reduce((acc, val) => (acc << 8) | parseInt(val), 0) >>> 0
}
99 changes: 41 additions & 58 deletions test/ext/firewall.test.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,61 @@
import { assertEquals } from "../deps.ts";
import { assertEquals } from '../deps.ts'
import cheetah from '../../mod.ts'
import { firewall } from "../../ext/firewall.ts";
import { firewall } from '../../ext/firewall.ts'

Deno.test("ext/firewall", async (t) => {
await t.step("vpn", async (t) => {
const app = new cheetah({debug: true});
Deno.test('ext/firewall', async (t) => {
await t.step('vpn', async () => {
const app = new cheetah({ debug: true })

app.use(firewall({
blockVPN: true,
}));

const res = await app.fetch(new Request("http://localhost", {
headers: {
"cf-connecting-ip": "2.56.16.0",
},
}));

assertEquals(res.status, 403);
}))

const res = await app.fetch(
new Request('http://localhost', {
headers: {
'cf-connecting-ip': '2.56.16.0',
},
}),
)

assertEquals(res.status, 403)
})
})


Deno.test("datacenters", async () => {
const app = new cheetah({debug: true});
Deno.test('datacenters', async () => {
const app = new cheetah({ debug: true })

app.use(firewall({
blockDatacenter: true,
}));
}))

const res = await app.fetch(new Request("http://localhost", {
headers: {
"cf-connecting-ip": "1.12.32.0",
},
}));
const res = await app.fetch(
new Request('http://localhost', {
headers: {
'cf-connecting-ip': '1.12.32.0',
},
}),
)

assertEquals(res.status, 403);
});
assertEquals(res.status, 403)
})

Deno.test("customRange", async () => {
const app = new cheetah({debug: true});
Deno.test('customRanges', async () => {
const app = new cheetah({ debug: true })

app.use(firewall({
customRange: [
customRanges: [
'1.2.3.4/32',
],
}));
}))

const res = await app.fetch(new Request("http://localhost", {
headers: {
"cf-connecting-ip": "1.2.3.4",
},
}));

assertEquals(res.status, 403);
});

Deno.test("customLists", async () => {
const app = new cheetah({debug: true});

app.use(firewall({
customLists: ['https://gist.githubusercontent.com/not-ivy/bfdb8483df177b2415fdae8b58884029/raw/44b651679b22448375b762d058962173fa205ba4/ipv4ver1.txt', 'https://gist.githubusercontent.com/not-ivy/bfdb8483df177b2415fdae8b58884029/raw/44b651679b22448375b762d058962173fa205ba4/ipv4ver2.txt'],
}));

const res1 = await app.fetch(new Request("http://localhost", {
headers: {
"cf-connecting-ip": "210.43.83.54",
},
}));
const res2 = await app.fetch(new Request("http://localhost", {
headers: {
"cf-connecting-ip": "47.240.42.225",
},
}));
const res = await app.fetch(
new Request('http://localhost', {
headers: {
'cf-connecting-ip': '1.2.3.4',
},
}),
)

assertEquals(res1.status, 403);
assertEquals(res2.status, 403);
});
assertEquals(res.status, 403)
})

0 comments on commit b54b9c6

Please sign in to comment.