Add support for Custom CloudFlare challenge

EbookParadijs, Film-Paleis, MuziekFabriek and Puur-Hollands
This commit is contained in:
ngosang 2022-01-30 21:32:16 +01:00
parent fdd1d245f4
commit bb7e82e6c4
2 changed files with 93 additions and 60 deletions

View File

@ -9,16 +9,27 @@ import log from "../services/log";
const BAN_SELECTORS = ['.text-gray-600']; const BAN_SELECTORS = ['.text-gray-600'];
const CHALLENGE_SELECTORS = [ const CHALLENGE_SELECTORS = [
'#trk_jschal_js', '.ray_id', '.attack-box', '#cf-please-wait', // CloudFlare '#trk_jschal_js', '.ray_id', '.attack-box', '#cf-please-wait', // CloudFlare
'#link-ddg' // DDoS-GUARD '#link-ddg', // DDoS-GUARD
'td.info #js_info' // Custom CloudFlare for EbookParadijs, Film-Paleis, MuziekFabriek and Puur-Hollands
]; ];
const CAPTCHA_SELECTORS = ['input[name="cf_captcha_kind"]']; const CAPTCHA_SELECTORS = ['input[name="cf_captcha_kind"]'];
export default async function resolveChallenge(url: string, page: Page, response: Response): Promise<Response> { export default async function resolveChallenge(url: string, page: Page, response: Response): Promise<Response> {
// look for challenge and return fast if not detected // look for challenge and return fast if not detected
if (response.headers().server && let cfDetected = response.headers().server && response.headers().server.startsWith('cloudflare');
response.headers().server.startsWith('cloudflare') && if (cfDetected) {
(response.status() == 403 || response.status() == 503)) { if (response.status() == 403 || response.status() == 503) {
cfDetected = true; // Defected CloudFlare and DDoS-GUARD
} else if (response.headers().vary && response.headers().vary.trim() == 'Accept-Encoding,User-Agent' &&
response.headers()['content-encoding'] && response.headers()['content-encoding'].trim() == 'br') {
cfDetected = true; // Detected Custom CloudFlare for EbookParadijs, Film-Paleis, MuziekFabriek and Puur-Hollands
} else {
cfDetected = false;
}
}
if (cfDetected) {
log.info('Cloudflare detected'); log.info('Cloudflare detected');
} else { } else {
log.info('Cloudflare not detected'); log.info('Cloudflare not detected');
@ -29,10 +40,8 @@ export default async function resolveChallenge(url: string, page: Page, response
throw new Error('Cloudflare has blocked this request. Probably your IP is banned for this site, check in your web browser.') throw new Error('Cloudflare has blocked this request. Probably your IP is banned for this site, check in your web browser.')
} }
let selectorFound = false;
if (response.status() > 400) {
// find Cloudflare selectors // find Cloudflare selectors
let selectorFound = false;
let selector: string = await findAnySelector(page, CHALLENGE_SELECTORS) let selector: string = await findAnySelector(page, CHALLENGE_SELECTORS)
if (selector) { if (selector) {
selectorFound = true; selectorFound = true;
@ -95,12 +104,6 @@ export default async function resolveChallenge(url: string, page: Page, response
log.debug(`No challenge element detected.`) log.debug(`No challenge element detected.`)
} }
} else {
// some sites use cloudflare but there is no challenge
log.debug(`Javascript challenge not detected. Status code: ${response.status()}`);
selectorFound = true;
}
// check for CAPTCHA challenge // check for CAPTCHA challenge
if (await findAnySelector(page, CAPTCHA_SELECTORS)) { if (await findAnySelector(page, CAPTCHA_SELECTORS)) {
log.info('CAPTCHA challenge detected'); log.info('CAPTCHA challenge detected');

View File

@ -16,6 +16,7 @@ const cfUrl = "https://pirateiro.com/torrents/?search=harry";
const cfCaptchaUrl = "https://idope.se" const cfCaptchaUrl = "https://idope.se"
const cfBlockedUrl = "https://www.torrentmafya.org/table.php" const cfBlockedUrl = "https://www.torrentmafya.org/table.php"
const ddgUrl = "https://www.erai-raws.info/feed/?type=magnet"; const ddgUrl = "https://www.erai-raws.info/feed/?type=magnet";
const ccfUrl = "https://www.muziekfabriek.org";
beforeAll(async () => { beforeAll(async () => {
// Init session // Init session
@ -198,6 +199,35 @@ describe("Test '/v1' path", () => {
expect(cfCookie.length).toBeGreaterThan(10) expect(cfCookie.length).toBeGreaterThan(10)
}); });
test("Cmd 'request.get' should return OK with Custom CloudFlare JS", async () => {
const payload = {
"cmd": "request.get",
"url": ccfUrl
}
const response: Response = await request(app).post("/v1").send(payload);
expect(response.statusCode).toBe(200);
const apiResponse: V1ResponseSolution = response.body;
expect(apiResponse.status).toBe("ok");
expect(apiResponse.message).toBe("");
expect(apiResponse.startTimestamp).toBeGreaterThan(1000);
expect(apiResponse.endTimestamp).toBeGreaterThan(apiResponse.startTimestamp);
expect(apiResponse.version).toBe(version);
const solution = apiResponse.solution;
expect(solution.url).toContain(ccfUrl)
expect(solution.status).toBe(200);
expect(Object.keys(solution.headers).length).toBeGreaterThan(0)
expect(solution.response).toContain("<html><head>")
expect(Object.keys(solution.cookies).length).toBeGreaterThan(0)
expect(solution.userAgent).toContain("Firefox/")
const cfCookie: string = (solution.cookies as any[]).filter(function(cookie) {
return cookie.name == "ct_anti_ddos_key";
})[0].value
expect(cfCookie.length).toBeGreaterThan(10)
});
test("Cmd 'request.get' should return OK with 'cookies' param", async () => { test("Cmd 'request.get' should return OK with 'cookies' param", async () => {
const payload = { const payload = {
"cmd": "request.get", "cmd": "request.get",