const noCookiesFileName = '/var/lib/njs/cookies.txt'; const blockedHoursMS = 1 * 1000 * 60 * 60; const noCookieIPs = loadFile(noCookiesFileName); function updateFile(file: string, dataArray: string[]): void { try { fs.writeFileSync(file, dataArray.join('\n')); } catch (e) { // unable to write file } } function verifyJSCookie(r: NginxHTTPRequest): boolean { const cookies = r.headersIn.Cookie; const njsCookie = cookies && cookies .split(';') .map((v) => v.split('=')) .find((x) => x[0] === 'njs'); try { if (!njsCookie || njsCookie.length < 2) { // no njs cookie or wrong cookie array length const foundIP = noCookieIPs.find((ip: string) => ip.match(r.remoteAddress)); if (foundIP && Date.now() - parseInt(foundIP.split(':')[1]) <= blockedHoursMS) { return false; } else { const ipIndex = noCookieIPs.findIndex((item: string) => item === foundIP); if (ipIndex) { noCookieIPs.splice(ipIndex, 1); updateFile(noCookiesFileName, noCookieIPs); } return true; } } // njs cookie found, validate it const cookieValue = njsCookie && njsCookie[1]; if (cookieValue) { const [cookieTimestamp, cookiePayload] = cookieValue.split(':'); const requestSignature = `${r.headersIn['User-Agent']}${r.remoteAddress}${cookieTimestamp}`; const requestSignatureHmac = crypto.createHmac('sha256', topSecretKey); const requestSignatureHex = requestSignatureHmac.update(requestSignature).digest('hex'); return requestSignatureHex === cookiePayload; } return false; // if all fails - block the request } catch (e) { // something went wrong - fail open return true; } }